Skip to content

Commit

Permalink
Increase TypeScript strictness for policies
Browse files Browse the repository at this point in the history
Before, the checks were all at runtime. Now they're at runtime and
compile time.

See [#369][0].

[0]: #369
  • Loading branch information
EvanHahn committed Jul 23, 2022
1 parent 3d85834 commit fdc3f2a
Show file tree
Hide file tree
Showing 17 changed files with 73 additions and 37 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion 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"]);
Expand Down
2 changes: 1 addition & 1 deletion 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([
Expand Down
6 changes: 6 additions & 0 deletions middlewares/cross-origin-resource-policy/CHANGELOG.md
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Changed

- **Breaking:** increase TypeScript strictness around arguments. Only affects TypeScript users. See [helmetjs/helmet#369](https://github.com/helmetjs/helmet/issues/369)

## 0.3.0 - 2021-04-17

### Added
Expand Down
2 changes: 1 addition & 1 deletion 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"]);
Expand Down
8 changes: 7 additions & 1 deletion middlewares/referrer-policy/CHANGELOG.md
@@ -1,10 +1,16 @@
# Changelog

## Unreleased

### Changed

- **Breaking:** increase TypeScript strictness around arguments. Only affects TypeScript users. See [helmetjs/helmet#369](https://github.com/helmetjs/helmet/issues/369)

## 2.0.0 - Unreleased

### Removed

- Dropped support for old Node versions. Node 10+ is now required
- **Breaking:** Dropped support for old Node versions. Node 10+ is now required

## 1.2.0 - 2019-05-03

Expand Down
17 changes: 14 additions & 3 deletions 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<string>([
const ALLOWED_TOKENS = new Set<ReferrerPolicyToken>([
"no-referrer",
"no-referrer-when-downgrade",
"same-origin",
Expand All @@ -25,7 +36,7 @@ function getHeaderValueFromOptions({
throw new Error("Referrer-Policy received no policy tokens");
}

const tokensSeen = new Set<string>();
const tokensSeen = new Set<ReferrerPolicyToken>();
tokens.forEach((token) => {
if (!ALLOWED_TOKENS.has(token)) {
throw new Error(
Expand Down
2 changes: 1 addition & 1 deletion middlewares/x-frame-options/CHANGELOG.md
Expand Up @@ -4,7 +4,7 @@

### Changed

- Add TypeScript editor autocomplete. See [#322](https://github.com/helmetjs/helmet/pull/322)
- **Breaking:** increase TypeScript strictness around arguments. Only affects TypeScript users. See [helmetjs/helmet#369](https://github.com/helmetjs/helmet/issues/369)

## 4.0.0 - 2020-12-21

Expand Down
5 changes: 2 additions & 3 deletions middlewares/x-frame-options/index.ts
@@ -1,12 +1,11 @@
import { IncomingMessage, ServerResponse } from "http";

export interface XFrameOptionsOptions {
// This offers autocomplete while still supporting regular `string`s.
action?: "DENY" | "SAMEORIGIN" | (string & { _?: never });
action?: "deny" | "sameorigin";
}

function getHeaderValueFromOptions({
action = "SAMEORIGIN",
action = "sameorigin",
}: Readonly<XFrameOptionsOptions>): string {
const normalizedAction =
typeof action === "string" ? action.toUpperCase() : action;
Expand Down
6 changes: 5 additions & 1 deletion middlewares/x-permitted-cross-domain-policies/CHANGELOG.md
Expand Up @@ -2,9 +2,13 @@

## Unreleased

### Changed

- **Breaking:** increase TypeScript strictness around arguments. Only affects TypeScript users. See [helmetjs/helmet#369](https://github.com/helmetjs/helmet/issues/369)

### Removed

- Dropped support for old Node versions. Node 10+ is now required
- Dropped support for old Node versions. Node 14+ is now required

## 0.5.0 - 2019-09-01

Expand Down
2 changes: 1 addition & 1 deletion 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([
Expand Down
2 changes: 1 addition & 1 deletion test/cross-origin-embedder-policy.test.ts
Expand Up @@ -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,
Expand Down
2 changes: 1 addition & 1 deletion test/cross-origin-opener-policy.test.ts
Expand Up @@ -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 }), {
Expand Down
2 changes: 1 addition & 1 deletion test/cross-origin-resource-policy.test.ts
Expand Up @@ -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,
Expand Down
24 changes: 13 additions & 11 deletions test/referrer-policy.test.ts
Expand Up @@ -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,
Expand Down
22 changes: 13 additions & 9 deletions test/x-frame-options.test.ts
Expand Up @@ -18,38 +18,42 @@ describe("X-Frame-Options middleware", () => {
});

it('can set "X-Frame-Options: DENY"', async () => {
await check(xFrameOptions({ action: "DENY" }), {
await check(xFrameOptions({ action: "deny" }), {
"x-frame-options": "DENY",
});
await check(xFrameOptions({ action: "deny" }), {

// These are not allowed by the types, but are supported.
await check(xFrameOptions({ action: "DENY" as any }), {
"x-frame-options": "DENY",
});
await check(xFrameOptions({ action: "deNY" }), {
await check(xFrameOptions({ action: "deNY" as any }), {
"x-frame-options": "DENY",
});
});

it('can set "X-Frame-Options: SAMEORIGIN" when specified', async () => {
await check(xFrameOptions({ action: "SAMEORIGIN" }), {
await check(xFrameOptions({ action: "sameorigin" }), {
"x-frame-options": "SAMEORIGIN",
});
await check(xFrameOptions({ action: "sameorigin" }), {

// These are not allowed by the types, but are supported.
await check(xFrameOptions({ action: "SAMEORIGIN" as any }), {
"x-frame-options": "SAMEORIGIN",
});
await check(xFrameOptions({ action: "sameORIGIN" }), {
await check(xFrameOptions({ action: "sameORIGIN" as any }), {
"x-frame-options": "SAMEORIGIN",
});
await check(xFrameOptions({ action: "SAME-ORIGIN" }), {
await check(xFrameOptions({ action: "SAME-ORIGIN" as any }), {
"x-frame-options": "SAMEORIGIN",
});
await check(xFrameOptions({ action: "same-origin" }), {
await check(xFrameOptions({ action: "same-origin" as any }), {
"x-frame-options": "SAMEORIGIN",
});
});

it("throws when passed invalid actions", () => {
for (const action of ["allow-from", "ALLOW-FROM"]) {
expect(() => xFrameOptions({ action })).toThrow(
expect(() => xFrameOptions({ action: action as any })).toThrow(
/^X-Frame-Options no longer supports `ALLOW-FROM` due to poor browser support. See <https:\/\/github.com\/helmetjs\/helmet\/wiki\/How-to-use-X%E2%80%93Frame%E2%80%93Options's-%60ALLOW%E2%80%93FROM%60-directive> for more info.$/
);
}
Expand Down
2 changes: 1 addition & 1 deletion test/x-permitted-cross-domain-policies.test.ts
Expand Up @@ -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 }), {
Expand Down

0 comments on commit fdc3f2a

Please sign in to comment.