Security Headers (#2736)

* feat: added more security headers

* fix: added option to disable forcing SSL

* fix: linting
This commit is contained in:
Wyatt Johnson
2019-12-03 21:47:36 +00:00
committed by GitHub
parent 9618e5dab1
commit a396efef0d
4 changed files with 201 additions and 3 deletions
+160
View File
@@ -3730,6 +3730,15 @@
"@types/serve-static": "*"
}
},
"@types/express-enforces-ssl": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/express-enforces-ssl/-/express-enforces-ssl-1.1.1.tgz",
"integrity": "sha512-TGLJv2jZs5E26lAqLMmcsqPJi1F5SxEsKbqdyAyYa3sicanX29ZP/bVW+1M3q1/fshMvQhGaPxql8IV7sbTh4A==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/express-jwt": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.34.tgz",
@@ -3798,6 +3807,15 @@
"@types/koa": "*"
}
},
"@types/helmet": {
"version": "0.0.45",
"resolved": "https://registry.npmjs.org/@types/helmet/-/helmet-0.0.45.tgz",
"integrity": "sha512-PsLZI1NqKpXvsMZxh66xAZtpKiTeW+swY8a8LnCNSBbM/mvwU41P3BYoEqkJM9RbITPsq4uhIH0NkIsL9fzPbg==",
"dev": true,
"requires": {
"@types/express": "*"
}
},
"@types/html-minifier": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-3.5.2.tgz",
@@ -7890,6 +7908,11 @@
"quick-lru": "^1.0.0"
}
},
"camelize": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz",
"integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs="
},
"caniuse-api": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
@@ -10214,6 +10237,11 @@
"assert-plus": "^1.0.0"
}
},
"dasherize": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz",
"integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg="
},
"data-uri-to-buffer": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-1.2.0.tgz",
@@ -10916,6 +10944,11 @@
"safe-buffer": "^5.0.1"
}
},
"dns-prefetch-control": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.2.0.tgz",
"integrity": "sha512-hvSnros73+qyZXhHFjx2CMLwoj3Fe7eR9EJsFsqmcI1bB2OBWL/+0YzaEaKssCHnj/6crawNnUyw74Gm2EKe+Q=="
},
"dns-txt": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
@@ -12930,6 +12963,11 @@
"domelementtype": "1"
}
},
"dont-sniff-mimetype": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz",
"integrity": "sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug=="
},
"dot-case": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/dot-case/-/dot-case-2.1.1.tgz",
@@ -14172,6 +14210,11 @@
"jest-regex-util": "^24.3.0"
}
},
"expect-ct": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.2.0.tgz",
"integrity": "sha512-6SK3MG/Bbhm8MsgyJAylg+ucIOU71/FzyFalcfu5nY19dH8y/z0tBJU0wrNBXD4B27EoQtqPF/9wqH0iYAd04g=="
},
"express": {
"version": "4.16.3",
"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
@@ -14216,6 +14259,11 @@
}
}
},
"express-enforces-ssl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/express-enforces-ssl/-/express-enforces-ssl-1.1.0.tgz",
"integrity": "sha1-zynGphxb3YAuLH7SZaSpjnSH0aw="
},
"express-static-gzip": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-0.3.2.tgz",
@@ -14474,6 +14522,11 @@
"integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==",
"dev": true
},
"feature-policy": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.3.0.tgz",
"integrity": "sha512-ZtijOTFN7TzCujt1fnNhfWPFPSHeZkesff9AXZj+UEjYBynWNUIYpC87Ve4wHzyexQsImicLu7WsC2LHq7/xrQ=="
},
"figgy-pudding": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz",
@@ -15168,6 +15221,11 @@
"map-cache": "^0.2.2"
}
},
"frameguard": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.1.0.tgz",
"integrity": "sha512-TxgSKM+7LTA6sidjOiSZK9wxY0ffMPY3Wta//MqwmX0nZuEHc8QrkV8Fh3ZhMJeiH+Uyh/tcaarImRy8u77O7g=="
},
"fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -17747,12 +17805,74 @@
"upper-case": "^1.1.3"
}
},
"helmet": {
"version": "3.21.2",
"resolved": "https://registry.npmjs.org/helmet/-/helmet-3.21.2.tgz",
"integrity": "sha512-okUo+MeWgg00cKB8Csblu8EXgcIoDyb5ZS/3u0W4spCimeVuCUvVZ6Vj3O2VJ1Sxpyb8jCDvzu0L1KKT11pkIg==",
"requires": {
"depd": "2.0.0",
"dns-prefetch-control": "0.2.0",
"dont-sniff-mimetype": "1.1.0",
"expect-ct": "0.2.0",
"feature-policy": "0.3.0",
"frameguard": "3.1.0",
"helmet-crossdomain": "0.4.0",
"helmet-csp": "2.9.4",
"hide-powered-by": "1.1.0",
"hpkp": "2.0.0",
"hsts": "2.2.0",
"ienoopen": "1.1.0",
"nocache": "2.1.0",
"referrer-policy": "1.2.0",
"x-xss-protection": "1.3.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"helmet-crossdomain": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.4.0.tgz",
"integrity": "sha512-AB4DTykRw3HCOxovD1nPR16hllrVImeFp5VBV9/twj66lJ2nU75DP8FPL0/Jp4jj79JhTfG+pFI2MD02kWJ+fA=="
},
"helmet-csp": {
"version": "2.9.4",
"resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.9.4.tgz",
"integrity": "sha512-qUgGx8+yk7Xl8XFEGI4MFu1oNmulxhQVTlV8HP8tV3tpfslCs30OZz/9uQqsWPvDISiu/NwrrCowsZBhFADYqg==",
"requires": {
"bowser": "^2.7.0",
"camelize": "1.0.0",
"content-security-policy-builder": "2.1.0",
"dasherize": "2.0.0"
},
"dependencies": {
"bowser": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz",
"integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w=="
},
"content-security-policy-builder": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.1.0.tgz",
"integrity": "sha512-/MtLWhJVvJNkA9dVLAp6fg9LxD2gfI6R2Fi1hPmfjYXSahJJzcfvoeDOxSyp4NvxMuwWv3WMssE9o31DoULHrQ=="
}
}
},
"hex-color-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
"dev": true
},
"hide-powered-by": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.1.0.tgz",
"integrity": "sha512-Io1zA2yOA1YJslkr+AJlWSf2yWFkKjvkcL9Ni1XSUqnGLr/qRQe2UI3Cn/J9MsJht7yEVCe0SscY1HgVMujbgg=="
},
"history": {
"version": "4.9.0",
"resolved": "https://registry.npmjs.org/history/-/history-4.9.0.tgz",
@@ -17828,6 +17948,11 @@
"wbuf": "^1.1.0"
}
},
"hpkp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz",
"integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI="
},
"hsl-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz",
@@ -17840,6 +17965,21 @@
"integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=",
"dev": true
},
"hsts": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/hsts/-/hsts-2.2.0.tgz",
"integrity": "sha512-ToaTnQ2TbJkochoVcdXYm4HOCliNozlviNsg+X2XQLQvZNI/kCHR9rZxVYpJB3UPcHz80PgxRyWQ7PdU1r+VBQ==",
"requires": {
"depd": "2.0.0"
},
"dependencies": {
"depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
}
}
},
"html-comment-regex": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
@@ -18391,6 +18531,11 @@
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.12.tgz",
"integrity": "sha512-GguP+DRY+pJ3soyIiGPTvdiVXjZ+DbXOxGpXn3eMvNW4x4irjqXm4wHKscC+TfxSJ0yw/S1F24tqdMNsMZTiLA=="
},
"ienoopen": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.1.0.tgz",
"integrity": "sha512-MFs36e/ca6ohEKtinTJ5VvAJ6oDRAYFdYXweUnGY9L9vcoqFOU4n2ZhmJ0C4z/cwGZ3YIQRSB3XZ1+ghZkY5NQ=="
},
"iferr": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
@@ -23063,6 +23208,11 @@
"lower-case": "^1.1.1"
}
},
"nocache": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/nocache/-/nocache-2.1.0.tgz",
"integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
},
"node-dir": {
"version": "0.1.17",
"resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz",
@@ -30059,6 +30209,11 @@
"symbol-observable": "^1.2.0"
}
},
"referrer-policy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.2.0.tgz",
"integrity": "sha512-LgQJIuS6nAy1Jd88DCQRemyE3mS+ispwlqMk3b0yjZ257fI1v9c+/p6SD5gP5FGyXUIgrNOAfmyioHwZtYv2VA=="
},
"reflect.ownkeys": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz",
@@ -37777,6 +37932,11 @@
"integrity": "sha1-R0tQhlrzpJqcRlfwWs0UVFj3fYI=",
"dev": true
},
"x-xss-protection": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.3.0.tgz",
"integrity": "sha512-kpyBI9TlVipZO4diReZMAHWtS0MMa/7Kgx8hwG/EuZLiA6sg4Ah/4TRdASHhRRN3boobzcYgFRUFSgHRge6Qhg=="
},
"xml": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz",
+4
View File
@@ -82,6 +82,7 @@
"dotenv-expand": "^4.2.0",
"env-rewrite": "^1.0.2",
"express": "^4.16.3",
"express-enforces-ssl": "^1.1.0",
"express-static-gzip": "^0.3.2",
"fluent": "^0.10.0",
"fluent-dom": "^0.4.1",
@@ -94,6 +95,7 @@
"graphql-redis-subscriptions": "^2.1.0",
"graphql-subscriptions": "^1.1.0",
"graphql-tools": "^3.0.5",
"helmet": "^3.21.2",
"html-minifier": "^3.5.21",
"html-to-text": "^4.0.0",
"ioredis": "^4.9.0",
@@ -175,9 +177,11 @@
"@types/enzyme-adapter-react-16": "^1.0.3",
"@types/eventemitter2": "^4.1.0",
"@types/express": "^4.16.0",
"@types/express-enforces-ssl": "^1.1.1",
"@types/flat": "0.0.28",
"@types/fs-extra": "^5.0.4",
"@types/graphql": "^0.13.3",
"@types/helmet": "0.0.45",
"@types/html-minifier": "^3.5.2",
"@types/html-to-text": "^1.4.31",
"@types/html-webpack-plugin": "^3.2.0",
+29 -3
View File
@@ -1,8 +1,10 @@
import cons from "consolidate";
import cors from "cors";
import { Express } from "express";
import enforceHTTPS from "express-enforces-ssl";
import { GraphQLSchema } from "graphql";
import { RedisPubSub } from "graphql-redis-subscriptions";
import { hsts, noSniff, referrerPolicy, xssFilter } from "helmet";
import http from "http";
import { Db } from "mongodb";
import nunjucks from "nunjucks";
@@ -13,6 +15,7 @@ import { HTMLErrorHandler } from "coral-server/app/middleware/error";
import { notFoundMiddleware } from "coral-server/app/middleware/notFound";
import { createPassport } from "coral-server/app/middleware/passport";
import { Config } from "coral-server/config";
import logger from "coral-server/logger";
import { MailerQueue } from "coral-server/queue/tasks/mailer";
import { NotifierQueue } from "coral-server/queue/tasks/notifier";
import { ScraperQueue } from "coral-server/queue/tasks/scraper";
@@ -110,9 +113,7 @@ export const listenAndServe = (
});
function configureApplication(options: AppOptions) {
const { parent } = options;
parent.disable("x-powered-by");
const { parent, config } = options;
// Trust the proxy in front of us, this will enable us to trust the fact that
// SSL was terminated correctly.
@@ -121,6 +122,31 @@ function configureApplication(options: AppOptions) {
parent.set("trust proxy", compileTrust(trust));
}
// Configure security middleware and options.
parent.disable("x-powered-by");
parent.use(noSniff());
parent.use(referrerPolicy({ policy: "same-origin" }));
parent.use(xssFilter());
// If we're in production mode, configure some production security settings.
if (config.get("env") === "production") {
if (config.get("disable_force_ssl")) {
logger.warn(
"SSL enforcement has been disabled in production, this should not be used except for testing"
);
} else {
// Coral in production requires SSL, so we'll send the HSTS headers here as
// well as force the use of HTTPS with a 301 redirect.
parent.use(
hsts({
// We don't want to break existing other services that run with SSL.
includeSubDomains: false,
})
);
parent.use(enforceHTTPS());
}
}
// Setup the view config.
setupViews(options);
}
+8
View File
@@ -255,6 +255,14 @@ const config = convict({
env: "SCRAPE_TIMEOUT",
arg: "scrapeTimeout",
},
disable_force_ssl: {
doc:
"Disables forcing SSL in production environments. Should not be used except for testing.",
format: Boolean,
default: false,
env: "DISABLE_FORCE_SSL",
arg: "disableForceSSL",
},
});
export type Config = typeof config;