* Update to helmet 5

* Disable cross-origin-embedder-policy

* Update helmet.js

* Update helmet.js

* Add CORS on get / options

* Update helmet.js

* Update helmet.js

* Update helmet.js

* Update helmet.js

* Revert "Update helmet.js"

This reverts commit 61ad2fb641ca16a31bf148164c395f2ba91e1734.

* Open up github domains

* Include self

* Update helmet.js

* Update helmet.js
This commit is contained in:
Kevin Heis 2022-06-14 14:43:25 -07:00 коммит произвёл GitHub
Родитель 6c7319a90d
Коммит 71fedb1f31
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 118 добавлений и 119 удалений

Просмотреть файл

@ -1,5 +0,0 @@
import cors from 'cors'
export default cors({
origin: '*',
methods: ['GET', 'HEAD'],
})

Просмотреть файл

@ -1,81 +0,0 @@
import helmet from 'helmet'
import isArchivedVersion from '../lib/is-archived-version.js'
import versionSatisfiesRange from '../lib/version-satisfies-range.js'
// This module defines a Content Security Policy (CSP) to disallow
// inline scripts and content from untrusted sources.
const { contentSecurityPolicy } = helmet
const AZURE_STORAGE_URL = 'githubdocs.azureedge.net'
const isDev = process.env.NODE_ENV === 'development'
export default function csp(req, res, next) {
const csp = {
directives: {
defaultSrc: ["'none'"],
prefetchSrc: ["'self'"],
connectSrc: [
"'self'",
// When doing local dev, especially in Safari, you need to add `ws:`
// which NextJS uses for the hot module reloading.
isDev && 'ws:',
].filter(Boolean),
fontSrc: ["'self'", 'data:', AZURE_STORAGE_URL],
imgSrc: [
"'self'",
'data:',
'github.githubassets.com',
AZURE_STORAGE_URL,
'placehold.it',
'*.githubusercontent.com',
'github.com',
],
objectSrc: ["'self'"],
scriptSrc: [
"'self'",
// For use during development only! This allows us to use a performant webpack devtool setting (eval)
// https://webpack.js.org/configuration/devtool/#devtool
isDev && "'unsafe-eval'",
].filter(Boolean),
frameSrc: [
// exceptions for GraphQL Explorer
'https://graphql.github.com/',
isDev && 'http://localhost:3000', // development env
'https://www.youtube-nocookie.com',
].filter(Boolean),
styleSrc: ["'self'", "'unsafe-inline'"],
childSrc: [
"'self'", // exception for search in deprecated GHE versions
],
},
}
const { requestedVersion } = isArchivedVersion(req)
// Exception for deprecated Enterprise docs (Node.js era)
if (
versionSatisfiesRange(requestedVersion, '<=2.19') &&
versionSatisfiesRange(requestedVersion, '>2.12')
) {
csp.directives.scriptSrc.push(
"'unsafe-eval'",
"'unsafe-inline'",
'http://www.google-analytics.com',
'https://ssl.google-analytics.com'
)
csp.directives.connectSrc.push('https://www.google-analytics.com')
csp.directives.imgSrc.push(
'http://www.google-analytics.com',
'https://ssl.google-analytics.com'
)
}
// Exception for search in deprecated Enterprise docs <=2.12 (static site era)
if (versionSatisfiesRange(requestedVersion, '<=2.12')) {
csp.directives.scriptSrc.push("'unsafe-inline'")
}
return contentSecurityPolicy(csp)(req, res, next)
}

91
middleware/helmet.js Normal file
Просмотреть файл

@ -0,0 +1,91 @@
import helmet from 'helmet'
import { cloneDeep } from 'lodash-es'
import isArchivedVersion from '../lib/is-archived-version.js'
import versionSatisfiesRange from '../lib/version-satisfies-range.js'
const isDev = process.env.NODE_ENV === 'development'
const AZURE_STORAGE_URL = 'githubdocs.azureedge.net'
const GITHUB_DOMAINS = [
"'self'",
'github.com',
'*.github.com',
'*.githubusercontent.com',
'*.githubassets.com',
]
const DEFAULT_OPTIONS = {
crossOriginResourcePolicy: true,
crossOriginEmbedderPolicy: false, // doesn't work with youtube
referrerPolicy: {
policy: 'strict-origin-when-cross-origin',
},
// This module defines a Content Security Policy (CSP) to disallow
// inline scripts and content from untrusted sources.
contentSecurityPolicy: {
directives: {
defaultSrc: ["'none'"],
prefetchSrc: ["'self'"],
// When doing local dev, especially in Safari, you need to add `ws:`
// which NextJS uses for the hot module reloading.
connectSrc: ["'self'", isDev && 'ws:'].filter(Boolean),
fontSrc: ["'self'", 'data:', AZURE_STORAGE_URL],
imgSrc: [...GITHUB_DOMAINS, 'data:', AZURE_STORAGE_URL, 'placehold.it'],
objectSrc: ["'self'"],
// For use during development only!
// `unsafe-eval` allows us to use a performant webpack devtool setting (eval)
// https://webpack.js.org/configuration/devtool/#devtool
scriptSrc: ["'self'", isDev && "'unsafe-eval'"].filter(Boolean),
frameSrc: [
...GITHUB_DOMAINS,
isDev && 'http://localhost:3000',
'https://www.youtube-nocookie.com',
].filter(Boolean),
frameAncestors: [...GITHUB_DOMAINS],
styleSrc: ["'self'", "'unsafe-inline'"],
childSrc: ["'self'"], // exception for search in deprecated GHE versions
},
},
}
const NODE_DEPRECATED_OPTIONS = cloneDeep(DEFAULT_OPTIONS)
const { directives: ndDirs } = NODE_DEPRECATED_OPTIONS.contentSecurityPolicy
ndDirs.scriptSrc.push(
"'unsafe-eval'",
"'unsafe-inline'",
'http://www.google-analytics.com',
'https://ssl.google-analytics.com'
)
ndDirs.connectSrc.push('https://www.google-analytics.com')
ndDirs.imgSrc.push('http://www.google-analytics.com', 'https://ssl.google-analytics.com')
const STATIC_DEPRECATED_OPTIONS = cloneDeep(DEFAULT_OPTIONS)
STATIC_DEPRECATED_OPTIONS.contentSecurityPolicy.directives.scriptSrc.push("'unsafe-inline'")
const defaultHelmet = helmet(DEFAULT_OPTIONS)
const nodeDeprecatedHelmet = helmet(NODE_DEPRECATED_OPTIONS)
const staticDeprecatedHelmet = helmet(STATIC_DEPRECATED_OPTIONS)
export default function helmetMiddleware(req, res, next) {
// Enable CORS
if (['GET', 'OPTIONS'].includes(req.method)) {
res.set('access-control-allow-origin', '*')
}
// Determine version for exceptions
const { requestedVersion } = isArchivedVersion(req)
// Exception for deprecated Enterprise docs (Node.js era)
if (
versionSatisfiesRange(requestedVersion, '<=2.19') &&
versionSatisfiesRange(requestedVersion, '>2.12')
) {
return nodeDeprecatedHelmet(req, res, next)
}
// Exception for search in deprecated Enterprise docs <=2.12 (static site era)
if (versionSatisfiesRange(requestedVersion, '<=2.12')) {
return staticDeprecatedHelmet(req, res, next)
}
return defaultHelmet(req, res, next)
}

Просмотреть файл

@ -9,9 +9,7 @@ import abort from './abort.js'
import timeout from './timeout.js'
import morgan from 'morgan'
import datadog from './connect-datadog.js'
import cors from './cors.js'
import helmet from 'helmet'
import csp from './csp.js'
import helmet from './helmet.js'
import cookieParser from './cookie-parser.js'
import csrf from './csrf.js'
import handleCsrfErrors from './handle-csrf-errors.js'
@ -208,17 +206,7 @@ export default function (app) {
app.use(instrument(handleNextDataPath, './handle-next-data-path'))
// *** Security ***
app.use(cors)
app.use(
helmet({
// Override referrerPolicy to match the browser's default: "strict-origin-when-cross-origin".
// Helmet now defaults to "no-referrer", which is a problem for our archived assets proxying.
referrerPolicy: {
policy: 'strict-origin-when-cross-origin',
},
})
)
app.use(csp) // Must come after helmet
app.use(helmet)
app.use(cookieParser) // Must come before csrf
app.use(express.json()) // Must come before csrf

42
package-lock.json сгенерированный
Просмотреть файл

@ -35,7 +35,7 @@
"hast-util-select": "^5.0.1",
"hast-util-to-string": "^2.0.0",
"hastscript": "^7.0.2",
"helmet": "^4.6.0",
"helmet": "^5.1.0",
"highlight.js": "11.4.0",
"highlightjs-curl": "^1.3.0",
"highlightjs-graphql": "^1.0.2",
@ -6916,13 +6916,19 @@
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"node_modules/caniuse-lite": {
"version": "1.0.30001294",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001294.tgz",
"integrity": "sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
}
"version": "1.0.30001352",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz",
"integrity": "sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
}
]
},
"node_modules/capital-case": {
"version": "1.0.4",
@ -11039,11 +11045,11 @@
}
},
"node_modules/helmet": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz",
"integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-5.1.0.tgz",
"integrity": "sha512-klsunXs8rgNSZoaUrNeuCiWUxyc+wzucnEnFejUg3/A+CaF589k9qepLZZ1Jehnzig7YbD4hEuscGXuBY3fq+g==",
"engines": {
"node": ">=10.0.0"
"node": ">=12.0.0"
}
},
"node_modules/hexoid": {
@ -28109,9 +28115,9 @@
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"caniuse-lite": {
"version": "1.0.30001294",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001294.tgz",
"integrity": "sha512-LiMlrs1nSKZ8qkNhpUf5KD0Al1KCBE3zaT7OLOwEkagXMEDij98SiOovn9wxVGQpklk9vVC/pUSqgYmkmKOS8g=="
"version": "1.0.30001352",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz",
"integrity": "sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA=="
},
"capital-case": {
"version": "1.0.4",
@ -31284,9 +31290,9 @@
}
},
"helmet": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.6.0.tgz",
"integrity": "sha512-HVqALKZlR95ROkrnesdhbbZJFi/rIVSoNq6f3jA/9u6MIbTsPh3xZwihjeI5+DO/2sOV6HMHooXcEOuwskHpTg=="
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-5.1.0.tgz",
"integrity": "sha512-klsunXs8rgNSZoaUrNeuCiWUxyc+wzucnEnFejUg3/A+CaF589k9qepLZZ1Jehnzig7YbD4hEuscGXuBY3fq+g=="
},
"hexoid": {
"version": "1.0.0",

Просмотреть файл

@ -37,7 +37,7 @@
"hast-util-select": "^5.0.1",
"hast-util-to-string": "^2.0.0",
"hastscript": "^7.0.2",
"helmet": "^4.6.0",
"helmet": "^5.1.0",
"highlight.js": "11.4.0",
"highlightjs-curl": "^1.3.0",
"highlightjs-graphql": "^1.0.2",