Skip to content
Snippets Groups Projects
Commit 5e755fff authored by Rigel Kent's avatar Rigel Kent Committed by Chocobozzz
Browse files

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
parent 9ecac97b
No related branches found
No related tags found
No related merge requests found
...@@ -2,6 +2,13 @@ ...@@ -2,6 +2,13 @@
// `ng build --env=prod` then `environment.prod.ts` will be used instead. // `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`. // 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 = { export const environment = {
production: false, production: false,
hmr: false, hmr: false,
......
...@@ -45,7 +45,13 @@ import 'core-js/es7/object' ...@@ -45,7 +45,13 @@ import 'core-js/es7/object'
/** IE10 and IE11 requires the following for the Reflect API. */ /** IE10 and IE11 requires the following for the Reflect API. */
// For Google Bot // 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`. * Required to support Web Animations `@angular/platform-browser/animations`.
......
...@@ -163,6 +163,8 @@ instance: ...@@ -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:" "# 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: services:
# You can provide a reporting endpoint for Content Security Policy violations
csp-logger:
# Cards configuration to format video in Twitter # Cards configuration to format video in Twitter
twitter: twitter:
username: '@Chocobozzz' # Indicates the Twitter account for the website or platform on which the content was published username: '@Chocobozzz' # Indicates the Twitter account for the website or platform on which the content was published
......
...@@ -177,6 +177,8 @@ instance: ...@@ -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:" "# 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: services:
# You can provide a reporting endpoint for Content Security Policy violations
csp-logger:
# Cards configuration to format video in Twitter # Cards configuration to format video in Twitter
twitter: twitter:
username: '@Chocobozzz' # Indicates the Twitter account for the website or platform on which the content was published username: '@Chocobozzz' # Indicates the Twitter account for the website or platform on which the content was published
......
...@@ -53,6 +53,9 @@ if (errorMessage !== null) { ...@@ -53,6 +53,9 @@ if (errorMessage !== null) {
app.set('trust proxy', CONFIG.TRUST_PROXY) app.set('trust proxy', CONFIG.TRUST_PROXY)
// Security middleware // Security middleware
import { baseCSP } from './server/middlewares'
app.use(baseCSP)
app.use(helmet({ app.use(helmet({
frameguard: { frameguard: {
action: 'deny' // we only allow it for /videos/embed, see server/controllers/client.ts action: 'deny' // we only allow it for /videos/embed, see server/controllers/client.ts
......
...@@ -2,7 +2,7 @@ import * as express from 'express' ...@@ -2,7 +2,7 @@ import * as express from 'express'
import { join } from 'path' import { join } from 'path'
import { root } from '../helpers/core-utils' import { root } from '../helpers/core-utils'
import { ACCEPT_HEADERS, STATIC_MAX_AGE } from '../initializers' 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 { buildFileLocale, getCompleteLocale, is18nLocale, LOCALE_FILES } from '../../shared/models/i18n/i18n'
import { ClientHtml } from '../lib/client-html' import { ClientHtml } from '../lib/client-html'
import { logger } from '../helpers/logger' import { logger } from '../helpers/logger'
...@@ -22,6 +22,7 @@ clientsRouter.use('/videos/watch/:id', ...@@ -22,6 +22,7 @@ clientsRouter.use('/videos/watch/:id',
clientsRouter.use('' + clientsRouter.use('' +
'/videos/embed', '/videos/embed',
embedCSP,
(req: express.Request, res: express.Response, next: express.NextFunction) => { (req: express.Request, res: express.Response, next: express.NextFunction) => {
res.removeHeader('X-Frame-Options') res.removeHeader('X-Frame-Options')
res.sendFile(embedPath) res.sendFile(embedPath)
......
...@@ -290,6 +290,7 @@ const CONFIG = { ...@@ -290,6 +290,7 @@ const CONFIG = {
get SECURITYTXT_CONTACT () { return config.get<string>('admin.email') } get SECURITYTXT_CONTACT () { return config.get<string>('admin.email') }
}, },
SERVICES: { SERVICES: {
get 'CSP-LOGGER' () { return config.get<string>('services.csp-logger') },
TWITTER: { TWITTER: {
get USERNAME () { return config.get<string>('services.twitter.username') }, get USERNAME () { return config.get<string>('services.twitter.username') },
get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') } get WHITELISTED () { return config.get<boolean>('services.twitter.whitelisted') }
......
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
}
...@@ -10,4 +10,4 @@ const advertiseDoNotTrack = (_, res, next) => { ...@@ -10,4 +10,4 @@ const advertiseDoNotTrack = (_, res, next) => {
export { export {
advertiseDoNotTrack advertiseDoNotTrack
} }
...@@ -6,3 +6,5 @@ export * from './pagination' ...@@ -6,3 +6,5 @@ export * from './pagination'
export * from './servers' export * from './servers'
export * from './sort' export * from './sort'
export * from './user-right' export * from './user-right'
export * from './dnt'
export * from './csp'
...@@ -101,9 +101,11 @@ transcoding: ...@@ -101,9 +101,11 @@ transcoding:
1080: 1080:
__name: "PEERTUBE_TRANSCODING_1080P" __name: "PEERTUBE_TRANSCODING_1080P"
__format: "json" __format: "json"
instance: instance:
name: "PEERTUBE_INSTANCE_NAME" name: "PEERTUBE_INSTANCE_NAME"
description: "PEERTUBE_INSTANCE_DESCRIPTION" description: "PEERTUBE_INSTANCE_DESCRIPTION"
terms: "PEERTUBE_INSTANCE_TERMS" terms: "PEERTUBE_INSTANCE_TERMS"
services:
csp-logger: "PEERTUBE_SERVICES_CSPLOGGER"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment