@exortek/apikey 1.1.0 → 1.1.1
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/CHANGELOG.md +19 -0
- package/dist/index.cjs +6 -2
- package/dist/index.mjs +6 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @exortek/apikey
|
|
2
2
|
|
|
3
|
+
## 1.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e53ae64: Fix polynomial-ReDoS (quadratic regex backtracking) surfaced by CodeQL, plus small code-quality fixes.
|
|
8
|
+
Bundled `@exortek/shared` utilities (base32, base64, duration) are inlined into the packages listed above, so each
|
|
9
|
+
ships the fix.
|
|
10
|
+
|
|
11
|
+
- Replace `/=+$/` trailing-padding strips (base32 / base64 decode, OTP provisioning URI) with linear scans —
|
|
12
|
+
`"=".repeat(n) + "x"` was O(n²).
|
|
13
|
+
- Rework the duration parser regex so surrounding whitespace can no longer cause O(n²) matching (trim first, single
|
|
14
|
+
interior `\s*`).
|
|
15
|
+
- Strip trailing spaces/dots in filename sanitisation with a linear scan — upload filenames are attacker-controlled.
|
|
16
|
+
- Cap email length before the regex in magic-link.
|
|
17
|
+
- Thread the JWT decode label into error messages (removes dead arguments and gives failures which segment broke).
|
|
18
|
+
- Drop a duplicate character in a UA browser-detection regex character class.
|
|
19
|
+
|
|
20
|
+
DoS-hardening and hygiene only — no API or behavioural change for valid input.
|
|
21
|
+
|
|
3
22
|
## 1.1.0
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -65,7 +65,11 @@ const UNIT_MS = Object.freeze({
|
|
|
65
65
|
years: 31_536_000_000,
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
// Note: no leading/trailing `\s*` — the caller trims first. Two `\s*` runs
|
|
69
|
+
// around the optional unit (`\s*([a-z]+)?\s*`) made this O(n^2) on hostile
|
|
70
|
+
// input like `"1" + " ".repeat(n) + "!"`; trimming plus a single interior
|
|
71
|
+
// `\s*` keeps matching linear.
|
|
72
|
+
const DURATION_RE = /^(-?\d+(?:\.\d+)?)\s*([a-z]+)?$/i;
|
|
69
73
|
|
|
70
74
|
const SUPPORTED_UNITS = 'ms, s, m, h, d, w, y (and long/plural forms)';
|
|
71
75
|
|
|
@@ -95,7 +99,7 @@ function parseDuration(input) {
|
|
|
95
99
|
throw new TypeError(`parseDuration: expected string or number; got ${typeof input}`);
|
|
96
100
|
}
|
|
97
101
|
|
|
98
|
-
const match = DURATION_RE.exec(input);
|
|
102
|
+
const match = DURATION_RE.exec(input.trim());
|
|
99
103
|
if (!match) {
|
|
100
104
|
throw new Error(
|
|
101
105
|
`parseDuration: could not parse ${JSON.stringify(input)}. Examples: 900 (ms), '15m', '2h', '7d', '500ms', '30s'.`,
|
package/dist/index.mjs
CHANGED
|
@@ -63,7 +63,11 @@ const UNIT_MS = Object.freeze({
|
|
|
63
63
|
years: 31_536_000_000,
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
// Note: no leading/trailing `\s*` — the caller trims first. Two `\s*` runs
|
|
67
|
+
// around the optional unit (`\s*([a-z]+)?\s*`) made this O(n^2) on hostile
|
|
68
|
+
// input like `"1" + " ".repeat(n) + "!"`; trimming plus a single interior
|
|
69
|
+
// `\s*` keeps matching linear.
|
|
70
|
+
const DURATION_RE = /^(-?\d+(?:\.\d+)?)\s*([a-z]+)?$/i;
|
|
67
71
|
|
|
68
72
|
const SUPPORTED_UNITS = 'ms, s, m, h, d, w, y (and long/plural forms)';
|
|
69
73
|
|
|
@@ -93,7 +97,7 @@ function parseDuration(input) {
|
|
|
93
97
|
throw new TypeError(`parseDuration: expected string or number; got ${typeof input}`);
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
const match = DURATION_RE.exec(input);
|
|
100
|
+
const match = DURATION_RE.exec(input.trim());
|
|
97
101
|
if (!match) {
|
|
98
102
|
throw new Error(
|
|
99
103
|
`parseDuration: could not parse ${JSON.stringify(input)}. Examples: 900 (ms), '15m', '2h', '7d', '500ms', '30s'.`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exortek/apikey",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Stripe-style prefixed API keys for Node.js — 3-segment tokens (prefix_id_secret), HMAC-SHA256 storage hash with pepper rotation, scope allowlists with wildcard match, opt-in lastUsedAt tracking, memory + Redis stores, Express + Fastify middleware. Server-only. Zero non-@exortek runtime dependencies.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|