-
Notifications
You must be signed in to change notification settings - Fork 212
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove payments/content consolidated CSP, fix Prettier-ified files, create separate middleware for payments Fix prettier things Add Stripe CSP things to payments server Add more config vars into proper directives Add stripe checkout API Remove unneeded directive Add tests to csp.test.js Remove unneeded test no-CSP lines Remove isCspRequired check in payment server (not content server) csp.enabled true by default Update CSP violations to report to content server Template literal return for getOrigin Update Stripe url doc
- Loading branch information
Showing
9 changed files
with
330 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
// Middleware to take care of CSP. CSP headers are not sent unless config | ||
// option 'csp.enabled' is set (default true). | ||
|
||
'use strict'; | ||
const helmet = require('helmet'); | ||
const htmlOnly = require('./html-middleware'); | ||
|
||
module.exports = function(config) { | ||
const cspMiddleware = helmet.contentSecurityPolicy(config.rules); | ||
|
||
return htmlOnly((req, res, next) => { | ||
cspMiddleware(req, res, next); | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
const config = require('../config'); | ||
const blockingRules = require('./csp/blocking'); | ||
|
||
describe('CSP blocking rules', () => { | ||
// force the CDN to be enabled for tests. | ||
const CDN_SERVER = 'https://static.accounts.firefox.com'; | ||
config.set('staticResources.url', CDN_SERVER); | ||
const { Sources, directives, reportOnly } = blockingRules(config); | ||
|
||
it('does not have a Sources value equal `undefined`', () => { | ||
expect(Sources).not.toHaveProperty('undefined'); | ||
expect(reportOnly).toBeFalsy(); | ||
}); | ||
|
||
it('has correct connectSrc directives', () => { | ||
const { connectSrc } = directives; | ||
|
||
expect(connectSrc).toHaveLength(6); | ||
expect(connectSrc).toContain(Sources.SELF); | ||
expect(connectSrc).toContain(Sources.AUTH_SERVER); | ||
expect(connectSrc).toContain(Sources.OAUTH_SERVER); | ||
expect(connectSrc).toContain(Sources.PROFILE_SERVER); | ||
expect(connectSrc).toContain(Sources.PAIRING_SERVER_WEBSOCKET); | ||
expect(connectSrc).toContain(Sources.STRIPE_API_URL); | ||
}); | ||
|
||
it('has correct defaultSrc directives', () => { | ||
const { defaultSrc } = directives; | ||
|
||
expect(defaultSrc).toHaveLength(1); | ||
expect(defaultSrc).toContain(Sources.SELF); | ||
}); | ||
|
||
it('has correct fontSrc directives', () => { | ||
const { fontSrc } = directives; | ||
|
||
expect(fontSrc).toHaveLength(2); | ||
expect(fontSrc).toContain(Sources.SELF); | ||
expect(fontSrc).toContain(CDN_SERVER); | ||
}); | ||
|
||
it('has correct frameSrc directives', () => { | ||
const { frameSrc } = directives; | ||
|
||
expect(frameSrc).toHaveLength(2); | ||
expect(frameSrc).toContain(Sources.STRIPE_SCRIPT_URL); | ||
expect(frameSrc).toContain(Sources.STRIPE_HOOKS_URL); | ||
}); | ||
|
||
it('has correct imgSrc directives', () => { | ||
const { imgSrc } = directives; | ||
|
||
expect(imgSrc).toHaveLength(5); | ||
expect(imgSrc).toContain(Sources.SELF); | ||
expect(imgSrc).toContain(Sources.DATA); | ||
expect(imgSrc).toContain(Sources.GRAVATAR); | ||
expect(imgSrc).toContain(Sources.PROFILE_IMAGES_SERVER); | ||
expect(imgSrc).toContain(CDN_SERVER); | ||
}); | ||
|
||
it('has correct mediaSrc directives', () => { | ||
const { mediaSrc } = directives; | ||
|
||
expect(mediaSrc).toHaveLength(1); | ||
expect(mediaSrc).toContain(Sources.BLOB); | ||
}); | ||
|
||
it('has correct objectSrc directives', () => { | ||
const { mediaSrc } = directives; | ||
|
||
expect(mediaSrc).toHaveLength(1); | ||
expect(mediaSrc).toContain(Sources.BLOB); | ||
}); | ||
|
||
it('has correct scriptSrc directives', () => { | ||
const { scriptSrc } = directives; | ||
|
||
expect(scriptSrc).toHaveLength(3); | ||
expect(scriptSrc).toContain(Sources.SELF); | ||
expect(scriptSrc).toContain(Sources.STRIPE_SCRIPT_URL); | ||
expect(scriptSrc).toContain(CDN_SERVER); | ||
}); | ||
|
||
it('has correct styleSrc directives', () => { | ||
const { styleSrc } = directives; | ||
|
||
expect(styleSrc).toHaveLength(3); | ||
expect(styleSrc).toContain(Sources.SELF); | ||
expect(styleSrc).toContain(Sources.UNSAFE_INLINE); | ||
expect(styleSrc).toContain(CDN_SERVER); | ||
}); | ||
}); |
106 changes: 106 additions & 0 deletions
106
packages/fxa-payments-server/server/lib/csp/blocking.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
// Middleware to take care of CSP. CSP headers are not sent unless config | ||
// option 'csp.enabled' is set (default true). | ||
|
||
const url = require('url'); | ||
|
||
function getOrigin(link) { | ||
const parsed = url.parse(link); | ||
return `${parsed.protocol}//${parsed.host}`; | ||
} | ||
|
||
/** | ||
* blockingCspMiddleware is where to declare rules that will cause a resource | ||
* to be blocked if it runs afowl of a rule. | ||
*/ | ||
module.exports = function(config) { | ||
const AUTH_SERVER = getOrigin(config.get('servers.auth.url')); | ||
const BLOB = 'blob:'; | ||
const CDN_URL = config.get('staticResources.url'); | ||
const DATA = 'data:'; | ||
const GRAVATAR = 'https://secure.gravatar.com'; | ||
const OAUTH_SERVER = getOrigin(config.get('servers.oauth.url')); | ||
const PROFILE_SERVER = getOrigin(config.get('servers.profile.url')); | ||
const PROFILE_IMAGES_SERVER = getOrigin( | ||
config.get('servers.profileImages.url') | ||
); | ||
const PUBLIC_URL = config.get('listen.publicUrl'); | ||
const PAIRING_SERVER_WEBSOCKET = PUBLIC_URL.replace(/^http/, 'ws'); | ||
|
||
const STRIPE_API_URL = getOrigin(config.get('stripe.apiUrl')); | ||
const STRIPE_HOOKS_URL = getOrigin(config.get('stripe.hooksUrl')); | ||
const STRIPE_SCRIPT_URL = getOrigin(config.get('stripe.scriptUrl')); | ||
|
||
// | ||
// Double quoted values | ||
// | ||
const NONE = "'none'"; | ||
// keyword sources - https://www.w3.org/TR/CSP2/#keyword_source | ||
// Note: "'unsafe-eval'" is not used in this module, and "'unsafe-inline'" is | ||
// needed for Stripe inline styles. | ||
const SELF = "'self'"; | ||
const UNSAFE_INLINE = "'unsafe-inline'"; | ||
|
||
function addCdnRuleIfRequired(target) { | ||
if (CDN_URL !== PUBLIC_URL) { | ||
target.push(CDN_URL); | ||
} | ||
return target; | ||
} | ||
|
||
const rules = { | ||
directives: { | ||
connectSrc: [ | ||
SELF, | ||
AUTH_SERVER, | ||
OAUTH_SERVER, | ||
PROFILE_SERVER, | ||
PAIRING_SERVER_WEBSOCKET, | ||
STRIPE_API_URL, | ||
], | ||
defaultSrc: [SELF], | ||
fontSrc: addCdnRuleIfRequired([SELF]), | ||
frameSrc: [STRIPE_SCRIPT_URL, STRIPE_HOOKS_URL], | ||
imgSrc: addCdnRuleIfRequired([ | ||
SELF, | ||
DATA, | ||
// Gravatar support was removed in #4927, but we don't want | ||
// to break the site for users who already use a Gravatar as | ||
// their profile image. | ||
GRAVATAR, | ||
PROFILE_IMAGES_SERVER, | ||
]), | ||
mediaSrc: [BLOB], | ||
objectSrc: [NONE], | ||
reportUri: config.get('csp.reportUri'), | ||
scriptSrc: addCdnRuleIfRequired([SELF, STRIPE_SCRIPT_URL]), | ||
styleSrc: addCdnRuleIfRequired([SELF, UNSAFE_INLINE]), | ||
}, | ||
reportOnly: false, | ||
// Sources are exported for unit tests | ||
Sources: { | ||
//eslint-disable-line sorting/sort-object-props | ||
AUTH_SERVER, | ||
BLOB, | ||
CDN_URL, | ||
DATA, | ||
GRAVATAR, | ||
NONE, | ||
OAUTH_SERVER, | ||
PAIRING_SERVER_WEBSOCKET, | ||
PROFILE_IMAGES_SERVER, | ||
PROFILE_SERVER, | ||
PUBLIC_URL, | ||
STRIPE_API_URL, | ||
STRIPE_HOOKS_URL, | ||
STRIPE_SCRIPT_URL, | ||
SELF, | ||
UNSAFE_INLINE, | ||
}, | ||
}; | ||
|
||
return rules; | ||
}; |
20 changes: 20 additions & 0 deletions
20
packages/fxa-payments-server/server/lib/csp/report-only.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* This Source Code Form is subject to the terms of the Mozilla Public | ||
* License, v. 2.0. If a copy of the MPL was not distributed with this | ||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | ||
|
||
/** | ||
* reportOnlyCspMiddleware is where to declare experimental rules that | ||
* will not cause a resource to be blocked if it runs afowl of a rule, but | ||
* will cause the resource to be reported. | ||
* | ||
* If no directives other than `reportUri` are declared, the CSP reportOnly | ||
* middleware will not be added. | ||
*/ | ||
module.exports = function(config) { | ||
return { | ||
directives: { | ||
reportUri: config.get('csp.reportOnlyUri'), | ||
}, | ||
reportOnly: true, | ||
}; | ||
}; |
Oops, something went wrong.