From d16a1f62ff751a567924ee1a28371fc0f9b238ac Mon Sep 17 00:00:00 2001 From: Armin Date: Thu, 7 Mar 2019 15:22:34 +0100 Subject: [PATCH] Refactoring + adding helmet for some basic security --- package.json | 3 +- src/activitypub/ActivityPub.js | 33 +---- src/activitypub/NitroDataSource.js | 10 +- .../routes/{webfinger.js => webFinger.js} | 0 src/activitypub/utils/activity.js | 38 ++++-- src/graphql-schema.js | 55 ++++---- src/seed/factories/index.js | 28 ++-- src/server.js | 2 + test/features/world.js | 2 +- yarn.lock | 123 +++++++++++++++++- 10 files changed, 201 insertions(+), 93 deletions(-) rename src/activitypub/routes/{webfinger.js => webFinger.js} (100%) diff --git a/package.json b/package.json index 85dfac6a2..d876b77d1 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/activitypub/ActivityPub.js b/src/activitypub/ActivityPub.js index 4bdbc9563..9cbf5b52e 100644 --- a/src/activitypub/ActivityPub.js +++ b/src/activitypub/ActivityPub.js @@ -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') } diff --git a/src/activitypub/NitroDataSource.js b/src/activitypub/NitroDataSource.js index 20339ec62..d43dc40a6 100644 --- a/src/activitypub/NitroDataSource.js +++ b/src/activitypub/NitroDataSource.js @@ -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 } } diff --git a/src/activitypub/routes/webfinger.js b/src/activitypub/routes/webFinger.js similarity index 100% rename from src/activitypub/routes/webfinger.js rename to src/activitypub/routes/webFinger.js diff --git a/src/activitypub/utils/activity.js b/src/activitypub/utils/activity.js index afe13dfca..00a91813d 100644 --- a/src/activitypub/utils/activity.js +++ b/src/activitypub/utils/activity.js @@ -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')) diff --git a/src/graphql-schema.js b/src/graphql-schema.js index bdf72c0a0..5ddf08492 100644 --- a/src/graphql-schema.js +++ b/src/graphql-schema.js @@ -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)}`) + } + } } } } diff --git a/src/seed/factories/index.js b/src/seed/factories/index.js index 752ae3369..d9bbd700c 100644 --- a/src/seed/factories/index.js +++ b/src/seed/factories/index.js @@ -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 = {}) => { diff --git a/src/server.js b/src/server.js index 5867e6952..10fdf291c 100644 --- a/src/server.js +++ b/src/server.js @@ -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')) diff --git a/test/features/world.js b/test/features/world.js index 9a27bd154..1b96e0761 100644 --- a/test/features/world.js +++ b/test/features/world.js @@ -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 diff --git a/yarn.lock b/yarn.lock index 05299ad6e..52fb19cde 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"