diff --git a/api/.gitignore b/api/.gitignore
index bed7e484..dd1e2b57 100644
--- a/api/.gitignore
+++ b/api/.gitignore
@@ -3,3 +3,4 @@ docs/*.md
# subsequent PRs will un-ignore areas that are under review until
# all docs are complete and we can drop this ignore file entirely
+!docs/tough-cookie.prefixsecurity.md
diff --git a/api/docs/tough-cookie.prefixsecurity.md b/api/docs/tough-cookie.prefixsecurity.md
new file mode 100644
index 00000000..8887f1ab
--- /dev/null
+++ b/api/docs/tough-cookie.prefixsecurity.md
@@ -0,0 +1,83 @@
+
+
+[Home](./index.md) > [tough-cookie](./tough-cookie.md) > [PrefixSecurity](./tough-cookie.prefixsecurity.md)
+
+## PrefixSecurity enum
+
+Cookie prefixes are a way to indicate that a given cookie was set with a set of attributes simply by inspecting the first few characters of the cookie's name. These are defined in [RFC6265bis - Section 4.1.3](https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-13#section-4.1.3).
+
+The following values can be used to configure how a [CookieJar](./tough-cookie.cookiejar.md) enforces attribute restrictions for Cookie prefixes.
+
+**Signature:**
+
+```typescript
+export declare enum PrefixSecurity
+```
+
+## Enumeration Members
+
+
+
+Member
+
+
+ |
+
+Value
+
+
+ |
+
+Description
+
+
+ |
+
+
+DISABLED
+
+
+ |
+
+`"unsafe-disabled"`
+
+
+ |
+
+Disables cookie prefix checking.
+
+
+ |
+
+
+SILENT
+
+
+ |
+
+`"silent"`
+
+
+ |
+
+Enable cookie prefix checking but silently ignores the cookie if conditions are not met. This is the default configuration for a [CookieJar](./tough-cookie.cookiejar.md).
+
+
+ |
+
+
+STRICT
+
+
+ |
+
+`"strict"`
+
+
+ |
+
+Enables cookie prefix checking and will raise an error if conditions are not met.
+
+
+ |
+
diff --git a/api/tough-cookie.api.md b/api/tough-cookie.api.md
index eca22a33..5f1cbce7 100644
--- a/api/tough-cookie.api.md
+++ b/api/tough-cookie.api.md
@@ -6,19 +6,21 @@
///
+// Warning: (ae-forgotten-export) The symbol "Nullable" needs to be exported by the entry point index.d.ts
+//
// @public (undocumented)
-export function canonicalDomain(str: string | null): string | null;
+export function canonicalDomain(str: Nullable): string | undefined;
// @public (undocumented)
export class Cookie {
// Warning: (ae-forgotten-export) The symbol "CreateCookieOptions" needs to be exported by the entry point index.d.ts
constructor(options?: CreateCookieOptions);
// (undocumented)
- canonicalizedDomain(): string | null;
+ canonicalizedDomain(): string | undefined;
// (undocumented)
- cdomain(): string | null;
+ cdomain(): string | undefined;
// (undocumented)
- clone(): Cookie | null;
+ clone(): Cookie | undefined;
// (undocumented)
static cookiesCreated: number;
// (undocumented)
@@ -100,7 +102,7 @@ export function cookieCompare(a: Cookie, b: Cookie): number;
// @public (undocumented)
export class CookieJar {
// Warning: (ae-forgotten-export) The symbol "CreateCookieJarOptions" needs to be exported by the entry point index.d.ts
- constructor(store?: Store | null | undefined, options?: CreateCookieJarOptions | boolean);
+ constructor(store?: Nullable, options?: CreateCookieJarOptions | boolean);
// (undocumented)
clone(callback: Callback): void;
// (undocumented)
@@ -198,29 +200,29 @@ export class CookieJar {
}
// @public (undocumented)
-export function defaultPath(path?: string | null): string;
+export function defaultPath(path?: Nullable): string;
// @public (undocumented)
-export function domainMatch(str?: string | null, domStr?: string | null, canonicalize?: boolean): boolean | null;
+export function domainMatch(str?: Nullable, domStr?: Nullable, canonicalize?: boolean): boolean | undefined;
// @public
export function formatDate(date: Date): string;
// @public (undocumented)
-export const fromJSON: (str: unknown) => Cookie | null;
+export const fromJSON: (str: unknown) => Cookie | undefined;
// Warning: (ae-forgotten-export) The symbol "GetPublicSuffixOptions" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
-export function getPublicSuffix(domain: string, options?: GetPublicSuffixOptions): string | null;
+export function getPublicSuffix(domain: string, options?: GetPublicSuffixOptions): string | undefined;
// @public (undocumented)
export class MemoryCookieStore extends Store {
constructor();
// (undocumented)
- findCookie(domain: string | null, path: string | null, key: string | undefined): Promise;
+ findCookie(domain: Nullable, path: Nullable, key: Nullable): Promise;
// (undocumented)
- findCookie(domain: string | null, path: string | null, key: string | undefined, callback: Callback): void;
+ findCookie(domain: Nullable, path: Nullable, key: Nullable, callback: Callback): void;
// (undocumented)
findCookies(domain: string, path: string, allowSpecialUseDomain?: boolean): Promise;
// (undocumented)
@@ -264,38 +266,38 @@ export class ParameterError extends Error {
// @public (undocumented)
export const parse: (str: string, options?: {
loose?: boolean | undefined;
-} | undefined) => Cookie | null | undefined;
+} | undefined) => Cookie | undefined;
// @public (undocumented)
-export function parseDate(str: string | undefined | null): Date | undefined;
+export function parseDate(str: Nullable): Date | undefined;
// @public (undocumented)
export function pathMatch(reqPath: string, cookiePath: string): boolean;
// @public (undocumented)
-export function permuteDomain(domain: string, allowSpecialUseDomain?: boolean): string[] | null;
+export function permuteDomain(domain: string, allowSpecialUseDomain?: boolean): string[] | undefined;
// @public
export function permutePath(path: string): string[];
-// @public (undocumented)
-export const PrefixSecurityEnum: Readonly<{
- SILENT: "silent";
- STRICT: "strict";
- DISABLED: "unsafe-disabled";
-}>;
+// @public
+export enum PrefixSecurity {
+ DISABLED = "unsafe-disabled",
+ SILENT = "silent",
+ STRICT = "strict"
+}
// @public (undocumented)
export class Store {
constructor();
// (undocumented)
- findCookie(domain: string | null, path: string | null, key: string | undefined): Promise;
+ findCookie(domain: Nullable, path: Nullable, key: Nullable): Promise;
// (undocumented)
- findCookie(domain: string | null, path: string | null, key: string | undefined, callback: Callback): void;
+ findCookie(domain: Nullable, path: Nullable, key: Nullable, callback: Callback): void;
// (undocumented)
- findCookies(domain: string | null, path: string | null, allowSpecialUseDomain?: boolean): Promise;
+ findCookies(domain: Nullable, path: Nullable, allowSpecialUseDomain?: boolean): Promise;
// (undocumented)
- findCookies(domain: string | null, path: string | null, allowSpecialUseDomain?: boolean, callback?: Callback): void;
+ findCookies(domain: Nullable, path: Nullable, allowSpecialUseDomain?: boolean, callback?: Callback): void;
// (undocumented)
getAllCookies(): Promise;
// (undocumented)
@@ -309,13 +311,13 @@ export class Store {
// (undocumented)
removeAllCookies(callback: ErrorCallback): void;
// (undocumented)
- removeCookie(domain: string | null | undefined, path: string | null | undefined, key: string | null | undefined): Promise;
+ removeCookie(domain: Nullable, path: Nullable, key: Nullable): Promise;
// (undocumented)
- removeCookie(domain: string | null | undefined, path: string | null | undefined, key: string | null | undefined, callback: ErrorCallback): void;
+ removeCookie(domain: Nullable, path: Nullable, key: Nullable, callback: ErrorCallback): void;
// (undocumented)
- removeCookies(domain: string, path: string | null): Promise;
+ removeCookies(domain: string, path: Nullable): Promise;
// (undocumented)
- removeCookies(domain: string, path: string | null, callback: ErrorCallback): void;
+ removeCookies(domain: string, path: Nullable, callback: ErrorCallback): void;
// (undocumented)
synchronous: boolean;
// (undocumented)
diff --git a/lib/__tests__/cookiePrefixes.spec.ts b/lib/__tests__/cookiePrefixes.spec.ts
index 770f53a9..96759fb9 100644
--- a/lib/__tests__/cookiePrefixes.spec.ts
+++ b/lib/__tests__/cookiePrefixes.spec.ts
@@ -1,4 +1,4 @@
-import { PrefixSecurityEnum } from '../cookie/constants'
+import { PrefixSecurity } from '../cookie/constants'
import { CookieJar } from '../cookie/cookieJar'
let cookieJar: CookieJar
@@ -11,7 +11,7 @@ describe('When `prefixSecurity` is enabled for `CookieJar`', () => {
cookieJar = new CookieJar(null, {
prefixSecurity: 'silent',
})
- expect(cookieJar.prefixSecurity).toBe(PrefixSecurityEnum.SILENT)
+ expect(cookieJar.prefixSecurity).toBe(PrefixSecurity.SILENT)
})
describe('__Secure prefix', () => {
@@ -106,7 +106,7 @@ describe('When `prefixSecurity` is enabled for `CookieJar`', () => {
cookieJar = new CookieJar(null, {
prefixSecurity: 'strict',
})
- expect(cookieJar.prefixSecurity).toBe(PrefixSecurityEnum.STRICT)
+ expect(cookieJar.prefixSecurity).toBe(PrefixSecurity.STRICT)
})
describe('__Secure prefix', () => {
@@ -173,7 +173,7 @@ describe('When `prefixSecurity` is enabled for `CookieJar`', () => {
cookieJar = new CookieJar(null, {
prefixSecurity: 'unsafe-disabled',
})
- expect(cookieJar.prefixSecurity).toBe(PrefixSecurityEnum.DISABLED)
+ expect(cookieJar.prefixSecurity).toBe(PrefixSecurity.DISABLED)
})
describe('__Secure prefix', () => {
diff --git a/lib/cookie/constants.ts b/lib/cookie/constants.ts
index 278449b3..335cd5b5 100644
--- a/lib/cookie/constants.ts
+++ b/lib/cookie/constants.ts
@@ -1,8 +1,24 @@
-export const PrefixSecurityEnum = Object.freeze({
- SILENT: 'silent',
- STRICT: 'strict',
- DISABLED: 'unsafe-disabled',
-})
+/**
+ * Cookie prefixes are a way to indicate that a given cookie was set with a set of attributes simply by inspecting the
+ * first few characters of the cookie's name. These are defined in {@link https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis-13#section-4.1.3 | RFC6265bis - Section 4.1.3}.
+ *
+ * The following values can be used to configure how a {@link CookieJar} enforces attribute restrictions for Cookie prefixes.
+ * @public
+ */
+export enum PrefixSecurity {
+ /**
+ * Enable cookie prefix checking but silently ignores the cookie if conditions are not met. This is the default configuration for a {@link CookieJar}.
+ */
+ SILENT = 'silent',
+ /**
+ * Enables cookie prefix checking and will raise an error if conditions are not met.
+ */
+ STRICT = 'strict',
+ /**
+ * Disables cookie prefix checking.
+ */
+ DISABLED = 'unsafe-disabled',
+}
const IP_V6_REGEX = `
\\[?(?:
diff --git a/lib/cookie/cookieJar.ts b/lib/cookie/cookieJar.ts
index ec881ae9..868d0ef3 100644
--- a/lib/cookie/cookieJar.ts
+++ b/lib/cookie/cookieJar.ts
@@ -9,16 +9,16 @@ import { pathMatch } from '../pathMatch'
import { Cookie } from './cookie'
import {
Callback,
- ErrorCallback,
- Nullable,
createPromiseCallback,
+ ErrorCallback,
inOperator,
+ Nullable,
safeToString,
} from '../utils'
import { canonicalDomain } from './canonicalDomain'
import {
IP_V6_REGEX_OBJECT,
- PrefixSecurityEnum,
+ PrefixSecurity,
SerializedCookieJar,
} from './constants'
import { defaultPath } from './defaultPath'
@@ -135,8 +135,7 @@ function isHostPrefixConditionMet(cookie: Cookie): boolean {
)
}
-type PrefixSecurityValue =
- (typeof PrefixSecurityEnum)[keyof typeof PrefixSecurityEnum]
+type PrefixSecurityValue = (typeof PrefixSecurity)[keyof typeof PrefixSecurity]
function getNormalizedPrefixSecurity(
prefixSecurity: string,
): PrefixSecurityValue {
@@ -144,14 +143,14 @@ function getNormalizedPrefixSecurity(
const normalizedPrefixSecurity = prefixSecurity.toLowerCase()
/* The three supported options */
switch (normalizedPrefixSecurity) {
- case PrefixSecurityEnum.STRICT:
- case PrefixSecurityEnum.SILENT:
- case PrefixSecurityEnum.DISABLED:
+ case PrefixSecurity.STRICT:
+ case PrefixSecurity.SILENT:
+ case PrefixSecurity.DISABLED:
return normalizedPrefixSecurity
}
}
/* Default is SILENT */
- return PrefixSecurityEnum.SILENT
+ return PrefixSecurity.SILENT
}
export class CookieJar {
@@ -402,9 +401,9 @@ export class CookieJar {
/* 6265bis-02 S5.4 Steps 15 & 16 */
const ignoreErrorForPrefixSecurity =
- this.prefixSecurity === PrefixSecurityEnum.SILENT
+ this.prefixSecurity === PrefixSecurity.SILENT
const prefixSecurityDisabled =
- this.prefixSecurity === PrefixSecurityEnum.DISABLED
+ this.prefixSecurity === PrefixSecurity.DISABLED
/* If prefix checking is not disabled ...*/
if (!prefixSecurityDisabled) {
let errorFound = false
diff --git a/lib/cookie/index.ts b/lib/cookie/index.ts
index 7b94bdd4..89495df0 100644
--- a/lib/cookie/index.ts
+++ b/lib/cookie/index.ts
@@ -7,7 +7,7 @@ export { ParameterError } from '../validators'
export { version } from '../version'
export { canonicalDomain } from './canonicalDomain'
-export { PrefixSecurityEnum } from './constants'
+export { PrefixSecurity } from './constants'
export { Cookie } from './cookie'
export { cookieCompare } from './cookieCompare'
export { CookieJar } from './cookieJar'
diff --git a/test/cookie_prefixes_test.js b/test/cookie_prefixes_test.js
index 20f9fb04..ef8624a1 100644
--- a/test/cookie_prefixes_test.js
+++ b/test/cookie_prefixes_test.js
@@ -33,7 +33,7 @@ const vows = require("vows");
const assert = require("assert");
const tough = require("../dist/cookie");
const CookieJar = tough.CookieJar;
-const PrefixSecurityEnum = tough.PrefixSecurityEnum;
+const PrefixSecurity = tough.PrefixSecurity;
vows
.describe("Cookie Prefixes")
@@ -45,7 +45,7 @@ vows
return new CookieJar(null, { prefixSecurity: "silent" });
},
"with no Secure attribute, should fail silently": function(cj) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Secure-SID=12345; Domain=example.com",
"http://www.example.com",
@@ -55,7 +55,7 @@ vows
assert.isEmpty(cookies); // no cookies set
},
"with Secure attribute and over https, should work": function(cj) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Secure-SID=12345; Domain=example.com; Secure",
"https://www.example.com",
@@ -69,7 +69,7 @@ vows
"with Secure attribute but not over https, should fail silently": function(
cj
) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Secure-SID=12345; Domain=example.com; Secure",
"http://www.example.com",
@@ -86,13 +86,13 @@ vows
"with no Secure attribute or Domain or Path, should fail silently": function(
cj
) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync("__Host-SID=12345", "http://www.example.com", {});
const cookies = cj.getCookiesSync("http://www.example.com");
assert.isEmpty(cookies); // no cookies set
},
"with no Domain or Path, should fail silently": function(cj) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Host-SID=12345; Secure",
"http://www.example.com",
@@ -102,7 +102,7 @@ vows
assert.isEmpty(cookies); // no cookies set
},
"with no Path, should fail silently": function(cj) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Host-SID=12345; Secure; Domain=example.com",
"http://www.example.com",
@@ -112,7 +112,7 @@ vows
assert.isEmpty(cookies); // no cookies set
},
"with Domain, should fail silently": function(cj) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Host-SID=12345; Secure; Domain=example.com; Path=/",
"http://www.example.com",
@@ -124,7 +124,7 @@ vows
"with Secure and Path but no Domain over https, should work": function(
cj
) {
- assert.equal(PrefixSecurityEnum.SILENT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.SILENT, cj.prefixSecurity);
cj.setCookieSync(
"__Host-SID=12345; Secure; Path=/",
"https://www.example.com",
@@ -144,7 +144,7 @@ vows
return new CookieJar(null, { prefixSecurity: "strict" });
},
passes: function(cj) {
- assert.equal(PrefixSecurityEnum.STRICT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.STRICT, cj.prefixSecurity);
cj.setCookieSync(
"__Secure-SID=12345; Secure; Domain=example.com",
"https://www.example.com",
@@ -159,7 +159,7 @@ vows
"for invalid cookie": {
topic: function() {
const cj = new CookieJar(null, { prefixSecurity: "strict" });
- assert.equal(PrefixSecurityEnum.STRICT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.STRICT, cj.prefixSecurity);
cj.setCookieSync(
"__Secure-SID=12345; Domain=example.com",
"http://www.example.com",
@@ -176,7 +176,7 @@ vows
"for invalid cookie": {
topic: function() {
const cj = new CookieJar(null, { prefixSecurity: "strict" });
- assert.equal(PrefixSecurityEnum.STRICT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.STRICT, cj.prefixSecurity);
cj.setCookieSync(
"__Host-SID=12345; Secure; Domain=example.com",
"https://www.example.com",
@@ -193,7 +193,7 @@ vows
return new CookieJar(null, { prefixSecurity: "strict" });
},
passes: function(cj) {
- assert.equal(PrefixSecurityEnum.STRICT, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.STRICT, cj.prefixSecurity);
cj.setCookieSync(
"__Host-SID=12345; Secure; Path=/",
"https://www.foo.com",
@@ -213,7 +213,7 @@ vows
return new CookieJar(null, { prefixSecurity: "unsafe-disabled" });
},
"does not fail": function(cj) {
- assert.equal(PrefixSecurityEnum.DISABLED, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.DISABLED, cj.prefixSecurity);
cj.setCookieSync(
"__Secure-SID=12345; Domain=example.com",
"http://www.example.com",
@@ -230,7 +230,7 @@ vows
return new CookieJar(null, { prefixSecurity: "unsafe-disabled" });
},
"does not fail": function(cj) {
- assert.equal(PrefixSecurityEnum.DISABLED, cj.prefixSecurity);
+ assert.equal(PrefixSecurity.DISABLED, cj.prefixSecurity);
/* Failure case because Domain defined */
cj.setCookieSync(
"__Host-SID=12345; Domain=example.com",