Project rename

This commit is contained in:
2019-03-24 08:27:49 +01:00
parent 594480d11f
commit 1728e0e6e1
7262 changed files with 0 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2018 Evan Hahn, Adam Baldwin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+149
View File
@@ -0,0 +1,149 @@
Content Security Policy middleware
==================================
[![Build Status](https://travis-ci.org/helmetjs/csp.svg?branch=master)](https://travis-ci.org/helmetjs/csp)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[_Looking for a changelog?_](https://github.com/helmetjs/helmet/blob/master/HISTORY.md)
Content Security Policy helps prevent unwanted content being injected into your webpages; this can mitigate cross-site scripting (XSS) vulnerabilities, malicious frames, unwanted trackers, and more. If you want to learn how CSP works, check out the fantastic [HTML5 Rocks guide](http://www.html5rocks.com/en/tutorials/security/content-security-policy/), the [Content Security Policy Reference](http://content-security-policy.com/), and the [Content Security Policy specification](http://www.w3.org/TR/CSP/). This module helps set Content Security Policies.
Usage:
```javascript
var csp = require('helmet-csp')
app.use(csp({
// Specify directives as normal.
directives: {
defaultSrc: ["'self'", 'default.com'],
scriptSrc: ["'self'", "'unsafe-inline'"],
styleSrc: ['style.com'],
fontSrc: ["'self'", 'fonts.com'],
imgSrc: ['img.com', 'data:'],
sandbox: ['allow-forms', 'allow-scripts'],
reportUri: '/report-violation',
objectSrc: ["'none'"],
upgradeInsecureRequests: true,
workerSrc: false // This is not set.
},
// This module will detect common mistakes in your directives and throw errors
// if it finds any. To disable this, enable "loose mode".
loose: false,
// Set to true if you only want browsers to report errors, not block them.
// You may also set this to a function(req, res) in order to decide dynamically
// whether to use reportOnly mode, e.g., to allow for a dynamic kill switch.
reportOnly: false,
// Set to true if you want to blindly set all headers: Content-Security-Policy,
// X-WebKit-CSP, and X-Content-Security-Policy.
setAllHeaders: false,
// Set to true if you want to disable CSP on Android where it can be buggy.
disableAndroid: false,
// Set to false if you want to completely disable any user-agent sniffing.
// This may make the headers less compatible but it will be much faster.
// This defaults to `true`.
browserSniff: true
}))
```
There are a lot of inconsistencies in how browsers implement CSP. Helmet looks at the user-agent of the browser and sets the appropriate header and value for that browser. If no user-agent is matched, it will set _all_ the headers with the 2.0 spec.
Supported directives
--------------------
Directives can be kebab-cased (like `script-src`) or camel-cased (like `scriptSrc`); they are equivalent.
The following directives are supported:
* `base-uri` or `baseUri`
* `block-all-mixed-content` or `blockAllMixedContent`
* `child-src` or `childSrc`
* `connect-src` or `connectSrc`
* `default-src` or `defaultSrc`
* `font-src` or `fontSrc`
* `form-action` or `formAction`
* `frame-ancestors` or `frameAncestors`
* `frame-src` or `frameSrc`
* `img-src` or `imgSrc`
* `manifest-src` or `manifestSrc`
* `media-src` or `mediaSrc`
* `object-src` or `objectSrc`
* `plugin-types` or `pluginTypes`
* `prefetch-src` or `prefetchSrc`
* `report-to` or `reportTo`
* `report-uri` or `reportUri`
* `require-sri-for` or `requireSriFor`
* `sandbox` or `sandbox`
* `script-src` or `scriptSrc`
* `style-src` or `styleSrc`
* `upgrade-insecure-requests` or `upgradeInsecureRequests`
* `worker-src` or `workerSrc`
Handling CSP violations
-----------------------
If you've specified a `reportUri`, browsers will POST any CSP violations to your server. Here's a simple example of a route that handles those reports:
```js
// You need a JSON parser first.
app.use(bodyParser.json({
type: ['json', 'application/csp-report']
}))
app.post('/report-violation', function (req, res) {
if (req.body) {
console.log('CSP Violation: ', req.body)
} else {
console.log('CSP Violation: No data received!')
}
res.status(204).end()
})
```
Not all browsers send CSP violations in the same way, so this might require a little work.
*Note*: If you're using a CSRF module like [csurf](https://github.com/expressjs/csurf), you might have problems handling these violations without a valid CSRF token. The fix is to put your CSP report route *above* csurf middleware.
Generating nonces
-----------------
You can dynamically generate nonces to allow inline `<script>` tags to be safely evaluated. Here's a simple example:
```js
var uuidv4 = require('uuid/v4')
app.use(function (req, res, next) {
res.locals.nonce = uuidv4()
next()
})
app.use(csp({
directives: {
scriptSrc: [
"'self'",
function (req, res) {
return "'nonce-" + res.locals.nonce + "'" // 'nonce-614d9122-d5b0-4760-aecf-3a5d17cf0ac9'
}
]
}
}))
app.use(function (req, res) {
res.end('<script nonce="' + res.locals.nonce + '">alert(1 + 1);</script>')
})
```
Using CSP with a CDN
--------------------
The default behavior of CSP is generate headers tailored for the browser that's requesting your page. If you have a CDN in front of your application, the CDN may cache the wrong headers, rendering your CSP useless. Make sure to eschew a CDN when using this module or set the `browserSniff` option to `false`.
See also
--------
* [GitHub's CSP journey](http://githubengineering.com/githubs-csp-journey/)
* [Content Security Policy for Single Page Web Apps](https://corner.squareup.com/2016/05/content-security-policy-single-page-app.html)
+87
View File
@@ -0,0 +1,87 @@
var camelize = require('camelize')
var cspBuilder = require('content-security-policy-builder')
var isFunction = require('./lib/is-function')
var platform = require('platform')
var checkOptions = require('./lib/check-options')
var containsFunction = require('./lib/contains-function')
var getHeaderKeysForBrowser = require('./lib/get-header-keys-for-browser')
var transformDirectivesForBrowser = require('./lib/transform-directives-for-browser')
var parseDynamicDirectives = require('./lib/parse-dynamic-directives')
var config = require('./lib/config')
module.exports = function csp (options) {
checkOptions(options)
var originalDirectives = camelize(options.directives || {})
var directivesAreDynamic = containsFunction(originalDirectives)
var shouldBrowserSniff = options.browserSniff !== false
var reportOnlyIsFunction = isFunction(options.reportOnly)
if (shouldBrowserSniff) {
return function csp (req, res, next) {
var userAgent = req.headers['user-agent']
var browser
if (userAgent) {
browser = platform.parse(userAgent)
} else {
browser = {}
}
var headerKeys
if (options.setAllHeaders || !userAgent) {
headerKeys = config.allHeaders
} else {
headerKeys = getHeaderKeysForBrowser(browser, options)
}
if (headerKeys.length === 0) {
next()
return
}
var directives = transformDirectivesForBrowser(browser, originalDirectives)
if (directivesAreDynamic) {
directives = parseDynamicDirectives(directives, [req, res])
}
var policyString = cspBuilder({ directives: directives })
headerKeys.forEach(function (headerKey) {
if ((reportOnlyIsFunction && options.reportOnly(req, res)) ||
(!reportOnlyIsFunction && options.reportOnly)) {
headerKey += '-Report-Only'
}
res.setHeader(headerKey, policyString)
})
next()
}
} else {
var headerKeys
if (options.setAllHeaders) {
headerKeys = config.allHeaders
} else {
headerKeys = ['Content-Security-Policy']
}
return function csp (req, res, next) {
var directives = parseDynamicDirectives(originalDirectives, [req, res])
var policyString = cspBuilder({ directives: directives })
if ((reportOnlyIsFunction && options.reportOnly(req, res)) ||
(!reportOnlyIsFunction && options.reportOnly)) {
headerKeys.forEach(function (headerKey) {
res.setHeader(headerKey + '-Report-Only', policyString)
})
} else {
headerKeys.forEach(function (headerKey) {
res.setHeader(headerKey, policyString)
})
}
next()
}
}
}
@@ -0,0 +1,7 @@
var isBoolean = require('../../is-boolean')
module.exports = function (key, value) {
if (!isBoolean(value)) {
throw new Error('"' + value + '" is not a valid value for ' + key + '. Use `true` or `false`.')
}
}
@@ -0,0 +1,20 @@
var config = require('../../config')
var checkers = {
sourceList: require('./source-list'),
pluginTypes: require('./plugin-types'),
sandbox: require('./sandbox'),
reportUri: require('./report-uri'),
requireSriFor: require('./require-sri-for'),
boolean: require('./boolean')
}
module.exports = function (key, value, options) {
if (options.loose) { return }
if (!config.directives.hasOwnProperty(key)) {
throw new Error('"' + key + '" is an invalid directive. See the documentation for the supported list. Force this by enabling loose mode.')
}
var directiveType = config.directives[key].type
checkers[directiveType](key, value, options)
}
@@ -0,0 +1,36 @@
var config = require('../../config')
var isFunction = require('../../is-function')
var notAllowed = ['self', "'self'"].concat(config.unsafes)
module.exports = function pluginTypesCheck (key, value, options) {
if (!Array.isArray(value) && (value !== false)) {
throw new Error('"' + value + '" is not a valid value for ' + key + '. Use an array of strings.')
}
if (value.length === 0) {
throw new Error(key + ' must have at least one value. To block everything, set ' + key + ' to ["\'none\'"].')
}
value.forEach(function (pluginType) {
if (!pluginType) {
throw new Error('"' + pluginType + '" is not a valid plugin type. Only non-empty strings are allowed.')
}
if (isFunction(pluginType)) { return }
pluginType = pluginType.valueOf()
if ((typeof pluginType !== 'string') || (pluginType.length === 0)) {
throw new Error('"' + pluginType + '" is not a valid plugin type. Only non-empty strings are allowed.')
}
if (notAllowed.indexOf(pluginType) !== -1) {
throw new Error('"' + pluginType + '" does not make sense in ' + key + '. Remove it.')
}
if (config.mustQuote.indexOf(pluginType) !== -1) {
throw new Error('"' + pluginType + '" must be quoted in ' + key + '. Change it to "\'' + pluginType + '\'" in your source list. Force this by enabling loose mode.')
}
})
}
@@ -0,0 +1,11 @@
var isFunction = require('../../is-function')
var isString = require('../../is-string')
module.exports = function (key, value) {
if (value === false) { return }
if (isFunction(value)) { return }
if (!isString(value) || (value.length === 0)) {
throw new Error('"' + value + '" is not a valid value for ' + key + '. Use a non-empty string.')
}
}
@@ -0,0 +1,20 @@
var isFunction = require('../../is-function')
var config = require('../../config')
module.exports = function requireSriForCheck (key, value) {
if (!Array.isArray(value)) {
throw new Error('"' + value + '" is not a valid value for ' + key + '. Use an array of strings.')
}
if (value.length === 0) {
throw new Error(key + ' must have at least one value. To require nothing, omit the directive.')
}
value.forEach(function (expression) {
if (isFunction(expression)) { return }
if (config.requireSriForValues.indexOf(expression) === -1) {
throw new Error('"' + expression + '" is not a valid ' + key + ' value. Remove it.')
}
})
}
@@ -0,0 +1,23 @@
var isFunction = require('../../is-function')
var config = require('../../config')
module.exports = function sandboxCheck (key, value) {
if (value === false) { return }
if (value === true) { return }
if (!Array.isArray(value)) {
throw new Error('"' + value + '" is not a valid value for ' + key + '. Use an array of strings or `true`.')
}
if (value.length === 0) {
throw new Error(key + ' must have at least one value. To block everything, set ' + key + ' to `true`.')
}
value.forEach(function (expression) {
if (isFunction(expression)) { return }
if (config.sandboxDirectives.indexOf(expression) === -1) {
throw new Error('"' + expression + '" is not a valid ' + key + ' directive. Remove it.')
}
})
}
@@ -0,0 +1,39 @@
var isFunction = require('../../is-function')
var config = require('../../config')
module.exports = function sourceListCheck (key, value, options) {
var directiveInfo = config.directives[key]
if (value === false) { return }
if (!Array.isArray(value)) {
throw new Error('"' + value + '" is not a valid value for ' + key + '. Use an array of strings.')
}
if (value.length === 0) {
throw new Error(key + ' must have at least one value. To block everything, set ' + key + ' to ["\'none\'"].')
}
value.forEach(function (sourceExpression) {
if (!sourceExpression) {
throw new Error('"' + sourceExpression + '" is not a valid source expression. Only non-empty strings are allowed.')
}
if (isFunction(sourceExpression)) { return }
sourceExpression = sourceExpression.valueOf()
if ((typeof sourceExpression !== 'string') || (sourceExpression.length === 0)) {
throw new Error('"' + sourceExpression + '" is not a valid source expression. Only non-empty strings are allowed.')
}
if ((!directiveInfo.hasUnsafes && (config.unsafes.indexOf(sourceExpression) !== -1)) ||
(!directiveInfo.hasStrictDynamic && (config.strictDynamics.indexOf(sourceExpression) !== -1))) {
throw new Error('"' + sourceExpression + '" does not make sense in ' + key + '. Remove it.')
}
if (config.mustQuote.indexOf(sourceExpression) !== -1) {
throw new Error('"' + sourceExpression + '" must be quoted in ' + key + '. Change it to "\'' + sourceExpression + '\'" in your source list. Force this by enabling loose mode.')
}
})
}
+23
View File
@@ -0,0 +1,23 @@
var checkDirective = require('./check-directive')
var dasherize = require('dasherize')
module.exports = function (options) {
if (!isObject(options)) {
throw new Error('csp must be called with an object argument. See the documentation.')
}
var directives = options.directives
var directivesExist = isObject(directives)
if (!directivesExist || Object.keys(directives).length === 0) {
throw new Error('csp must have at least one directive under the "directives" key. See the documentation.')
}
Object.keys(directives).forEach(function (directiveKey) {
checkDirective(dasherize(directiveKey), directives[directiveKey], options)
})
}
function isObject (value) {
return Object.prototype.toString.call(value) === '[object Object]'
}
+61
View File
@@ -0,0 +1,61 @@
module.exports = {
directives: {
'base-uri': { type: 'sourceList' },
'block-all-mixed-content': { type: 'boolean' },
'child-src': { type: 'sourceList' },
'connect-src': { type: 'sourceList' },
'default-src': {
type: 'sourceList',
hasStrictDynamic: true
},
'font-src': { type: 'sourceList' },
'form-action': { type: 'sourceList' },
'frame-ancestors': { type: 'sourceList' },
'frame-src': { type: 'sourceList' },
'img-src': { type: 'sourceList' },
'manifest-src': { type: 'sourceList' },
'media-src': { type: 'sourceList' },
'object-src': { type: 'sourceList' },
'script-src': {
type: 'sourceList',
hasUnsafes: true,
hasStrictDynamic: true
},
'style-src': {
type: 'sourceList',
hasUnsafes: true
},
'prefetch-src': { type: 'sourceList' },
'plugin-types': { type: 'pluginTypes' },
'sandbox': { type: 'sandbox' },
'report-to': { type: 'reportUri' },
'report-uri': { type: 'reportUri' },
'require-sri-for': { type: 'requireSriFor' },
'upgrade-insecure-requests': { type: 'boolean' },
'worker-src': {
type: 'sourceList',
hasUnsafes: true
}
},
allHeaders: [
'Content-Security-Policy',
'X-Content-Security-Policy',
'X-WebKit-CSP'
],
mustQuote: ['none', 'self', 'unsafe-inline', 'unsafe-eval', 'strict-dynamic'],
unsafes: ["'unsafe-inline'", 'unsafe-inline', "'unsafe-eval'", 'unsafe-eval'],
strictDynamics: ["'strict-dynamic'", 'strict-dynamic'],
requireSriForValues: ['script', 'style'],
sandboxDirectives: [
'allow-forms',
'allow-modals',
'allow-orientation-lock',
'allow-pointer-lock',
'allow-popups',
'allow-popups-to-escape-sandbox',
'allow-presentation',
'allow-same-origin',
'allow-scripts',
'allow-top-navigation'
]
}
+19
View File
@@ -0,0 +1,19 @@
var isFunction = require('./is-function')
module.exports = function containsFunction (obj) {
for (var key in obj) {
if (!obj.hasOwnProperty(key)) { continue }
var value = obj[key]
if (!Array.isArray(value)) {
value = [value]
}
if (value.some(isFunction)) {
return true
}
}
return false
}
@@ -0,0 +1,114 @@
var config = require('./config')
function goodBrowser () {
return ['Content-Security-Policy']
}
var handlers = {
'Android Browser': function (browser, options) {
if (parseFloat(browser.os.version) < 4.4 || options.disableAndroid) {
return []
} else {
return ['Content-Security-Policy']
}
},
Chrome: function (browser) {
var version = parseFloat(browser.version)
if (version >= 14 && version < 25) {
return ['X-WebKit-CSP']
} else if (version >= 25) {
return ['Content-Security-Policy']
} else {
return []
}
},
'Chrome Mobile': function (browser) {
if (browser.os.family === 'iOS') {
return ['Content-Security-Policy']
} else {
return handlers['Android Browser'].apply(this, arguments)
}
},
Firefox: function (browser) {
var version = parseFloat(browser.version)
if (version >= 23) {
return ['Content-Security-Policy']
} else if (version >= 4 && version < 23) {
return ['X-Content-Security-Policy']
} else {
return []
}
},
'Firefox Mobile': function (browser) {
// Handles both Firefox for Android and Firefox OS
var family = browser.os.family
var version = parseFloat(browser.version)
if (family === 'Firefox OS') {
if (version >= 32) {
return ['Content-Security-Policy']
} else {
return ['X-Content-Security-Policy']
}
} else if (family === 'Android') {
if (version >= 25) {
return ['Content-Security-Policy']
} else {
return ['X-Content-Security-Policy']
}
}
return []
},
'Firefox for iOS': goodBrowser,
IE: function (browser) {
var version = parseFloat(browser.version)
var header = version < 12 ? 'X-Content-Security-Policy' : 'Content-Security-Policy'
return [header]
},
'Microsoft Edge': goodBrowser,
'Microsoft Edge Mobile': goodBrowser,
Opera: function (browser) {
if (parseFloat(browser.version) >= 15) {
return ['Content-Security-Policy']
} else {
return []
}
},
Safari: function (browser) {
var version = parseFloat(browser.version)
if (version >= 7) {
return ['Content-Security-Policy']
} else if (version >= 6) {
return ['X-WebKit-CSP']
} else {
return []
}
}
}
handlers['IE Mobile'] = handlers.IE
module.exports = function getHeaderKeysForBrowser (browser, options) {
var handler = handlers[browser.name]
if (handler) {
return handler(browser, options)
} else {
return config.allHeaders
}
}
+3
View File
@@ -0,0 +1,3 @@
module.exports = function isBoolean (value) {
return Object.prototype.toString.call(value) === '[object Boolean]'
}
+3
View File
@@ -0,0 +1,3 @@
module.exports = function isFunction (value) {
return value instanceof Function
}
+3
View File
@@ -0,0 +1,3 @@
module.exports = function isString (value) {
return Object.prototype.toString.call(value) === '[object String]'
}
@@ -0,0 +1,25 @@
var isFunction = require('./is-function')
module.exports = function parseDynamicDirectives (directives, functionArgs) {
var result = {}
Object.keys(directives).forEach(function (key) {
var value = directives[key]
if (Array.isArray(value)) {
result[key] = value.map(function (element) {
if (isFunction(element)) {
return element.apply(null, functionArgs)
} else {
return element
}
})
} else if (isFunction(value)) {
result[key] = value.apply(null, functionArgs)
} else if (value !== false) {
result[key] = value
}
})
return result
}
@@ -0,0 +1,76 @@
function createFirefoxPreCSP10Directives (directives, basePolicy) {
var result = Object.assign({}, basePolicy)
Object.keys(directives).forEach(function (key) {
var value = directives[key]
if (key === 'connectSrc') {
result.xhrSrc = value
} else {
result[key] = value
}
if (key === 'scriptSrc') {
var optionsValues = []
if (value.indexOf("'unsafe-inline'") !== -1) {
optionsValues.push('inline-script')
}
if (value.indexOf("'unsafe-eval'") !== -1) {
optionsValues.push('eval-script')
}
if (optionsValues.length !== 0) {
result.options = optionsValues
}
}
})
return result
}
var handlers = {
Firefox: function (browser, directives) {
var version = parseFloat(browser.version)
if (version >= 4 && version < 23) {
var basePolicy = {}
if (version < 5) {
basePolicy.allow = ['*']
if (directives.defaultSrc) {
basePolicy.allow = directives.defaultSrc
delete directives.defaultSrc
}
} else {
basePolicy.defaultSrc = ['*']
}
return createFirefoxPreCSP10Directives(directives, basePolicy)
} else {
return directives
}
},
'Firefox Mobile': function (browser, directives) {
// Handles both Firefox for Android and Firefox OS
var family = browser.os.family
var version = parseFloat(browser.version)
if ((family === 'Firefox OS' && version < 32) || (family === 'Android' && version < 25)) {
return createFirefoxPreCSP10Directives(directives, { defaultSrc: ['*'] })
} else {
return directives
}
}
}
module.exports = function transformDirectivesForBrowser (browser, directives) {
var handler = handlers[browser.name]
if (handler) {
return handler(browser, directives)
} else {
return directives
}
}
+132
View File
@@ -0,0 +1,132 @@
{
"_args": [
[
{
"raw": "helmet-csp@2.7.1",
"scope": null,
"escapedName": "helmet-csp",
"name": "helmet-csp",
"rawSpec": "2.7.1",
"spec": "2.7.1",
"type": "version"
},
"/Users/gerrit/Documents/dev/nodejs/rentfor.camp/html/RentForCamp/node_modules/helmet"
]
],
"_from": "helmet-csp@2.7.1",
"_id": "helmet-csp@2.7.1",
"_inCache": true,
"_location": "/helmet-csp",
"_nodeVersion": "10.5.0",
"_npmOperationalInternal": {
"host": "s3://npm-registry-packages",
"tmp": "tmp/helmet-csp_2.7.1_1532118830676_0.2757220233905715"
},
"_npmUser": {
"name": "evanhahn",
"email": "me@evanhahn.com"
},
"_npmVersion": "6.2.0",
"_phantomChildren": {},
"_requested": {
"raw": "helmet-csp@2.7.1",
"scope": null,
"escapedName": "helmet-csp",
"name": "helmet-csp",
"rawSpec": "2.7.1",
"spec": "2.7.1",
"type": "version"
},
"_requiredBy": [
"/helmet"
],
"_resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.1.tgz",
"_shasum": "e8e0b5186ffd4db625cfcce523758adbfadb9dca",
"_shrinkwrap": null,
"_spec": "helmet-csp@2.7.1",
"_where": "/Users/gerrit/Documents/dev/nodejs/rentfor.camp/html/RentForCamp/node_modules/helmet",
"author": {
"name": "Adam Baldwin",
"email": "baldwin@andyet.net",
"url": "http://andyet.net/team/baldwin"
},
"bugs": {
"url": "https://github.com/helmetjs/csp/issues"
},
"contributors": [
{
"name": "Evan Hahn",
"email": "me@evanhahn.com",
"url": "https://evanhahn.com"
},
{
"name": "Ryan Cannon",
"email": "ryan@ryancannon.com",
"url": "https://ryancannon.com"
}
],
"dependencies": {
"camelize": "1.0.0",
"content-security-policy-builder": "2.0.0",
"dasherize": "2.0.0",
"platform": "1.3.5"
},
"description": "Content Security Policy middleware.",
"devDependencies": {
"content-security-policy-parser": "^0.1.1",
"express": "^4.16.3",
"lodash": "^4.17.10",
"mocha": "^5.2.0",
"standard": "^11.0.1",
"supertest": "^3.1.0"
},
"directories": {},
"dist": {
"integrity": "sha512-sCHwywg4daQ2mY0YYwXSZRsgcCeerUwxMwNixGA7aMLkVmPTYBl7gJoZDHOZyXkqPrtuDT3s2B1A+RLI7WxSdQ==",
"shasum": "e8e0b5186ffd4db625cfcce523758adbfadb9dca",
"tarball": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.1.tgz",
"fileCount": 20,
"unpackedSize": 24588,
"npm-signature": "-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbUkcuCRA9TVsSAnZWagAAMpkP/jGWI9/c5mDrE40MQeO8\nCcnjhks0SsCCvnhDNggmFW8TNB/uHtNMklDx32M3lKV3fZKBeA8TAXwh0y1I\nLooWC1niKdvmLts6AG+8hk6uZk2HWwQz8wTHTaEZUCdP6hOfK7eMsJSD7SAS\nWhJ8qZnAjFvGyqr/Ni5SJ8OUWKF1je9K9WIozlej7kaFhGlLl0JCHRns/Kiq\n2u+2bMQdKRYHFnJbfztJrvQenoYNpiYP1bNdamXIJ7K6veCantLrYw/f33R4\n2TR3rQb29WGknKkfIH6+szoGz1ruaZjD311u8UXWVIQv/10aaP8sBEQQjj3Y\n2QHV5lB9JAfXXqG8ny5KKpcGAnstDnQUBPNuNFN4I4GLAe4oO4wrYfo1Gy5S\nYsTQwKf2EuMOhsgvAv6fkD+kRCneuXA248b5GS37y6miZxgxJjxgZKbS01CF\n/xfoC9ykto2pp30UVwwFvtbZHwlS5pTyZu/daFaQXj9NYevIEiHAliNJ9omX\nc+90SD2dsSMtTqZkzJI6fkunpgWWkv4r2JC2px0NknzVGAw2WdOe74HFRAok\nrTy2ozagrqef05k5RpjMLvEM3oRI13IX63f1R0Zb0enL3ua23lCqNg7xFmxX\nbBHQIrjQrr0esPZq6MJYI/x9GX9rKs+7UsOtU5DngnEUZnZdnu/mtwGIc9fx\n2tUx\r\n=UGEX\r\n-----END PGP SIGNATURE-----\r\n"
},
"gitHead": "4880b53cb58d46dbdf09d01b9293e5365694f8b7",
"homepage": "https://github.com/helmetjs/csp#readme",
"keywords": [
"helmet",
"security",
"express",
"connect",
"content",
"security",
"policy",
"csp",
"xss"
],
"license": "MIT",
"maintainers": [
{
"name": "evanhahn",
"email": "me@evanhahn.com"
}
],
"name": "helmet-csp",
"optionalDependencies": {},
"readme": "ERROR: No README data found!",
"repository": {
"type": "git",
"url": "git://github.com/helmetjs/csp.git"
},
"scripts": {
"generate-supported-directives-docs": "./scripts/generate_supported_directives_docs",
"pretest": "standard --fix",
"test": "mocha"
},
"standard": {
"globals": [
"describe",
"beforeEach",
"it"
]
},
"version": "2.7.1"
}