diff --git a/CHANGELOG.md b/CHANGELOG.md index 07d1ec5..343ed12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Changed + +- **Breaking:** Where possible, increase TypeScript strictness around some strings. Only affects TypeScript users. See [#369](https://github.com/helmetjs/helmet/issues/369) + ### Removed - **Breaking:** Dropped support for Node 12 and 13. Node 14+ is now required diff --git a/middlewares/cross-origin-embedder-policy/index.ts b/middlewares/cross-origin-embedder-policy/index.ts index 43a166c..992f6b3 100644 --- a/middlewares/cross-origin-embedder-policy/index.ts +++ b/middlewares/cross-origin-embedder-policy/index.ts @@ -1,7 +1,7 @@ import { IncomingMessage, ServerResponse } from "http"; export interface CrossOriginEmbedderPolicyOptions { - policy?: string; + policy?: "require-corp" | "credentialless"; } const ALLOWED_POLICIES = new Set(["require-corp", "credentialless"]); diff --git a/middlewares/cross-origin-opener-policy/index.ts b/middlewares/cross-origin-opener-policy/index.ts index 1200ced..4c6bc03 100644 --- a/middlewares/cross-origin-opener-policy/index.ts +++ b/middlewares/cross-origin-opener-policy/index.ts @@ -1,7 +1,7 @@ import { IncomingMessage, ServerResponse } from "http"; export interface CrossOriginOpenerPolicyOptions { - policy?: string; + policy?: "same-origin" | "same-origin-allow-popups" | "unsafe-none"; } const ALLOWED_POLICIES = new Set([ diff --git a/middlewares/cross-origin-resource-policy/index.ts b/middlewares/cross-origin-resource-policy/index.ts index 74e6938..a24e91d 100644 --- a/middlewares/cross-origin-resource-policy/index.ts +++ b/middlewares/cross-origin-resource-policy/index.ts @@ -1,7 +1,7 @@ import { IncomingMessage, ServerResponse } from "http"; export interface CrossOriginResourcePolicyOptions { - policy?: string; + policy?: "same-origin" | "same-site" | "cross-origin"; } const ALLOWED_POLICIES = new Set(["same-origin", "same-site", "cross-origin"]); diff --git a/middlewares/referrer-policy/index.ts b/middlewares/referrer-policy/index.ts index 0e6e7e3..c3ca27c 100644 --- a/middlewares/referrer-policy/index.ts +++ b/middlewares/referrer-policy/index.ts @@ -1,10 +1,21 @@ import { IncomingMessage, ServerResponse } from "http"; +type ReferrerPolicyToken = + | "no-referrer" + | "no-referrer-when-downgrade" + | "same-origin" + | "origin" + | "strict-origin" + | "origin-when-cross-origin" + | "strict-origin-when-cross-origin" + | "unsafe-url" + | ""; + export interface ReferrerPolicyOptions { - policy?: string | string[]; + policy?: ReferrerPolicyToken | ReferrerPolicyToken[]; } -const ALLOWED_TOKENS = new Set([ +const ALLOWED_TOKENS = new Set([ "no-referrer", "no-referrer-when-downgrade", "same-origin", @@ -25,7 +36,7 @@ function getHeaderValueFromOptions({ throw new Error("Referrer-Policy received no policy tokens"); } - const tokensSeen = new Set(); + const tokensSeen = new Set(); tokens.forEach((token) => { if (!ALLOWED_TOKENS.has(token)) { throw new Error( diff --git a/middlewares/x-permitted-cross-domain-policies/index.ts b/middlewares/x-permitted-cross-domain-policies/index.ts index b991daa..96c0c44 100644 --- a/middlewares/x-permitted-cross-domain-policies/index.ts +++ b/middlewares/x-permitted-cross-domain-policies/index.ts @@ -1,7 +1,7 @@ import { IncomingMessage, ServerResponse } from "http"; export interface XPermittedCrossDomainPoliciesOptions { - permittedPolicies?: string; + permittedPolicies?: "none" | "master-only" | "by-content-type" | "all"; } const ALLOWED_PERMITTED_POLICIES = new Set([ diff --git a/test/cross-origin-embedder-policy.test.ts b/test/cross-origin-embedder-policy.test.ts index 9d956ce..7cc52b3 100644 --- a/test/cross-origin-embedder-policy.test.ts +++ b/test/cross-origin-embedder-policy.test.ts @@ -18,7 +18,7 @@ describe("Cross-Origin-Embedder-Policy middleware", () => { ); }); - ["require-corp", "credentialless"].forEach((policy) => { + (["require-corp", "credentialless"] as const).forEach((policy) => { it(`sets "Cross-Origin-Embedder-Policy: ${policy}" when told to`, async () => { await check(crossOriginEmbedderPolicy({ policy }), { "cross-origin-embedder-policy": policy, @@ -29,16 +29,16 @@ describe("Cross-Origin-Embedder-Policy middleware", () => { it("throws when setting the policy to an invalid value", () => { const invalidValues = [ "", - "NONE", - "by-ftp-filename", - 123 as any, - null as any, - new String("none") as any, + "foo", + "CREDENTIALLESS", + 123, + null, + new String("credentialless"), ]; for (const policy of invalidValues) { - expect(() => crossOriginEmbedderPolicy({ policy })).toThrow( - /^Cross-Origin-Embedder-Policy does not support / - ); + expect(() => + crossOriginEmbedderPolicy({ policy: policy as any }) + ).toThrow(/^Cross-Origin-Embedder-Policy does not support /); } }); }); diff --git a/test/cross-origin-opener-policy.test.ts b/test/cross-origin-opener-policy.test.ts index c7424a6..07ff10a 100644 --- a/test/cross-origin-opener-policy.test.ts +++ b/test/cross-origin-opener-policy.test.ts @@ -15,7 +15,7 @@ describe("Cross-Origin-Opener-Policy middleware", () => { ); }); - ["same-origin", "same-origin-allow-popups", "unsafe-none"].forEach( + (["same-origin", "same-origin-allow-popups", "unsafe-none"] as const).forEach( (policy) => { it(`sets "Cross-Origin-Opener-Policy: ${policy}" when told to`, async () => { await check(crossOriginOpenerPolicy({ policy }), { @@ -28,14 +28,14 @@ describe("Cross-Origin-Opener-Policy middleware", () => { it("throws when setting the policy to an invalid value", () => { const invalidValues = [ "", - "NONE", - "by-ftp-filename", - 123 as any, - null as any, - new String("none") as any, + "foo", + "SAME-ORIGIN", + 123, + null, + new String("same-origin"), ]; for (const policy of invalidValues) { - expect(() => crossOriginOpenerPolicy({ policy })).toThrow( + expect(() => crossOriginOpenerPolicy({ policy: policy as any })).toThrow( /^Cross-Origin-Opener-Policy does not support / ); } diff --git a/test/cross-origin-resource-policy.test.ts b/test/cross-origin-resource-policy.test.ts index 1c3f535..f725b23 100644 --- a/test/cross-origin-resource-policy.test.ts +++ b/test/cross-origin-resource-policy.test.ts @@ -18,7 +18,7 @@ describe("Cross-Origin-Resource-Policy middleware", () => { ); }); - ["same-origin", "same-site", "cross-origin"].forEach((policy) => { + (["same-origin", "same-site", "cross-origin"] as const).forEach((policy) => { it(`sets "Cross-Origin-Resource-Policy: ${policy}" when told to`, async () => { await check(crossOriginResourcePolicy({ policy }), { "cross-origin-resource-policy": policy, @@ -29,16 +29,16 @@ describe("Cross-Origin-Resource-Policy middleware", () => { it("throws when setting the policy to an invalid value", () => { const invalidValues = [ "", - "NONE", - "by-ftp-filename", - 123 as any, - null as any, - new String("none") as any, + "foo", + "CROSS-ORIGIN", + 123, + null, + new String("none"), ]; for (const policy of invalidValues) { - expect(() => crossOriginResourcePolicy({ policy })).toThrow( - /^Cross-Origin-Resource-Policy does not support / - ); + expect(() => + crossOriginResourcePolicy({ policy: policy as any }) + ).toThrow(/^Cross-Origin-Resource-Policy does not support /); } }); }); diff --git a/test/referrer-policy.test.ts b/test/referrer-policy.test.ts index b352458..fb07ca4 100644 --- a/test/referrer-policy.test.ts +++ b/test/referrer-policy.test.ts @@ -17,17 +17,19 @@ describe("Referrer-Policy middleware", () => { }); }); - [ - "no-referrer", - "no-referrer-when-downgrade", - "same-origin", - "origin", - "strict-origin", - "origin-when-cross-origin", - "strict-origin-when-cross-origin", - "unsafe-url", - "", - ].forEach((policy) => { + ( + [ + "no-referrer", + "no-referrer-when-downgrade", + "same-origin", + "origin", + "strict-origin", + "origin-when-cross-origin", + "strict-origin-when-cross-origin", + "unsafe-url", + "", + ] as const + ).forEach((policy) => { it(`can set the header to "${policy}" by specifying it as a string`, async () => { await check(referrerPolicy({ policy }), { "referrer-policy": policy, @@ -48,12 +50,10 @@ describe("Referrer-Policy middleware", () => { }); it("fails with a bad policy", () => { - expect(referrerPolicy.bind(null, { policy: "garbage" })).toThrow(); - expect(referrerPolicy.bind(null, { policy: "sameorigin" })).toThrow(); - expect(referrerPolicy.bind(null, { policy: 123 as any })).toThrow(); - expect(referrerPolicy.bind(null, { policy: false as any })).toThrow(); - expect(referrerPolicy.bind(null, { policy: null as any })).toThrow(); - expect(referrerPolicy.bind(null, { policy: {} as any })).toThrow(); + const invalidValues = ["foo", "sameorigin", "ORIGIN", 123, false, null, {}]; + for (const policy of invalidValues) { + expect(referrerPolicy.bind(null, { policy: policy as any })).toThrow(); + } }); it("fails with an empty array", () => { diff --git a/test/x-permitted-cross-domain-policies.test.ts b/test/x-permitted-cross-domain-policies.test.ts index ee1d2cd..ac74fa6 100644 --- a/test/x-permitted-cross-domain-policies.test.ts +++ b/test/x-permitted-cross-domain-policies.test.ts @@ -18,7 +18,7 @@ describe("X-Permitted-Cross-Domain-Policies middleware", () => { ); }); - ["none", "master-only", "by-content-type", "all"].forEach( + (["none", "master-only", "by-content-type", "all"] as const).forEach( (permittedPolicies) => { it(`sets "X-Permitted-Cross-Domain-Policies: ${permittedPolicies}" when told to`, async () => { await check(xPermittedCrossDomainPolicies({ permittedPolicies }), { @@ -33,13 +33,15 @@ describe("X-Permitted-Cross-Domain-Policies middleware", () => { "", "NONE", "by-ftp-filename", - 123 as any, - null as any, - new String("none") as any, + 123, + null, + new String("none"), ]; for (const permittedPolicies of invalidValues) { expect(() => - xPermittedCrossDomainPolicies({ permittedPolicies }) + xPermittedCrossDomainPolicies({ + permittedPolicies: permittedPolicies as any, + }) ).toThrow(/^X-Permitted-Cross-Domain-Policies does not support /); } });