add Content Security Policy (#1252)

* add Content Security Policy

* remove reflect-metadata on production builds to get rid of unsafe-eval

* fix baseCSP usage

* add SRI to CSP

* add blob: to media-src

* remove SRI

* CSP set to reportOnly

* adding data: to connect-src CSP

* remove block-all-mixed-content

* add report-uri support
pull/1488/head
Rigel Kent 2018-12-13 09:49:45 +01:00 committed by Chocobozzz
parent 9ecac97be0
commit 5e755fff9d
11 changed files with 75 additions and 4 deletions

View File

@ -2,6 +2,13 @@
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.
// Reflect.metadata polyfill is only needed in the JIT/dev mode.
//
// In order to load these polyfills early enough (before app code), polyfill.ts imports this file to
// to change the order in the final bundle.
import 'core-js/es6/reflect'
import 'core-js/es7/reflect'
export const environment = {
production: false,
hmr: false,

View File

@ -45,7 +45,13 @@ import 'core-js/es7/object'
/** IE10 and IE11 requires the following for the Reflect API. */
// For Google Bot
import 'core-js/es6/reflect'
// import 'core-js/es6/reflect'; // --> dealt with in src/environment.ts
/**
* Evergreen browsers require these.
*/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
// import 'core-js/es7/reflect' // --> dealt with in src/environment.ts
/**
* Required to support Web Animations `@angular/platform-browser/animations`.

View File

@ -163,6 +163,8 @@ instance:
"# If you would like to report a security issue\n# you may report it to:\nContact: https://github.com/Chocobozzz/PeerTube/blob/develop/SECURITY.md\nContact: mailto:"
services:
# You can provide a reporting endpoint for Content Security Policy violations
csp-logger:
# Cards configuration to format video in Twitter
twitter:
username: '@Chocobozzz' # Indicates the Twitter account for the website or platform on which the content was published

View File

@ -177,6 +177,8 @@ instance:
"# If you would like to report a security issue\n# you may report it to:\nContact: https://github.com/Chocobozzz/PeerTube/blob/develop/SECURITY.md\nContact: mailto:"
services:
# You can provide a reporting endpoint for Content Security Policy violations
csp-logger:
# Cards configuration to format video in Twitter
twitter:
username: '@Chocobozzz' # Indicates the Twitter account for the website or platform on which the content was published

View File

@ -53,6 +53,9 @@ if (errorMessage !== null) {
app.set('trust proxy', CONFIG.TRUST_PROXY)
// Security middleware
import { baseCSP } from './server/middlewares'
app.use(baseCSP)
app.use(helmet({
frameguard: {
action: 'deny' // we only allow it for /videos/embed, see server/controllers/client.ts

View File

@ -2,7 +2,7 @@ import * as express from 'express'
import { join } from 'path'
import { root } from '../helpers/core-utils'
import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers'
import { asyncMiddleware } from '../middlewares'
import { asyncMiddleware, embedCSP } from '../middlewares'
import { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n'
import { ClientHtml } from '../lib/client-html'
import { logger } from '../helpers/logger'
@ -22,6 +22,7 @@ clientsRouter.use('/videos/watch/:id',
clientsRouter.use('' +
'/videos/embed',
embedCSP,
(req: express.Request, res: express.Response, next: express.NextFunction) => {
res.removeHeader('X-Frame-Options')
res.sendFile(embedPath)

View File

@ -290,6 +290,7 @@ const CONFIG = {
get SECURITYTXT_CONTACT () { return config.get<string>('admin.email') }
},
SERVICES: {
get 'CSP-LOGGER' () { return config.get<string>('services.csp-logger') },
TWITTER: {
get USERNAME () { return config.get<string>('services.twitter.username') },
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }

45
server/middlewares/csp.ts Normal file
View File

@ -0,0 +1,45 @@
import * as helmet from 'helmet'
import { CONFIG } from '../initializers/constants'
const baseDirectives = Object.assign({},
{
defaultSrc: ["'none'"], // by default, not specifying default-src = '*'
connectSrc: ['*', 'data:'],
mediaSrc: ["'self'", 'https:', 'blob:'],
fontSrc: ["'self'", 'data:'],
imgSrc: ["'self'", 'data:'],
scriptSrc: ["'self' 'unsafe-inline'"],
styleSrc: ["'self' 'unsafe-inline'"],
// objectSrc: ["'none'"], // only define to allow plugins, else let defaultSrc 'none' block it
formAction: ["'self'"],
frameAncestors: ["'none'"],
baseUri: ["'self'"],
pluginTypes: ["'none'"],
manifestSrc: ["'self'"],
frameSrc: ["'self'"], // instead of deprecated child-src / self because of test-embed
workerSrc: ["'self'"], // instead of deprecated child-src
upgradeInsecureRequests: true
},
(CONFIG.SERVICES['CSP-LOGGER'] != null) ? { reportUri: CONFIG.SERVICES['CSP-LOGGER'] } : {}
)
const baseCSP = helmet.contentSecurityPolicy({
directives: baseDirectives,
browserSniff: false,
reportOnly: true
})
const embedCSP = helmet.contentSecurityPolicy({
directives: Object.assign(baseDirectives, {
frameAncestors: ['*']
}),
browserSniff: false, // assumes a modern browser, but allows CDN in front
reportOnly: true
})
// ---------------------------------------------------------------------------
export {
baseCSP,
embedCSP
}

View File

@ -10,4 +10,4 @@ const advertiseDoNotTrack = (_, res, next) => {
export {
advertiseDoNotTrack
}
}

View File

@ -6,3 +6,5 @@ export * from './pagination'
export * from './servers'
export * from './sort'
export * from './user-right'
export * from './dnt'
export * from './csp'

View File

@ -101,9 +101,11 @@ transcoding:
1080:
__name: "PEERTUBE_TRANSCODING_1080P"
__format: "json"
instance:
name: "PEERTUBE_INSTANCE_NAME"
description: "PEERTUBE_INSTANCE_DESCRIPTION"
terms: "PEERTUBE_INSTANCE_TERMS"
services:
csp-logger: "PEERTUBE_SERVICES_CSPLOGGER"