Refactoring + adding helmet for some basic security

This commit is contained in:
Armin 2019-03-07 15:22:34 +01:00
parent ea2f6b7811
commit d16a1f62ff
10 changed files with 201 additions and 93 deletions

View File

@ -11,7 +11,7 @@
"start": "node dist/",
"dev": "nodemon --exec babel-node src/",
"dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/index.js",
"lint": "eslint src --config .eslintrc.js",
"lint": "eslint src --config .eslintrc.js --fix",
"test": "nyc --reporter=text-lcov yarn test:jest",
"test:cypress": "run-p --race test:before:*",
"test:before:server": "cross-env GRAPHQL_URI=http://localhost:4123 GRAPHQL_PORT=4123 babel-node src/ 2> /dev/null",
@ -57,6 +57,7 @@
"graphql-shield": "~5.3.0",
"graphql-tag": "~2.10.1",
"graphql-yoga": "~1.17.4",
"helmet": "^3.15.1",
"jsonwebtoken": "~8.5.0",
"linkifyjs": "~2.1.8",
"lodash": "~4.17.11",

View File

@ -8,19 +8,14 @@ import {
sendAcceptActivity,
sendRejectActivity
} from './utils/activity'
import cluster from 'cluster'
import os from 'os'
import request from 'request'
import as from 'activitystrea.ms'
import NitroDataSource from './NitroDataSource'
import router from './routes'
import dotenv from 'dotenv'
import express from 'express'
import http from 'http'
import { resolve } from 'path'
import Collections from './Collections'
const debug = require('debug')('ea')
const numCPUs = os.cpus().length
let activityPub = null
@ -39,30 +34,10 @@ export default class ActivityPub {
const port = process.env.ACTIVITYPUB_PORT
activityPub = new ActivityPub(process.env.ACTIVITYPUB_DOMAIN || 'localhost', port || 4100)
if (server) {
// integrated into "server" express framework
server.express.set('ap', activityPub)
server.express.use(router)
debug('ActivityPub middleware added to the express service')
} else {
// standalone clustered ActivityPub service
if (cluster.isMaster) {
debug(`master with pid = ${process.pid} is running`)
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
cluster.on('exit', (worker, code, signal) => {
debug(`worker ${worker.process.pid} died with code ${code} and signal ${signal}`)
})
} else {
const app = express()
app.set('ap', activityPub)
app.use(router)
http.createServer(app).listen(port, () => {
debug(`ActivityPub express service listening on port ${port}`)
})
}
}
// integrated into "server" express framework
server.express.set('ap', activityPub)
server.express.use(router)
debug('ActivityPub middleware added to the express service')
} else {
debug('ActivityPub middleware already added to the express service')
}

View File

@ -9,7 +9,7 @@ import {
createOrderedCollectionPage
} from './utils/collection'
import {
createArticleActivity,
createArticleObject,
isPublicAddressed
} from './utils/activity'
import crypto from 'crypto'
@ -221,6 +221,7 @@ export default class NitroDataSource {
query: gql`
query {
User(slug:"${slug}") {
actorId
contributions {
id
title
@ -242,8 +243,8 @@ export default class NitroDataSource {
const outboxCollection = createOrderedCollectionPage(slug, 'outbox')
outboxCollection.totalItems = posts.length
await Promise.all(
posts.map((post) => {
outboxCollection.orderedItems.push(createArticleActivity(post.content, slug, post.id, post.createdAt))
posts.map(async (post) => {
outboxCollection.orderedItems.push(await createArticleObject(post.activityId, post.objectId, post.content, extractNameFromId(post.id), post.id, post.createdAt))
})
)
@ -335,11 +336,10 @@ export default class NitroDataSource {
}
const title = postObject.summary ? postObject.summary : postObject.content.split(' ').slice(0, 5).join(' ')
const postId = extractIdFromActivityId(postObject.id)
const activityId = extractIdFromActivityId(activity.id)
let result = await this.client.mutate({
mutation: gql`
mutation {
CreatePost(content: "${postObject.content}", contentExcerpt: "${trunc(postObject.content, 120)}", title: "${title}", id: "${postId}", activityId: "${activityId}") {
CreatePost(content: "${postObject.content}", contentExcerpt: "${trunc(postObject.content, 120)}", title: "${title}", id: "${postId}", objectId: "${postObject.id}", activityId: "${activity.id}") {
id
}
}

View File

@ -1,10 +1,12 @@
import crypto from 'crypto'
import { activityPub } from '../ActivityPub'
import { signAndSend, throwErrorIfApolloErrorOccurred } from './index'
import crypto from 'crypto'
import as from 'activitystrea.ms'
import { signAndSend } from './index'
import gql from 'graphql-tag'
const debug = require('debug')('ea:utils:activity')
export function createNoteActivity (text, name, id, published) {
export function createNoteObject (text, name, id, published) {
const createUuid = crypto.randomBytes(16).toString('hex')
return {
@ -23,25 +25,43 @@ export function createNoteActivity (text, name, id, published) {
}
}
export function createArticleActivity (text, name, id, published) {
const createUuid = crypto.randomBytes(16).toString('hex')
export async function createArticleObject (activityId, objectId, text, name, id, published) {
const actorId = await getActorId(name)
return {
'@context': 'https://www.w3.org/ns/activitystreams',
'id': `https://${activityPub.domain}/activitypub/users/${name}/status/${createUuid}`,
'id': `${activityId}`,
'type': 'Create',
'actor': `https://${activityPub.domain}/activitypub/users/${name}`,
'actor': `${actorId}`,
'object': {
'id': `https://${activityPub.domain}/activitypub/users/${name}/status/${id}`,
'id': `${objectId}`,
'type': 'Article',
'published': published,
'attributedTo': `https://${activityPub.domain}/activitypub/users/${name}`,
'attributedTo': `${actorId}`,
'content': text,
'to': 'https://www.w3.org/ns/activitystreams#Public'
}
}
}
export async function getActorId (name) {
const result = await activityPub.dataSource.client.query({
query: gql`
query {
User(slug: "${name}") {
actorId
}
}
`
})
throwErrorIfApolloErrorOccurred(result)
if (Array.isArray(result.data.User) && result.data.User[0]) {
return result.data.User[0].actorId
} else {
throw Error(`No user with name: ${name}`)
}
}
export function sendAcceptActivity (theBody, name, targetDomain, url) {
as.accept()
.id(`https://${activityPub.domain}/activitypub/users/${name}/status/` + crypto.randomBytes(16).toString('hex'))

View File

@ -6,6 +6,8 @@ import uuid from 'uuid/v4'
import { fixUrl } from './middleware/fixImageUrlsMiddleware'
import { AuthenticationError } from 'apollo-server'
import { neo4jgraphql } from 'neo4j-graphql-js'
import { activityPub } from './activitypub/ActivityPub'
import as from 'activitystrea.ms'
/*
import as from 'activitystrea.ms'
import request from 'request'
@ -174,14 +176,15 @@ export const resolvers = {
debug(`user = ${JSON.stringify(ctx.user, null, 2)}`)
const session = ctx.driver.session()
const author = await session.run(
'MATCH (author:User {id: $userId}), (post:Post {id: $postId}) ' +
'MATCH (author:User {slug: $slug}), (post:Post {id: $postId}) ' +
'MERGE (post)<-[:WROTE]-(author) ' +
'RETURN author', {
userId: ctx.user.id,
slug: ctx.user.slug,
postId: result.id
})
debug(`author = ${JSON.stringify(author, null, 2)}`)
/* if (Array.isArray(author.records) && author.records.length > 0) {
// debug(`result = ${JSON.stringify(author, null, 2)}`)
debug(`actorId = ${author.records[0]._fields[0].properties.actorId}`)
if (Array.isArray(author.records) && author.records.length > 0) {
const actorId = author.records[0]._fields[0].properties.actorId
const createActivity = await new Promise((resolve, reject) => {
as.create()
@ -195,36 +198,22 @@ export const resolvers = {
.publishedNow()
.attributedTo(`${actorId}`)
).prettyWrite((err, doc) => {
if (err) {
reject(err)
} else {
debug(doc)
const parsedDoc = JSON.parse(doc)
parsedDoc.send = true
resolve(JSON.stringify(parsedDoc))
}
})
if (err) {
reject(err)
} else {
debug(doc)
const parsedDoc = JSON.parse(doc)
parsedDoc.send = true
resolve(JSON.stringify(parsedDoc))
}
})
})
session.close()
// try sending post via ActivityPub
await new Promise((resolve) => {
const url = new URL(actorId)
request(`${url.origin}/activitypub/inbox`, {
method: 'POST',
headers: {
'Content-Type': 'application/activity+json'
},
body: createActivity
}, (err) => {
if (err) {
debug(`error = ${JSON.stringify(err, null, 2)}`)
resolve(err)
}
resolve(null)
})
})
return result
} */
try {
await activityPub.sendActivity(createActivity)
} catch (e) {
debug(`error sending post activity = ${JSON.stringify(e, null, 2)}`)
}
}
}
}
}

View File

@ -1,14 +1,14 @@
import { GraphQLClient, request } from 'graphql-request'
import { getDriver } from '../../bootstrap/neo4j'
import createBadge from './badges.js'
import createUser from './users.js'
import createBadge from './badges.js'
import createUser from './users.js'
import createOrganization from './organizations.js'
import createPost from './posts.js'
import createComment from './comments.js'
import createCategory from './categories.js'
import createTag from './tags.js'
import createReport from './reports.js'
import createPost from './posts.js'
import createComment from './comments.js'
import createCategory from './categories.js'
import createTag from './tags.js'
import createReport from './reports.js'
export const seedServerHost = 'http://127.0.0.1:4001'
@ -25,14 +25,14 @@ const authenticatedHeaders = async ({ email, password }, host) => {
}
}
const factories = {
'Badge': createBadge,
'User': createUser,
'Badge': createBadge,
'User': createUser,
'Organization': createOrganization,
'Post': createPost,
'Comment': createComment,
'Category': createCategory,
'Tag': createTag,
'Report': createReport
'Post': createPost,
'Comment': createComment,
'Category': createCategory,
'Tag': createTag,
'Report': createReport
}
export const cleanDatabase = async (options = {}) => {

View File

@ -12,6 +12,7 @@ import { getDriver } from './bootstrap/neo4j'
import passport from 'passport'
import jwtStrategy from './jwt/strategy'
import jwt from 'jsonwebtoken'
import helmet from 'helmet'
dotenv.config()
// check env and warn
@ -66,6 +67,7 @@ const createServer = (options) => {
const server = new GraphQLServer(Object.assign({}, defaults, options))
passport.use('jwt', jwtStrategy(driver))
server.express.use(helmet())
server.express.use(passport.initialize())
server.express.use(express.static('public'))

View File

@ -5,7 +5,7 @@ const debug = require('debug')('ea:test:world')
class CustomWorld {
constructor () {
// webfinger.feature
// webFinger.feature
this.lastResponses = []
this.lastContentType = null
this.lastInboxUrl = null

123
yarn.lock
View File

@ -1789,6 +1789,11 @@ camelcase@^5.0.0:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42"
integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==
camelize@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/camelize/-/camelize-1.0.0.tgz#164a5483e630fa4321e5af07020e531831b2609b"
integrity sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=
caniuse-lite@^1.0.30000912:
version "1.0.30000916"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000916.tgz#3428d3f529f0a7b2bfaaec65e796037bdd433aab"
@ -2053,6 +2058,11 @@ content-disposition@0.5.2:
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4"
integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ=
content-security-policy-builder@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/content-security-policy-builder/-/content-security-policy-builder-2.0.0.tgz#8749a1d542fcbe82237281ea9f716ce68b394dd2"
integrity sha512-j+Nhmj1yfZAikJLImCvPJFE29x/UuBi+/MWqggGGc515JKaZrjuei2RhULJmy0MsstW3E3htl002bwmBNMKr7w==
content-type@~1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
@ -2261,6 +2271,11 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
dasherize@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dasherize/-/dasherize-2.0.0.tgz#6d809c9cd0cf7bb8952d80fc84fa13d47ddb1308"
integrity sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=
data-urls@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe"
@ -2369,6 +2384,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
depd@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
depd@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
@ -2412,6 +2432,11 @@ diff@^3.0.0:
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
dns-prefetch-control@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz#60ddb457774e178f1f9415f0cabb0e85b0b300b2"
integrity sha1-YN20V3dOF48flBXwyrsOhbCzALI=
doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
@ -2475,6 +2500,11 @@ domutils@^1.5.1:
dom-serializer "0"
domelementtype "1"
dont-sniff-mimetype@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz#5932890dc9f4e2f19e5eb02a20026e5e5efc8f58"
integrity sha1-WTKJDcn04vGeXrAqIAJuXl78j1g=
dot-prop@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
@ -2716,7 +2746,7 @@ eslint-plugin-import@~2.16.0:
read-pkg-up "^2.0.0"
resolve "^1.9.0"
eslint-plugin-jest@~22.3.0:
eslint-plugin-jest@^22.3.0:
version "22.3.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.3.0.tgz#a10f10dedfc92def774ec9bb5bfbd2fb8e1c96d2"
integrity sha512-P1mYVRNlOEoO5T9yTqOfucjOYf1ktmJ26NjwjH8sxpCFQa6IhBGr5TpKl3hcAAT29hOsRJVuMWmTsHoUVo9FoA==
@ -2920,6 +2950,11 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
expect-ct@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/expect-ct/-/expect-ct-0.1.1.tgz#de84476a2dbcb85000d5903737e9bc8a5ba7b897"
integrity sha512-ngXzTfoRGG7fYens3/RMb6yYoVLvLMfmsSllP/mZPxNHgFq41TmPSLF/nLY7fwoclI2vElvAmILFWGUYqdjfCg==
expect@^24.1.0:
version "24.1.0"
resolved "https://registry.yarnpkg.com/expect/-/expect-24.1.0.tgz#88e73301c4c785cde5f16da130ab407bdaf8c0f2"
@ -3047,6 +3082,11 @@ fb-watchman@^2.0.0:
dependencies:
bser "^2.0.0"
feature-policy@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/feature-policy/-/feature-policy-0.2.0.tgz#22096de49ab240176878ffe2bde2f6ff04d48c43"
integrity sha512-2hGrlv6efG4hscYVZeaYjpzpT6I2OZgYqE2yDUzeAcKj2D1SH0AsEzqJNXzdoglEddcIXQQYop3lD97XpG75Jw==
figures@2.0.0, figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
@ -3184,6 +3224,11 @@ fragment-cache@^0.2.1:
dependencies:
map-cache "^0.2.2"
frameguard@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/frameguard/-/frameguard-3.0.0.tgz#7bcad469ee7b96e91d12ceb3959c78235a9272e9"
integrity sha1-e8rUae57lukdEs6zlZx4I1qScuk=
fresh@0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@ -3610,6 +3655,47 @@ he@0.5.0:
resolved "https://registry.yarnpkg.com/he/-/he-0.5.0.tgz#2c05ffaef90b68e860f3fd2b54ef580989277ee2"
integrity sha1-LAX/rvkLaOhg8/0rVO9YCYknfuI=
helmet-crossdomain@0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/helmet-crossdomain/-/helmet-crossdomain-0.3.0.tgz#707e2df930f13ad61f76ed08e1bb51ab2b2e85fa"
integrity sha512-YiXhj0E35nC4Na5EPE4mTfoXMf9JTGpN4OtB4aLqShKuH9d2HNaJX5MQoglO6STVka0uMsHyG5lCut5Kzsy7Lg==
helmet-csp@2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/helmet-csp/-/helmet-csp-2.7.1.tgz#e8e0b5186ffd4db625cfcce523758adbfadb9dca"
integrity sha512-sCHwywg4daQ2mY0YYwXSZRsgcCeerUwxMwNixGA7aMLkVmPTYBl7gJoZDHOZyXkqPrtuDT3s2B1A+RLI7WxSdQ==
dependencies:
camelize "1.0.0"
content-security-policy-builder "2.0.0"
dasherize "2.0.0"
platform "1.3.5"
helmet@^3.15.1:
version "3.15.1"
resolved "https://registry.yarnpkg.com/helmet/-/helmet-3.15.1.tgz#2c80d1a59138b6f23929605afca4b1c88b3298ec"
integrity sha512-hgoNe/sjKlKNvJ3g9Gz149H14BjMMWOCmW/DTXl7IfyKGtIK37GePwZrHNfr4aPXdKVyXcTj26RgRFbPKDy9lw==
dependencies:
depd "2.0.0"
dns-prefetch-control "0.1.0"
dont-sniff-mimetype "1.0.0"
expect-ct "0.1.1"
feature-policy "0.2.0"
frameguard "3.0.0"
helmet-crossdomain "0.3.0"
helmet-csp "2.7.1"
hide-powered-by "1.0.0"
hpkp "2.0.0"
hsts "2.1.0"
ienoopen "1.0.0"
nocache "2.0.0"
referrer-policy "1.1.0"
x-xss-protection "1.1.0"
hide-powered-by@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/hide-powered-by/-/hide-powered-by-1.0.0.tgz#4a85ad65881f62857fc70af7174a1184dccce32b"
integrity sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=
hoek@5.x.x:
version "5.0.4"
resolved "https://registry.yarnpkg.com/hoek/-/hoek-5.0.4.tgz#0f7fa270a1cafeb364a4b2ddfaa33f864e4157da"
@ -3637,6 +3723,16 @@ hosted-git-info@^2.1.4:
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047"
integrity sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==
hpkp@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/hpkp/-/hpkp-2.0.0.tgz#10e142264e76215a5d30c44ec43de64dee6d1672"
integrity sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=
hsts@2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/hsts/-/hsts-2.1.0.tgz#cbd6c918a2385fee1dd5680bfb2b3a194c0121cc"
integrity sha512-zXhh/DqgrTXJ7erTN6Fh5k/xjMhDGXCqdYN3wvxUvGUQvnxcFfUd8E+6vLg/nk3ss1TYMb+DhRl25fYABioTvA==
html-encoding-sniffer@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8"
@ -3710,6 +3806,11 @@ ieee754@^1.1.4:
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b"
integrity sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA==
ienoopen@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/ienoopen/-/ienoopen-1.0.0.tgz#346a428f474aac8f50cf3784ea2d0f16f62bda6b"
integrity sha1-NGpCj0dKrI9QzzeE6i0PFvYr2ms=
ignore-by-default@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
@ -5243,6 +5344,11 @@ no-case@^2.2.0:
dependencies:
lower-case "^1.1.1"
nocache@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.0.0.tgz#202b48021a0c4cbde2df80de15a17443c8b43980"
integrity sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=
node-fetch@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5"
@ -5863,6 +5969,11 @@ pkginfo@~0.4.0:
resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.4.1.tgz#b5418ef0439de5425fc4995042dced14fb2a84ff"
integrity sha1-tUGO8EOd5UJfxJlQQtztFPsqhP8=
platform@1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/platform/-/platform-1.3.5.tgz#fb6958c696e07e2918d2eeda0f0bc9448d733444"
integrity sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==
pn@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb"
@ -6160,6 +6271,11 @@ reasoner@2.0.0:
vocabs-rdfs "^0.11.1"
vocabs-xsd "^0.11.1"
referrer-policy@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.1.0.tgz#35774eb735bf50fb6c078e83334b472350207d79"
integrity sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=
regenerate-unicode-properties@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-7.0.0.tgz#107405afcc4a190ec5ed450ecaa00ed0cafa7a4c"
@ -7668,6 +7784,11 @@ ws@^6.0.0:
dependencies:
async-limiter "~1.0.0"
x-xss-protection@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/x-xss-protection/-/x-xss-protection-1.1.0.tgz#4f1898c332deb1e7f2be1280efb3e2c53d69c1a7"
integrity sha512-rx3GzJlgEeZ08MIcDsU2vY2B1QEriUKJTSiNHHUIem6eg9pzVOr2TL3Y4Pd6TMAM5D5azGjcxqI62piITBDHVg==
xdg-basedir@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4"