diff --git a/CHANGELOG.md b/CHANGELOG.md index 87878f3c..ec4b3ea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Changed - `helmet.hidePoweredBy` is no longer a separate package. This should have no effect on end users. +- `helmet.noSniff` is no longer a separate package. This should have no effect on end users. ## 3.23.3 - 2020-06-26 diff --git a/index.ts b/index.ts index 745565b5..7e05e7fe 100644 --- a/index.ts +++ b/index.ts @@ -1,5 +1,6 @@ import { IncomingMessage, ServerResponse } from "http"; import expectCt from "./middlewares/expect-ct"; +import xContentTypeOptions from "./middlewares/x-content-type-options"; import xDnsPrefetchControl from "./middlewares/x-dns-prefetch-control"; import xDownloadOptions from "./middlewares/x-download-options"; import xFrameOptions from "./middlewares/x-frame-options"; @@ -136,7 +137,7 @@ helmet.frameguard = xFrameOptions; helmet.hidePoweredBy = xPoweredBy; helmet.hsts = require("hsts"); helmet.ieNoOpen = xDownloadOptions; -helmet.noSniff = require("dont-sniff-mimetype"); +helmet.noSniff = xContentTypeOptions; helmet.permittedCrossDomainPolicies = require("helmet-crossdomain"); helmet.referrerPolicy = require("referrer-policy"); helmet.xssFilter = require("x-xss-protection"); diff --git a/middlewares/x-content-type-options/CHANGELOG.md b/middlewares/x-content-type-options/CHANGELOG.md new file mode 100644 index 00000000..b9ef0204 --- /dev/null +++ b/middlewares/x-content-type-options/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +## 1.1.0 - 2019-05-11 + +### Added + +- Added TypeScript type definitions. See [#4](https://github.com/helmetjs/dont-sniff-mimetype/issues/4) and [helmetjs/helmet#188](https://github.com/helmetjs/helmet/issues/188) +- Created a changelog + +### Changed + +- Updated some package metadata +- Excluded some files from npm package + +Changes in versions 1.0.0 and below can be found in [Helmet's changelog](https://github.com/helmetjs/helmet/blob/master/CHANGELOG.md). diff --git a/middlewares/x-content-type-options/README.md b/middlewares/x-content-type-options/README.md new file mode 100644 index 00000000..10b5a8ab --- /dev/null +++ b/middlewares/x-content-type-options/README.md @@ -0,0 +1,16 @@ +# X-Content-Type-Options middleware + +Some browsers will try to "sniff" mimetypes. For example, if my server serves _file.txt_ with a _text/plain_ content-type, some browsers can still run that file with ``. Many browsers will allow _file.js_ to be run even if the content-type isn't for JavaScript. + +Browsers' same-origin policies generally prevent remote resources from being loaded dangerously, but vulnerabilities in web browsers can cause this to be abused. Some browsers, like [Chrome](https://developers.google.com/web/updates/2018/07/site-isolation), will further isolate memory if the `X-Content-Type-Options` header is seen. + +There are [some other vulnerabilities](http://miki.it/blog/2014/7/8/abusing-jsonp-with-rosetta-flash/), too. + +This middleware prevents Chrome, Opera 13+, IE 8+ and [Firefox 50+](https://bugzilla.mozilla.org/show_bug.cgi?id=471020) from doing this sniffing. The following example sets the `X-Content-Type-Options` header to its only option, `nosniff`: + +```javascript +const dontSniffMimetype = require("dont-sniff-mimetype"); +app.use(dontSniffMimetype()); +``` + +[MSDN has a good description](http://msdn.microsoft.com/en-us/library/gg622941%28v=vs.85%29.aspx) of how browsers behave when this header is sent. diff --git a/middlewares/x-content-type-options/index.ts b/middlewares/x-content-type-options/index.ts new file mode 100644 index 00000000..24d9c9db --- /dev/null +++ b/middlewares/x-content-type-options/index.ts @@ -0,0 +1,15 @@ +import { IncomingMessage, ServerResponse } from "http"; + +function xContentTypeOptions() { + return function xContentTypeOptionsMiddleware( + _req: IncomingMessage, + res: ServerResponse, + next: () => void + ) { + res.setHeader("X-Content-Type-Options", "nosniff"); + next(); + }; +} + +module.exports = xContentTypeOptions; +export default xContentTypeOptions; diff --git a/middlewares/x-content-type-options/package-files.json b/middlewares/x-content-type-options/package-files.json new file mode 100644 index 00000000..962389e9 --- /dev/null +++ b/middlewares/x-content-type-options/package-files.json @@ -0,0 +1 @@ +["index.js", "index.d.ts"] diff --git a/middlewares/x-content-type-options/package-overrides.json b/middlewares/x-content-type-options/package-overrides.json new file mode 100644 index 00000000..7a4e0a86 --- /dev/null +++ b/middlewares/x-content-type-options/package-overrides.json @@ -0,0 +1,7 @@ +{ + "name": "dont-sniff-mimetype", + "description": "Middleware to prevent mimetype from being sniffed", + "version": "1.1.0", + "keywords": ["express", "security", "mimetype", "x-content-type-options"], + "homepage": "https://helmetjs.github.io/docs/dont-sniff-mimetype" +} diff --git a/package-lock.json b/package-lock.json index 8c919210..f3fd4173 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2310,11 +2310,6 @@ } } }, - "dont-sniff-mimetype": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.1.0.tgz", - "integrity": "sha512-ZjI4zqTaxveH2/tTlzS1wFp+7ncxNZaIEWYg3lzZRHkKf5zPT/MnEG6WL0BhHMJUabkh8GeU5NL5j+rEUCb7Ug==" - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", diff --git a/package.json b/package.json index 47755948..aeaa6fb7 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "SECURITY.md", "dist/index.js", "dist/middlewares/expect-ct/index.js", + "dist/middlewares/x-content-type-options/index.js", "dist/middlewares/x-dns-prefetch-control/index.js", "dist/middlewares/x-download-options/index.js", "dist/middlewares/x-frame-options/index.js", @@ -45,7 +46,6 @@ ], "dependencies": { "depd": "2.0.0", - "dont-sniff-mimetype": "1.1.0", "feature-policy": "0.3.0", "helmet-crossdomain": "0.4.0", "helmet-csp": "2.10.0", diff --git a/test/index.test.ts b/test/index.test.ts index 5068c25f..0dfd0043 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -4,6 +4,7 @@ import { IncomingMessage, ServerResponse } from "http"; import connect = require("connect"); import request = require("supertest"); import expectCt from "../middlewares/expect-ct"; +import xContentTypeOptions from "../middlewares/x-content-type-options"; import xDnsPrefetchControl from "../middlewares/x-dns-prefetch-control"; import xDowloadOptions from "../middlewares/x-download-options"; import xFrameOptions from "../middlewares/x-frame-options"; @@ -15,9 +16,8 @@ describe("helmet", function () { expect(helmet.dnsPrefetchControl.name).toBe(xDnsPrefetchControl.name); }); - it('aliases "dont-sniff-mimetype"', function () { - const pkg = require("dont-sniff-mimetype"); - expect(helmet.noSniff).toBe(pkg); + it("aliases the X-Content-Type-Options middleware to helmet.noSniff", () => { + expect(helmet.noSniff.name).toBe(xContentTypeOptions.name); }); it("aliases the Expect-CT middleware to helmet.expectCt", function () { diff --git a/test/x-content-type-options.test.ts b/test/x-content-type-options.test.ts new file mode 100644 index 00000000..14d716d9 --- /dev/null +++ b/test/x-content-type-options.test.ts @@ -0,0 +1,10 @@ +import { check } from "./helpers"; +import xContentTypeOptions from "../middlewares/x-content-type-options"; + +describe("X-Content-Type-Options middleware", () => { + it('sets "X-Content-Type-Options: nosniff"', async () => { + await check(xContentTypeOptions(), { + "x-content-type-options": "nosniff", + }); + }); +});