diff --git a/api/.gitignore b/api/.gitignore index bed7e484..3be88649 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -3,3 +3,5 @@ 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.getpublicsuffix.md +!docs/tough-cookie.getpublicsuffixoptions.md diff --git a/api/docs/tough-cookie.getpublicsuffix.md b/api/docs/tough-cookie.getpublicsuffix.md new file mode 100644 index 00000000..70312d66 --- /dev/null +++ b/api/docs/tough-cookie.getpublicsuffix.md @@ -0,0 +1,37 @@ + + +[Home](./index.md) > [tough-cookie](./tough-cookie.md) > [getPublicSuffix](./tough-cookie.getpublicsuffix.md) + +## getPublicSuffix() function + +Returns the public suffix of this hostname. The public suffix is the shortest domain name upon which a cookie can be set. + +**Signature:** + +```typescript +export declare function getPublicSuffix(domain: string, options?: GetPublicSuffixOptions): string | null; +``` + +## Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| domain | string | the domain attribute of a cookie | +| options | [GetPublicSuffixOptions](./tough-cookie.getpublicsuffixoptions.md) | _(Optional)_ optional configuration for controlling how the public suffix is determined | + +**Returns:** + +string \| null + +## Remarks + +A "public suffix" is a domain that is controlled by a public registry, such as "com", "co.uk", and "pvt.k12.wy.us". This step is essential for preventing attacker.com from disrupting the integrity of example.com by setting a cookie with a Domain attribute of "com". Unfortunately, the set of public suffixes (also known as "registry controlled domains") changes over time. If feasible, user agents SHOULD use an up-to-date public suffix list, such as the one maintained by the Mozilla project at http://publicsuffix.org/. (See [RFC6265 - Section 5.3](https://www.rfc-editor.org/rfc/rfc6265.html#section-5.3)) + +## Example + + +``` +getPublicSuffix('www.example.com') === 'example.com' +getPublicSuffix('www.subdomain.example.com') === 'example.com' +``` + diff --git a/api/docs/tough-cookie.getpublicsuffixoptions.md b/api/docs/tough-cookie.getpublicsuffixoptions.md new file mode 100644 index 00000000..39dbde64 --- /dev/null +++ b/api/docs/tough-cookie.getpublicsuffixoptions.md @@ -0,0 +1,16 @@ + + +[Home](./index.md) > [tough-cookie](./tough-cookie.md) > [GetPublicSuffixOptions](./tough-cookie.getpublicsuffixoptions.md) + +## GetPublicSuffixOptions type + +Options for configuring how [getPublicSuffix()](./tough-cookie.getpublicsuffix.md) behaves. + +**Signature:** + +```typescript +export type GetPublicSuffixOptions = { + allowSpecialUseDomain?: boolean | undefined; + ignoreError?: boolean | undefined; +}; +``` diff --git a/api/tough-cookie.api.md b/api/tough-cookie.api.md index eca22a33..1e5670f4 100644 --- a/api/tough-cookie.api.md +++ b/api/tough-cookie.api.md @@ -209,11 +209,15 @@ export function formatDate(date: Date): string; // @public (undocumented) export const fromJSON: (str: unknown) => Cookie | null; -// Warning: (ae-forgotten-export) The symbol "GetPublicSuffixOptions" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) +// @public export function getPublicSuffix(domain: string, options?: GetPublicSuffixOptions): string | null; +// @public +export type GetPublicSuffixOptions = { + allowSpecialUseDomain?: boolean | undefined; + ignoreError?: boolean | undefined; +}; + // @public (undocumented) export class MemoryCookieStore extends Store { constructor(); diff --git a/lib/cookie/index.ts b/lib/cookie/index.ts index 7b94bdd4..3124381a 100644 --- a/lib/cookie/index.ts +++ b/lib/cookie/index.ts @@ -1,7 +1,7 @@ export { MemoryCookieStore } from '../memstore' export { pathMatch } from '../pathMatch' export { permuteDomain } from '../permuteDomain' -export { getPublicSuffix } from '../getPublicSuffix' +export { getPublicSuffix, GetPublicSuffixOptions } from '../getPublicSuffix' export { Store } from '../store' export { ParameterError } from '../validators' export { version } from '../version' diff --git a/lib/getPublicSuffix.ts b/lib/getPublicSuffix.ts index 7e7967cf..0caf773f 100644 --- a/lib/getPublicSuffix.ts +++ b/lib/getPublicSuffix.ts @@ -1,34 +1,3 @@ -/*! - * Copyright (c) 2018, Salesforce.com, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. Neither the name of Salesforce.com nor the names of its contributors may - * be used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -'use strict' import { getDomain } from 'tldts' // RFC 6761 @@ -36,8 +5,31 @@ const SPECIAL_USE_DOMAINS = ['local', 'example', 'invalid', 'localhost', 'test'] const SPECIAL_TREATMENT_DOMAINS = ['localhost', 'invalid'] -type GetPublicSuffixOptions = { +/** + * Options for configuring how {@link getPublicSuffix} behaves. + * @public + */ +export type GetPublicSuffixOptions = { + /** + * Should the following {@link https://www.rfc-editor.org/rfc/rfc6761.html | Special Use Domains} be treated as if they were valid public suffixes ('local', 'example', 'invalid', 'localhost', 'test') + * + * @remarks + * In testing scenarios it's common to configure the cookies store with: + * ```json + * { + * allowSpecialUseDomain: true, + * rejectPublicSuffixes: false + * } + * ``` + * + * @defaultValue false + */ allowSpecialUseDomain?: boolean | undefined + /** + * Should an invalid public domains error be ignored + * + * @defaultValue false + */ ignoreError?: boolean | undefined } @@ -46,6 +38,32 @@ const defaultGetPublicSuffixOptions: GetPublicSuffixOptions = { ignoreError: false, } +/** + * Returns the public suffix of this hostname. The public suffix is the shortest domain + * name upon which a cookie can be set. + * + * @remarks + * A "public suffix" is a domain that is controlled by a + * public registry, such as "com", "co.uk", and "pvt.k12.wy.us". + * This step is essential for preventing attacker.com from + * disrupting the integrity of example.com by setting a cookie + * with a Domain attribute of "com". Unfortunately, the set of + * public suffixes (also known as "registry controlled domains") + * changes over time. If feasible, user agents SHOULD use an + * up-to-date public suffix list, such as the one maintained by + * the Mozilla project at http://publicsuffix.org/. + * (See {@link https://www.rfc-editor.org/rfc/rfc6265.html#section-5.3 | RFC6265 - Section 5.3}) + * + * @example + * ``` + * getPublicSuffix('www.example.com') === 'example.com' + * getPublicSuffix('www.subdomain.example.com') === 'example.com' + * ``` + * + * @param domain - the domain attribute of a cookie + * @param options - optional configuration for controlling how the public suffix is determined + * @public + */ export function getPublicSuffix( domain: string, options: GetPublicSuffixOptions = {}, @@ -80,7 +98,7 @@ export function getPublicSuffix( SPECIAL_USE_DOMAINS.includes(topLevelDomain) ) { throw new Error( - `Cookie has domain set to the public suffix "${topLevelDomain}" which is a special use domain. To allow this, configure your CookieJar with {allowSpecialUseDomain:true, rejectPublicSuffixes: false}.`, + `Cookie has domain set to the public suffix "${topLevelDomain}" which is a special use domain. To allow this, configure your CookieJar with {allowSpecialUseDomain: true, rejectPublicSuffixes: false}.`, ) }