helmet-crossdomain
Advanced tools
Comparing version 0.2.0 to 0.3.0
41
index.js
@@ -1,24 +0,27 @@ | ||
var url = require('url') | ||
var DEFAULT_PERMITTED_POLICIES = 'none' | ||
var ALLOWED_POLICIES = [ | ||
'none', | ||
'master-only', | ||
'by-content-type', | ||
'all' | ||
] | ||
var POLICY = [ | ||
'<?xml version="1.0"?>', | ||
'<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">', | ||
'<cross-domain-policy>', | ||
'<site-control permitted-cross-domain-policies="none"/>', | ||
'</cross-domain-policy>' | ||
].join('') | ||
module.exports = function crossdomain (options) { | ||
options = options || {} | ||
module.exports = function crossdomain () { | ||
return function crossdomain (req, res, next) { | ||
var pathname = url.parse(req.url).pathname | ||
var permittedPolicies | ||
if ('permittedPolicies' in options) { | ||
permittedPolicies = options.permittedPolicies | ||
} else { | ||
permittedPolicies = DEFAULT_PERMITTED_POLICIES | ||
} | ||
if (pathname === '/crossdomain.xml') { | ||
res.writeHead(200, { | ||
'Content-Type': 'text/x-cross-domain-policy' | ||
}) | ||
res.end(POLICY) | ||
} else { | ||
next() | ||
} | ||
if (ALLOWED_POLICIES.indexOf(permittedPolicies) === -1) { | ||
throw new Error('"' + permittedPolicies + '" is not a valid permitted policy. Allowed values: ' + ALLOWED_POLICIES.join(', ') + '.') | ||
} | ||
return function crossdomain (req, res, next) { | ||
res.setHeader('X-Permitted-Cross-Domain-Policies', permittedPolicies) | ||
next() | ||
} | ||
} |
{ | ||
"name": "helmet-crossdomain", | ||
"author": "Evan Hahn <me@evanhahn.com> (https://evanhahn.com)", | ||
"description": "Serve a restrictive crossdomain.xml at your site's root.", | ||
"version": "0.2.0", | ||
"description": "Set the X-Permitted-Cross-Domain-Policies header in Express apps", | ||
"version": "0.3.0", | ||
"license": "MIT", | ||
@@ -11,3 +11,5 @@ "keywords": [ | ||
"connect", | ||
"crossdomain.xml" | ||
"crossdomain.xml", | ||
"x-permitted-cross-domain-policies", | ||
"flash" | ||
], | ||
@@ -20,3 +22,3 @@ "repository": { | ||
"engines": { | ||
"node": ">= 4" | ||
"node": ">= 6" | ||
}, | ||
@@ -29,5 +31,5 @@ "scripts": { | ||
"connect": "^3.6.6", | ||
"mocha": "^5.0.1", | ||
"standard": "^10.0.3", | ||
"supertest": "^3.0.0" | ||
"mocha": "^5.2.0", | ||
"standard": "^11.0.1", | ||
"supertest": "^3.1.0" | ||
}, | ||
@@ -34,0 +36,0 @@ "standard": { |
@@ -1,17 +0,26 @@ | ||
Helmet's crossdomain.xml middleware | ||
=================================== | ||
X-Permitted-Cross-Domain-Policies middleware | ||
============================================ | ||
[![Build Status](https://travis-ci.org/helmetjs/crossdomain.svg?branch=master)](https://travis-ci.org/helmetjs/crossdomain) | ||
Adobe defines [the spec for crossdomain.xml](https://www.adobe.com/devnet/adobe-media-server/articles/cross-domain-xml-for-streaming.html), a policy file that grants some Adobe products (like Flash) read access to resources on your domain. An unrestrictive policy could let others load things off your domain that you don't want. | ||
[_Looking for a changelog?_](https://github.com/helmetjs/helmet/blob/master/HISTORY.md) | ||
To serve up a restrictive policy: | ||
The `X-Permitted-Cross-Domain-Policies` header tells some web clients (like Adobe Flash or Adobe Acrobat) your domain's policy for loading cross-domain content. See the description on [OWASP](https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#X-Permitted-Cross-Domain-Policies) for more. | ||
Usage: | ||
```javascript | ||
var crossdomain = require('helmet-crossdomain') | ||
const crossdomain = require('helmet-crossdomain') | ||
// Sets X-Permitted-Cross-Domain-Policies: none | ||
app.use(crossdomain()) | ||
// You can use any of the following values: | ||
app.use(crossdomain({ permittedPolicies: 'none' })) | ||
app.use(crossdomain({ permittedPolicies: 'master-only' })) | ||
app.use(crossdomain({ permittedPolicies: 'by-content-type' })) | ||
app.use(crossdomain({ permittedPolicies: 'all' })) | ||
``` | ||
This serves the policy at `/crossdomain.xml`. | ||
The `by-ftp-type` is not currently supported. Please open an issue or pull request if you desire this feature! | ||
This doesn't make you wildly more secure, but it does help to keep Flash from loading things that you don't want it to. You might also *want* some of this behavior, in which case you should make your own less-restrictive policy and serve it. | ||
If you don't expect Adobe products to load data from your site, you get a minor security benefit by adding this header. |
@@ -1,47 +0,67 @@ | ||
var crossdomain = require('..') | ||
const crossdomain = require('..') | ||
var assert = require('assert') | ||
var connect = require('connect') | ||
var request = require('supertest') | ||
const assert = require('assert') | ||
const connect = require('connect') | ||
const request = require('supertest') | ||
var EXPECTED_POLICY = [ | ||
'<?xml version="1.0"?>', | ||
'<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">', | ||
'<cross-domain-policy>', | ||
'<site-control permitted-cross-domain-policies="none"/>', | ||
'</cross-domain-policy>' | ||
].join('') | ||
describe('crossdomain', function () { | ||
function app () { | ||
var result = connect() | ||
result.use(crossdomain()) | ||
result.use(function (req, res) { res.end('Hello world') }) | ||
function app (middleware) { | ||
const result = connect() | ||
result.use(middleware) | ||
result.use((req, res) => { res.end('Hello world') }) | ||
return result | ||
} | ||
it("doesn't respond to requests to /", function () { | ||
return request(app()).get('/').expect('Hello world') | ||
it('sets X-Permitted-Cross-Domain-Policies: none when called with no arguments', () => { | ||
return request(app(crossdomain())) | ||
.get('/') | ||
.expect('X-Permitted-Cross-Domain-Policies', 'none') | ||
.expect('Hello world') | ||
}) | ||
it("doesn't respond to requests to different casing", function () { | ||
return Promise.all([ | ||
request(app()).get('/CROSSDOMAIN.XML').expect('Hello world'), | ||
request(app()).get('/crossdomain.XML').expect('Hello world'), | ||
request(app()).get('/CROSSDOMAIN.xml').expect('Hello world') | ||
]) | ||
it('sets X-Permitted-Cross-Domain-Policies: none when called with an empty object', () => { | ||
return request(app(crossdomain({}))) | ||
.get('/') | ||
.expect('X-Permitted-Cross-Domain-Policies', 'none') | ||
.expect('Hello world') | ||
}) | ||
it('responds with proper XML when visiting /crossdomain.xml', function () { | ||
return request(app()).get('/crossdomain.xml') | ||
.expect('Content-Type', 'text/x-cross-domain-policy') | ||
.expect(EXPECTED_POLICY) | ||
it('can explicitly set the policy to "none"', () => { | ||
return request(app(crossdomain({ permittedPolicies: 'none' }))) | ||
.get('/') | ||
.expect('X-Permitted-Cross-Domain-Policies', 'none') | ||
.expect('Hello world') | ||
}) | ||
it('responds with proper XML when visiting /crossdomain.xml with query string', function () { | ||
return request(app()).get('/crossdomain.xml?hi=5') | ||
.expect('Content-Type', 'text/x-cross-domain-policy') | ||
.expect(EXPECTED_POLICY) | ||
it('can set the policy to "master-only"', () => { | ||
return request(app(crossdomain({ permittedPolicies: 'master-only' }))) | ||
.get('/') | ||
.expect('X-Permitted-Cross-Domain-Policies', 'master-only') | ||
.expect('Hello world') | ||
}) | ||
it('can set the policy to "by-content-type"', () => { | ||
return request(app(crossdomain({ permittedPolicies: 'by-content-type' }))) | ||
.get('/') | ||
.expect('X-Permitted-Cross-Domain-Policies', 'by-content-type') | ||
.expect('Hello world') | ||
}) | ||
it('can set the policy to "all"', () => { | ||
return request(app(crossdomain({ permittedPolicies: 'all' }))) | ||
.get('/') | ||
.expect('X-Permitted-Cross-Domain-Policies', 'all') | ||
.expect('Hello world') | ||
}) | ||
it('cannot set the policy to "by-ftp-filename"', () => { | ||
assert.throws(() => { crossdomain({ permittedPolicies: 'by-ftp-filename' }) }) | ||
}) | ||
it('cannot set the policy to invalid values', function () { | ||
assert.throws(() => { crossdomain({ permittedPolicies: '' }) }) | ||
assert.throws(() => { crossdomain({ permittedPolicies: null }) }) | ||
assert.throws(() => { crossdomain({ permittedPolicies: 'NONE' }) }) | ||
}) | ||
it('names its function and middleware', function () { | ||
@@ -48,0 +68,0 @@ assert.equal(crossdomain.name, 'crossdomain') |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
6335
83
27