tough-cookie 6.0.1 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -384,7 +384,7 @@ var ParameterError = class extends Error {
384
384
  };
385
385
 
386
386
  // lib/version.ts
387
- var version = "6.0.1";
387
+ var version = "6.1.0";
388
388
 
389
389
  // lib/cookie/constants.ts
390
390
  var PrefixSecurityEnum = {
@@ -438,6 +438,17 @@ function formatDate(date) {
438
438
  return date.toUTCString();
439
439
  }
440
440
 
441
+ // lib/cookie/cookieName.ts
442
+ var INVALID_TOKEN_CHARACTER = /[^\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7A\x7C\x7E]/;
443
+ var CookieName = {
444
+ parse(input) {
445
+ if (input.length === 0 || INVALID_TOKEN_CHARACTER.test(input)) {
446
+ return void 0;
447
+ }
448
+ return input;
449
+ }
450
+ };
451
+
441
452
  // lib/cookie/parseDate.ts
442
453
  function parseDate(cookieDate) {
443
454
  if (!cookieDate) {
@@ -612,8 +623,8 @@ function parse(str, options) {
612
623
  return c;
613
624
  }
614
625
  const cookie_avs = unparsed.split(";");
615
- while (cookie_avs.length) {
616
- const av = (cookie_avs.shift() ?? "").trim();
626
+ for (const cookie_av of cookie_avs) {
627
+ const av = cookie_av.trim();
617
628
  if (av.length === 0) {
618
629
  continue;
619
630
  }
@@ -896,10 +907,17 @@ var _Cookie = class _Cookie {
896
907
  *
897
908
  * @remarks
898
909
  * Works for a few things, but is by no means comprehensive.
910
+ * Checks that the cookie name is a non-empty token as defined in RFC 6265 Section 4.1.1.
911
+ * Nameless cookies (including those parsed in loose mode or created with `new Cookie({ value })`)
912
+ * and names containing characters outside the token grammar (such as `a b`) return `false`.
913
+ * Parsing and storage remain permissive; this check only applies to explicit validation.
899
914
  *
900
915
  * @beta
901
916
  */
902
917
  validate() {
918
+ if (CookieName.parse(this.key) === void 0) {
919
+ return false;
920
+ }
903
921
  if (!this.value || !COOKIE_OCTETS.test(this.value)) {
904
922
  return false;
905
923
  }
@@ -918,7 +936,7 @@ var _Cookie = class _Cookie {
918
936
  return false;
919
937
  }
920
938
  const suffix = getPublicSuffix(cdomain);
921
- if (suffix == null) {
939
+ if (suffix == null && !IP_V4_REGEX_OBJECT.test(cdomain) && !IP_V6_REGEX_OBJECT.test(cdomain)) {
922
940
  return false;
923
941
  }
924
942
  }
@@ -994,11 +1012,13 @@ var _Cookie = class _Cookie {
994
1012
  if (this.httpOnly) {
995
1013
  str += "; HttpOnly";
996
1014
  }
997
- if (this.sameSite && this.sameSite !== "none") {
1015
+ if (this.sameSite) {
998
1016
  if (this.sameSite.toLowerCase() === _Cookie.sameSiteCanonical.lax.toLowerCase()) {
999
1017
  str += `; SameSite=${_Cookie.sameSiteCanonical.lax}`;
1000
1018
  } else if (this.sameSite.toLowerCase() === _Cookie.sameSiteCanonical.strict.toLowerCase()) {
1001
1019
  str += `; SameSite=${_Cookie.sameSiteCanonical.strict}`;
1020
+ } else if (this.sameSite.toLowerCase() === _Cookie.sameSiteCanonical.none.toLowerCase()) {
1021
+ str += `; SameSite=${_Cookie.sameSiteCanonical.none}`;
1002
1022
  } else {
1003
1023
  str += `; SameSite=${this.sameSite}`;
1004
1024
  }
@@ -1045,6 +1065,9 @@ var _Cookie = class _Cookie {
1045
1065
  */
1046
1066
  expiryTime(now) {
1047
1067
  if (this.maxAge != null) {
1068
+ if (this.maxAge === "Infinity") {
1069
+ return Infinity;
1070
+ }
1048
1071
  const relativeTo = now || this.lastAccessed || /* @__PURE__ */ new Date();
1049
1072
  const maxAge = typeof this.maxAge === "number" ? this.maxAge : -Infinity;
1050
1073
  const age = maxAge <= 0 ? -Infinity : maxAge * 1e3;
@@ -1177,7 +1200,8 @@ _Cookie.sameSiteLevel = {
1177
1200
  */
1178
1201
  _Cookie.sameSiteCanonical = {
1179
1202
  strict: "Strict",
1180
- lax: "Lax"
1203
+ lax: "Lax",
1204
+ none: "None"
1181
1205
  };
1182
1206
  /**
1183
1207
  * Cookie properties that will be serialized when using {@link Cookie.fromJSON} and {@link Cookie.toJSON}.
@@ -1336,23 +1360,34 @@ var defaultGetCookieOptions = {
1336
1360
  var SAME_SITE_CONTEXT_VAL_ERR = 'Invalid sameSiteContext option for getCookies(); expected one of "strict", "lax", or "none"';
1337
1361
  function getCookieContext(url) {
1338
1362
  if (url && typeof url === "object" && "hostname" in url && typeof url.hostname === "string" && "pathname" in url && typeof url.pathname === "string" && "protocol" in url && typeof url.protocol === "string") {
1363
+ let pathname = url.pathname;
1364
+ try {
1365
+ pathname = decodeURI(pathname);
1366
+ } catch {
1367
+ }
1339
1368
  return {
1340
1369
  hostname: url.hostname,
1341
- pathname: url.pathname,
1370
+ pathname,
1342
1371
  protocol: url.protocol
1343
1372
  };
1344
1373
  } else if (typeof url === "string") {
1374
+ const parsed = new URL(url);
1375
+ let pathname = parsed.pathname;
1345
1376
  try {
1346
- return new URL(decodeURI(url));
1377
+ pathname = decodeURI(pathname);
1347
1378
  } catch {
1348
- return new URL(url);
1349
1379
  }
1380
+ return {
1381
+ hostname: parsed.hostname,
1382
+ pathname,
1383
+ protocol: parsed.protocol
1384
+ };
1350
1385
  } else {
1351
1386
  throw new ParameterError("`url` argument is not a string or URL.");
1352
1387
  }
1353
1388
  }
1354
1389
  function checkSameSiteContext(value) {
1355
- const context = String(value).toLowerCase();
1390
+ const context = value.toLowerCase();
1356
1391
  if (context === "none" || context === "lax" || context === "strict") {
1357
1392
  return context;
1358
1393
  } else {
@@ -1366,7 +1401,7 @@ function isSecurePrefixConditionMet(cookie) {
1366
1401
  function isHostPrefixConditionMet(cookie) {
1367
1402
  const startsWithHostPrefix = typeof cookie.key === "string" && cookie.key.startsWith("__Host-");
1368
1403
  return !startsWithHostPrefix || Boolean(
1369
- cookie.secure && cookie.hostOnly && cookie.path != null && cookie.path === "/"
1404
+ cookie.secure && cookie.hostOnly && cookie.path != null && cookie.path === "/" && !cookie.pathIsDefault
1370
1405
  );
1371
1406
  }
1372
1407
  function getNormalizedPrefixSecurity(prefixSecurity) {
@@ -1399,6 +1434,7 @@ var CookieJar = class _CookieJar {
1399
1434
  this.enableLooseMode = options?.looseMode ?? false;
1400
1435
  this.allowSpecialUseDomain = options?.allowSpecialUseDomain ?? true;
1401
1436
  this.allowSecureOnLocal = options?.allowSecureOnLocal ?? true;
1437
+ this.enforceSecureOriginOnStorage = options?.enforceSecureOriginOnStorage ?? true;
1402
1438
  this.prefixSecurity = getNormalizedPrefixSecurity(
1403
1439
  options?.prefixSecurity ?? "silent"
1404
1440
  );
@@ -1486,7 +1522,7 @@ var CookieJar = class _CookieJar {
1486
1522
  allowSpecialUseDomain: this.allowSpecialUseDomain,
1487
1523
  ignoreError: options?.ignoreError
1488
1524
  }) : null;
1489
- if (suffix == null && !IP_V6_REGEX_OBJECT.test(cookie.domain)) {
1525
+ if (suffix == null && !IP_V4_REGEX_OBJECT.test(cdomain ?? "") && !IP_V6_REGEX_OBJECT.test(cdomain ?? "")) {
1490
1526
  const err = new Error("Cookie has domain set to a public suffix");
1491
1527
  return options?.ignoreError ? promiseCallback.resolve(void 0) : promiseCallback.reject(err);
1492
1528
  }
@@ -1515,6 +1551,12 @@ var CookieJar = class _CookieJar {
1515
1551
  cookie.path = defaultPath(context.pathname);
1516
1552
  cookie.pathIsDefault = true;
1517
1553
  }
1554
+ if (this.enforceSecureOriginOnStorage && cookie.secure && !isPotentiallyTrustworthy(url, this.allowSecureOnLocal)) {
1555
+ const err = new Error(
1556
+ "Cookie is Secure but this is not a secure connection"
1557
+ );
1558
+ return options?.ignoreError ? promiseCallback.resolve(void 0) : promiseCallback.reject(err);
1559
+ }
1518
1560
  if (options?.http === false && cookie.httpOnly) {
1519
1561
  const err = new Error("Cookie is HttpOnly and this isn't an HTTP API");
1520
1562
  return options.ignoreError ? promiseCallback.resolve(void 0) : promiseCallback.reject(err);
@@ -1839,6 +1881,7 @@ var CookieJar = class _CookieJar {
1839
1881
  rejectPublicSuffixes: this.rejectPublicSuffixes,
1840
1882
  enableLooseMode: this.enableLooseMode,
1841
1883
  allowSpecialUseDomain: this.allowSpecialUseDomain,
1884
+ enforceSecureOriginOnStorage: this.enforceSecureOriginOnStorage,
1842
1885
  prefixSecurity: getNormalizedPrefixSecurity(this.prefixSecurity),
1843
1886
  // this gets filled from getAllCookies:
1844
1887
  cookies: []
@@ -2085,6 +2128,9 @@ var CookieJar = class _CookieJar {
2085
2128
  rejectPublicSuffixes: readSerializedBoolean("rejectPublicSuffixes"),
2086
2129
  looseMode: readSerializedBoolean("enableLooseMode"),
2087
2130
  allowSpecialUseDomain: readSerializedBoolean("allowSpecialUseDomain"),
2131
+ enforceSecureOriginOnStorage: readSerializedBoolean(
2132
+ "enforceSecureOriginOnStorage"
2133
+ ),
2088
2134
  prefixSecurity: getNormalizedPrefixSecurity(
2089
2135
  readSerializedString("prefixSecurity") ?? "silent"
2090
2136
  )
@@ -2130,6 +2176,9 @@ var CookieJar = class _CookieJar {
2130
2176
  rejectPublicSuffixes: readSerializedBoolean("rejectPublicSuffixes"),
2131
2177
  looseMode: readSerializedBoolean("enableLooseMode"),
2132
2178
  allowSpecialUseDomain: readSerializedBoolean("allowSpecialUseDomain"),
2179
+ enforceSecureOriginOnStorage: readSerializedBoolean(
2180
+ "enforceSecureOriginOnStorage"
2181
+ ),
2133
2182
  prefixSecurity: getNormalizedPrefixSecurity(
2134
2183
  readSerializedString("prefixSecurity") ?? "silent"
2135
2184
  )