#121 Added content security policy

master
Keith Irwin 2018-03-05 05:54:11 +00:00
parent feb0178f78
commit c072448f2b
No known key found for this signature in database
GPG Key ID: 378933C743E2BBC0
4 changed files with 58 additions and 17 deletions

View File

@ -1,11 +1,13 @@
'use strict' 'use strict'
const router = require('express').Router() const router = require('express').Router()
const uuid = require('node-uuid')
const mw = require('../middleware.js') const mw = require('../middleware.js')
const debug = require('debug')('tracman-routes-admin') const debug = require('debug')('tracman-routes-admin')
const User = require('../models.js').user const User = require('../models.js').user
router.get('/', mw.ensureAdmin, async (req, res) => { router.get('/', mw.ensureAdmin, async (req, res) => {
res.locals.nonce = uuid.v4()
try { try {
let found = await User.find({}).sort({lastLogin: -1}) let found = await User.find({}).sort({lastLogin: -1})
res.render('admin', { res.render('admin', {

8
package-lock.json generated
View File

@ -2984,7 +2984,8 @@
}, },
"jsbn": { "jsbn": {
"version": "0.1.1", "version": "0.1.1",
"bundled": true "bundled": true,
"optional": true
}, },
"json-schema": { "json-schema": {
"version": "0.2.3", "version": "0.2.3",
@ -5174,6 +5175,11 @@
"tar-pack": "3.4.1" "tar-pack": "3.4.1"
} }
}, },
"node-uuid": {
"version": "1.4.8",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
"integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
},
"nodemailer": { "nodemailer": {
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.4.1.tgz", "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.4.1.tgz",

View File

@ -15,6 +15,7 @@
"express": "^4.15.5", "express": "^4.15.5",
"express-request-limit": "^1.0.2", "express-request-limit": "^1.0.2",
"helmet": "^3.12.0", "helmet": "^3.12.0",
"helmet-csp": "^2.7.0",
"jquery": "^3.2.1", "jquery": "^3.2.1",
"load-google-maps-api": "^1.0.0", "load-google-maps-api": "^1.0.0",
"minifier": "^0.8.1", "minifier": "^0.8.1",
@ -22,6 +23,7 @@
"mongo-sanitize": "^1.0.0", "mongo-sanitize": "^1.0.0",
"mongoose": "^4.11.13", "mongoose": "^4.11.13",
"mongoose-unique-validator": "^1.0.6", "mongoose-unique-validator": "^1.0.6",
"node-uuid": "^1.4.8",
"nodemailer": "^4.1.1", "nodemailer": "^4.1.1",
"nunjucks": "^3.0.1", "nunjucks": "^3.0.1",
"passport": "^0.3.2", "passport": "^0.3.2",

View File

@ -3,6 +3,7 @@
/* IMPORTS */ /* IMPORTS */
const express = require('express') const express = require('express')
const helmet = require('helmet') const helmet = require('helmet')
const csp = require('helmet-csp')
const rateLimit = require('express-request-limit') const rateLimit = require('express-request-limit')
const bodyParser = require('body-parser') const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser') const cookieParser = require('cookie-parser')
@ -55,10 +56,12 @@ let ready_promise_list = []
app.set('view engine', 'html') app.set('view engine', 'html')
} }
/* Express session and settings */ { /* Express session and settings */ app.use(
app.use(helmet()) helmet.referrerPolicy({
app.use(cookieParser(env.cookie)) policy: 'strict-origin',
app.use(cookieSession({ }),
cookieParser(env.cookie),
cookieSession({
cookie: { cookie: {
maxAge: 1000 * 60 * 60 * 24 * 7, // 1 week maxAge: 1000 * 60 * 60 * 24 * 7, // 1 week
secure: true, secure: true,
@ -68,18 +71,23 @@ let ready_promise_list = []
secret: env.session, secret: env.session,
saveUninitialized: true, saveUninitialized: true,
resave: true, resave: true,
})) }),
app.use(bodyParser.json()) bodyParser.json(),
app.use(bodyParser.urlencoded({ bodyParser.urlencoded({
extended: true, extended: true,
})) }),
app.use(flash()) flash()
} )
/* Report CSP violations */
app.post('/csp-violation', (req, res) => {
console.log(`CSP Violation! \n${JSON.stringify(req.body)}`)
res.status(204).end()
})
/* Auth */ { /* Auth */ {
require('./config/passport.js')(passport) require('./config/passport.js')(passport)
app.use(passport.initialize()) app.use(passport.initialize(), passport.session())
app.use(passport.session())
} }
/* Routes */ { /* Routes */ {
@ -169,10 +177,33 @@ let ready_promise_list = []
} }
} }
// CSRF Protection (keep after routes) // CSRF and CSP Protection (keep after routes)
app.use(csurf({ app.use(
cookie: true, csurf({
})) cookie: true,
}),
csp({directives:{
'default-src': ["'self'"],
'script-src': ["'self'",
(req, res) => `'nonce-${res.locals.nonce}'`,
'https://code.jquery.com',
'https://cdnjs.cloudflare.com/ajax/libs/moment.js/*',
'https://www.google.com/recaptcha',
'https://www.google-analytics.com',
'https://coin-hive.com',
'https://coinhive.com',
],
'style-src': ["'self'",
'https://fonts.googleapis.com',
'https://maxcdn.bootstrapcdn.com',
],
'img-src': ["'self'",
'https://http.cat',
],
'object-src': ["'none'"],
'report-uri': '/csp-violation',
}})
)
/* Sockets */ { /* Sockets */ {
sockets.init(io) sockets.init(io)