зеркало из https://github.com/github/docs.git
Update to helmet 5 (#28488)
* 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:
Родитель
6c7319a90d
Коммит
71fedb1f31
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
Загрузка…
Ссылка в новой задаче