brace-expansion 2.1.0 → 2.1.2

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.
@@ -0,0 +1,107 @@
1
+ # DoS via unbounded expansion length — out-of-memory process crash
2
+
3
+ - **CVE:** CVE-2026-14257
4
+ - **Package:** brace-expansion (npm)
5
+ - **Reporter:** @bnbdr
6
+ - **Severity (proposed):** High — `CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H` (7.5)
7
+ - **Weakness:** CWE-770 (Allocation of Resources Without Limits or Throttling) / CWE-400 (Uncontrolled Resource Consumption)
8
+ - **Affected:** all versions up to and including `5.0.7` (the `1.x`, `2.x`, `3.x` and `4.x` lines share the same combine logic and are expected to be affected)
9
+
10
+ ### Summary
11
+
12
+ `expand()` bounds the *number* of results it produces (the `max` option,
13
+ `100_000` by default) but not their *length*. By chaining many brace groups,
14
+ an attacker keeps the result count under `max` while making every result grow
15
+ with the number of groups. Building `max` long results — plus the intermediate
16
+ arrays combined at each brace group — exhausts memory and crashes the Node
17
+ process with an **uncatchable** out-of-memory error. `try/catch` around
18
+ `expand()` does not help: the fatal error terminates the process.
19
+
20
+ A ~7.5 KB input (`'{a,b}'.repeat(1500)`) is enough to crash a default Node
21
+ process.
22
+
23
+ ### Details
24
+
25
+ For `N` chained brace groups such as `'{a,b}'.repeat(N)`:
26
+
27
+ - the result count is `2^N`, immediately capped at `max` (`100_000`), so the
28
+ `max` protection appears to hold, but
29
+ - each result is `N` characters long, so the total output size is
30
+ `max × N` characters, which grows without bound in `N`.
31
+
32
+ `expand_` combines each brace set with the fully-expanded tail:
33
+
34
+ ```js
35
+ const post = m.post.length ? expand_(m.post, max, false) : ['']
36
+ ...
37
+ for (let j = 0; j < N.length; j++) {
38
+ for (let k = 0; k < post.length && expansions.length < max; k++) {
39
+ const expansion = pre + N[j] + post[k] // grows one group longer per level
40
+ ...
41
+ expansions.push(expansion)
42
+ }
43
+ }
44
+ ```
45
+
46
+ The loop guard `expansions.length < max` limits how many strings are built, but
47
+ nothing limits how long they get. Each recursion level materializes another
48
+ array of up to `max` strings, one character longer than the level below, and —
49
+ because V8 represents `pre + N[j] + post[k]` as a cons-string (rope) that
50
+ references `post[k]` — those intermediate strings stay reachable through the
51
+ whole chain. Memory therefore scales with `max × N`.
52
+
53
+ Measured on `5.0.7` (`'{a,b}'.repeat(N)`, default `max`):
54
+
55
+ | groups (N) | input bytes | result count | peak RSS |
56
+ |---|---|---|---|
57
+ | 20 | 100 | 100,000 | ~80 MB |
58
+ | 50 | 250 | 100,000 | ~214 MB |
59
+ | 100 | 500 | 100,000 | ~409 MB |
60
+ | 300 | 1,500 | 100,000 | ~1,148 MB |
61
+ | 1500 | 7,500 | — | **OOM crash** |
62
+
63
+ ### Proof of concept
64
+
65
+ ```js
66
+ const { expand } = require('brace-expansion')
67
+
68
+ // ~7.5 KB input — crashes the process with a fatal, uncatchable OOM:
69
+ // FATAL ERROR: ... JavaScript heap out of memory
70
+ try {
71
+ expand('{a,b}'.repeat(1500))
72
+ } catch (e) {
73
+ // never reached — the process is already dead
74
+ }
75
+ ```
76
+
77
+ ### Impact
78
+
79
+ Any application that passes attacker-influenced strings to
80
+ `brace-expansion.expand()` — directly, or transitively via `minimatch` / `glob`
81
+ brace patterns — can be crashed by a small request. Because the failure is a
82
+ fatal V8 out-of-memory error rather than a thrown exception, it cannot be caught
83
+ and it takes down the whole worker/process, denying service.
84
+
85
+ ### Remediation
86
+
87
+ Upgrade to a patched release. The fix bounds the total number of characters a
88
+ single `expand()` call may accumulate (`EXPANSION_MAX_LENGTH`, default
89
+ `4_000_000`, configurable via a new `maxLength` option), applied inside the
90
+ output-building loops so intermediate arrays are bounded too. Once the limit is
91
+ reached, output is truncated — consistent with how `max` already truncates —
92
+ instead of growing without bound. The limit sits well above any realistic
93
+ expansion (100,000 results hitting `max` measure ~1M characters), so legitimate
94
+ input is unaffected.
95
+
96
+ After the fix, `'{a,b}'.repeat(1500)` returns a bounded, truncated result in
97
+ ~0.7 s using ~340 MB and never crashes, including under a constrained 512 MB
98
+ heap.
99
+
100
+ The fix bounds memory but the algorithm still rebuilds intermediate arrays at
101
+ each level (roughly `O(N × maxLength)` work on this input class). A streaming
102
+ rewrite that produces output in `O(total output size)` can be a non-urgent
103
+ follow-up.
104
+
105
+ If immediate upgrade isn't possible, avoid passing untrusted input to
106
+ `expand()` / glob brace patterns, or pass a small explicit `max` **and**
107
+ `maxLength`.
@@ -0,0 +1,8 @@
1
+ export declare const EXPANSION_MAX = 100000;
2
+ export declare const EXPANSION_MAX_LENGTH = 4000000;
3
+ export type BraceExpansionOptions = {
4
+ max?: number;
5
+ maxLength?: number;
6
+ };
7
+ export declare function expand(str: string, options?: BraceExpansionOptions): string[];
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,SAAU,CAAA;AAYpC,eAAO,MAAM,oBAAoB,UAAY,CAAA;AAwD7C,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,YAkBtE"}
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXPANSION_MAX_LENGTH = exports.EXPANSION_MAX = void 0;
4
+ exports.expand = expand;
5
+ const balanced_match_1 = require("balanced-match");
6
+ const escSlash = '\0SLASH' + Math.random() + '\0';
7
+ const escOpen = '\0OPEN' + Math.random() + '\0';
8
+ const escClose = '\0CLOSE' + Math.random() + '\0';
9
+ const escComma = '\0COMMA' + Math.random() + '\0';
10
+ const escPeriod = '\0PERIOD' + Math.random() + '\0';
11
+ const escSlashPattern = new RegExp(escSlash, 'g');
12
+ const escOpenPattern = new RegExp(escOpen, 'g');
13
+ const escClosePattern = new RegExp(escClose, 'g');
14
+ const escCommaPattern = new RegExp(escComma, 'g');
15
+ const escPeriodPattern = new RegExp(escPeriod, 'g');
16
+ const slashPattern = /\\\\/g;
17
+ const openPattern = /\\{/g;
18
+ const closePattern = /\\}/g;
19
+ const commaPattern = /\\,/g;
20
+ const periodPattern = /\\\./g;
21
+ exports.EXPANSION_MAX = 100_000;
22
+ // `EXPANSION_MAX` caps the *number* of expansions, but not their length. An
23
+ // input like `'{a,b}'.repeat(1500)` stays under that count - its output is
24
+ // truncated to 100k results - while making every result ~1500 characters
25
+ // long. The result set, and the intermediate arrays built while combining
26
+ // brace sets, then grow large enough to exhaust memory and crash the process
27
+ // (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of
28
+ // characters the accumulator may hold at any point, so memory stays flat no
29
+ // matter how many brace groups are chained. The limit sits well above any
30
+ // realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M
31
+ // characters) so legitimate input is unaffected.
32
+ exports.EXPANSION_MAX_LENGTH = 4_000_000;
33
+ function numeric(str) {
34
+ return !isNaN(str) ? parseInt(str, 10) : str.charCodeAt(0);
35
+ }
36
+ function escapeBraces(str) {
37
+ return str
38
+ .replace(slashPattern, escSlash)
39
+ .replace(openPattern, escOpen)
40
+ .replace(closePattern, escClose)
41
+ .replace(commaPattern, escComma)
42
+ .replace(periodPattern, escPeriod);
43
+ }
44
+ function unescapeBraces(str) {
45
+ return str
46
+ .replace(escSlashPattern, '\\')
47
+ .replace(escOpenPattern, '{')
48
+ .replace(escClosePattern, '}')
49
+ .replace(escCommaPattern, ',')
50
+ .replace(escPeriodPattern, '.');
51
+ }
52
+ /**
53
+ * Basically just str.split(","), but handling cases
54
+ * where we have nested braced sections, which should be
55
+ * treated as individual members, like {a,{b,c},d}
56
+ */
57
+ function parseCommaParts(str) {
58
+ if (!str) {
59
+ return [''];
60
+ }
61
+ const parts = [];
62
+ const m = (0, balanced_match_1.balanced)('{', '}', str);
63
+ if (!m) {
64
+ return str.split(',');
65
+ }
66
+ const { pre, body, post } = m;
67
+ const p = pre.split(',');
68
+ p[p.length - 1] += '{' + body + '}';
69
+ const postParts = parseCommaParts(post);
70
+ if (post.length) {
71
+ ;
72
+ p[p.length - 1] += postParts.shift();
73
+ p.push.apply(p, postParts);
74
+ }
75
+ parts.push.apply(parts, p);
76
+ return parts;
77
+ }
78
+ function expand(str, options = {}) {
79
+ if (!str) {
80
+ return [];
81
+ }
82
+ const { max = exports.EXPANSION_MAX, maxLength = exports.EXPANSION_MAX_LENGTH } = options;
83
+ // I don't know why Bash 4.3 does this, but it does.
84
+ // Anything starting with {} will have the first two bytes preserved
85
+ // but *only* at the top level, so {},a}b will not expand to anything,
86
+ // but a{},b}c will be expanded to [a}c,abc].
87
+ // One could argue that this is a bug in Bash, but since the goal of
88
+ // this module is to match Bash's rules, we escape a leading {}
89
+ if (str.slice(0, 2) === '{}') {
90
+ str = '\\{\\}' + str.slice(2);
91
+ }
92
+ return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces);
93
+ }
94
+ function embrace(str) {
95
+ return '{' + str + '}';
96
+ }
97
+ function isPadded(el) {
98
+ return /^-?0\d/.test(el);
99
+ }
100
+ function lte(i, y) {
101
+ return i <= y;
102
+ }
103
+ function gte(i, y) {
104
+ return i >= y;
105
+ }
106
+ // Build `{ acc[a] + pre + values[v] }` for every combination, capping the
107
+ // number of results at `max` and the total number of characters at `maxLength`.
108
+ // This is the one place output grows, so bounding it here keeps the single
109
+ // accumulator - and therefore memory - flat regardless of how many brace groups
110
+ // are combined (CVE-2026-14257).
111
+ function combine(acc, pre, values, max, maxLength, dropEmpties) {
112
+ const out = [];
113
+ let length = 0;
114
+ for (let a = 0; a < acc.length; a++) {
115
+ for (let v = 0; v < values.length; v++) {
116
+ if (out.length >= max)
117
+ return out;
118
+ const expansion = acc[a] + pre + values[v];
119
+ // Bash drops empty results at the top level. Skip them before they count
120
+ // against `max`, so `max` bounds the number of *kept* results.
121
+ if (dropEmpties && !expansion)
122
+ continue;
123
+ if (length + expansion.length > maxLength)
124
+ return out;
125
+ out.push(expansion);
126
+ length += expansion.length;
127
+ }
128
+ }
129
+ return out;
130
+ }
131
+ // The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)
132
+ // sequence body.
133
+ function expandSequence(body, isAlphaSequence, max) {
134
+ const n = body.split(/\.\./);
135
+ const N = [];
136
+ // A sequence body always splits into two or three parts, but the compiler
137
+ // can't know that.
138
+ /* c8 ignore start */
139
+ if (n[0] === undefined || n[1] === undefined) {
140
+ return N;
141
+ }
142
+ /* c8 ignore stop */
143
+ const x = numeric(n[0]);
144
+ const y = numeric(n[1]);
145
+ const width = Math.max(n[0].length, n[1].length);
146
+ let incr = n.length === 3 && n[2] !== undefined ?
147
+ Math.max(Math.abs(numeric(n[2])), 1)
148
+ : 1;
149
+ let test = lte;
150
+ const reverse = y < x;
151
+ if (reverse) {
152
+ incr *= -1;
153
+ test = gte;
154
+ }
155
+ const pad = n.some(isPadded);
156
+ for (let i = x; test(i, y) && N.length < max; i += incr) {
157
+ let c;
158
+ if (isAlphaSequence) {
159
+ c = String.fromCharCode(i);
160
+ if (c === '\\') {
161
+ c = '';
162
+ }
163
+ }
164
+ else {
165
+ c = String(i);
166
+ if (pad) {
167
+ const need = width - c.length;
168
+ if (need > 0) {
169
+ const z = new Array(need + 1).join('0');
170
+ if (i < 0) {
171
+ c = '-' + z + c.slice(1);
172
+ }
173
+ else {
174
+ c = z + c;
175
+ }
176
+ }
177
+ }
178
+ }
179
+ N.push(c);
180
+ }
181
+ return N;
182
+ }
183
+ function expand_(str, max, maxLength, isTop) {
184
+ // Consume the string's top-level brace groups left to right, threading a
185
+ // running set of combined prefixes (`acc`). Expanding the tail iteratively -
186
+ // rather than recursing on `m.post` once per group - keeps the native stack
187
+ // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no
188
+ // longer overflow the stack, and leaves a single accumulator whose size
189
+ // `maxLength` bounds directly (CVE-2026-14257).
190
+ let acc = [''];
191
+ // Bash drops empty results, but only when the *first* top-level group is a
192
+ // comma set - a sequence like `{a..\}` may legitimately yield ''. The drop
193
+ // is on the final strings, so it is applied to whichever `combine` produces
194
+ // them (the one with no brace set left in the tail).
195
+ let dropEmpties = false;
196
+ let firstGroup = true;
197
+ for (;;) {
198
+ const m = (0, balanced_match_1.balanced)('{', '}', str);
199
+ // No brace set left: the rest of the string is literal.
200
+ if (!m) {
201
+ return combine(acc, str, [''], max, maxLength, dropEmpties);
202
+ }
203
+ // no need to expand pre, since it is guaranteed to be free of brace-sets
204
+ const pre = m.pre;
205
+ if (/\$$/.test(pre)) {
206
+ acc = combine(acc, pre + '{' + m.body + '}', [''], max, maxLength, dropEmpties && !m.post.length);
207
+ firstGroup = false;
208
+ if (!m.post.length)
209
+ break;
210
+ str = m.post;
211
+ continue;
212
+ }
213
+ const isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
214
+ const isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
215
+ const isSequence = isNumericSequence || isAlphaSequence;
216
+ const isOptions = m.body.indexOf(',') >= 0;
217
+ if (!isSequence && !isOptions) {
218
+ // {a},b}
219
+ if (m.post.match(/,(?!,).*\}/)) {
220
+ str = m.pre + '{' + m.body + escClose + m.post;
221
+ isTop = true;
222
+ continue;
223
+ }
224
+ // Nothing here expands, so the whole remaining string is literal.
225
+ return combine(acc, pre + '{' + m.body + '}' + m.post, [''], max, maxLength, dropEmpties);
226
+ }
227
+ if (firstGroup) {
228
+ dropEmpties = isTop && !isSequence;
229
+ firstGroup = false;
230
+ }
231
+ let values;
232
+ if (isSequence) {
233
+ values = expandSequence(m.body, isAlphaSequence, max);
234
+ }
235
+ else {
236
+ let n = parseCommaParts(m.body);
237
+ if (n.length === 1 && n[0] !== undefined) {
238
+ // x{{a,b}}y ==> x{a}y x{b}y
239
+ n = expand_(n[0], max, maxLength, false).map(embrace);
240
+ //XXX is this necessary? Can't seem to hit it in tests.
241
+ /* c8 ignore start */
242
+ if (n.length === 1) {
243
+ acc = combine(acc, pre + n[0], [''], max, maxLength, dropEmpties && !m.post.length);
244
+ if (!m.post.length)
245
+ break;
246
+ str = m.post;
247
+ continue;
248
+ }
249
+ /* c8 ignore stop */
250
+ }
251
+ values = [];
252
+ for (let j = 0; j < n.length; j++) {
253
+ values.push.apply(values, expand_(n[j], max, maxLength, false));
254
+ }
255
+ }
256
+ acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length);
257
+ if (!m.post.length)
258
+ break;
259
+ str = m.post;
260
+ }
261
+ return acc;
262
+ }
263
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { balanced } from 'balanced-match'\n\nconst escSlash = '\\0SLASH' + Math.random() + '\\0'\nconst escOpen = '\\0OPEN' + Math.random() + '\\0'\nconst escClose = '\\0CLOSE' + Math.random() + '\\0'\nconst escComma = '\\0COMMA' + Math.random() + '\\0'\nconst escPeriod = '\\0PERIOD' + Math.random() + '\\0'\nconst escSlashPattern = new RegExp(escSlash, 'g')\nconst escOpenPattern = new RegExp(escOpen, 'g')\nconst escClosePattern = new RegExp(escClose, 'g')\nconst escCommaPattern = new RegExp(escComma, 'g')\nconst escPeriodPattern = new RegExp(escPeriod, 'g')\nconst slashPattern = /\\\\\\\\/g\nconst openPattern = /\\\\{/g\nconst closePattern = /\\\\}/g\nconst commaPattern = /\\\\,/g\nconst periodPattern = /\\\\\\./g\n\nexport const EXPANSION_MAX = 100_000\n\n// `EXPANSION_MAX` caps the *number* of expansions, but not their length. An\n// input like `'{a,b}'.repeat(1500)` stays under that count - its output is\n// truncated to 100k results - while making every result ~1500 characters\n// long. The result set, and the intermediate arrays built while combining\n// brace sets, then grow large enough to exhaust memory and crash the process\n// (CVE-2026-14257). `EXPANSION_MAX_LENGTH` bounds the total number of\n// characters the accumulator may hold at any point, so memory stays flat no\n// matter how many brace groups are chained. The limit sits well above any\n// realistic expansion (100k results hitting `EXPANSION_MAX` measure ~1M\n// characters) so legitimate input is unaffected.\nexport const EXPANSION_MAX_LENGTH = 4_000_000\n\nfunction numeric(str: string) {\n return !isNaN(str as any) ? parseInt(str, 10) : str.charCodeAt(0)\n}\n\nfunction escapeBraces(str: string) {\n return str\n .replace(slashPattern, escSlash)\n .replace(openPattern, escOpen)\n .replace(closePattern, escClose)\n .replace(commaPattern, escComma)\n .replace(periodPattern, escPeriod)\n}\n\nfunction unescapeBraces(str: string) {\n return str\n .replace(escSlashPattern, '\\\\')\n .replace(escOpenPattern, '{')\n .replace(escClosePattern, '}')\n .replace(escCommaPattern, ',')\n .replace(escPeriodPattern, '.')\n}\n\n/**\n * Basically just str.split(\",\"), but handling cases\n * where we have nested braced sections, which should be\n * treated as individual members, like {a,{b,c},d}\n */\nfunction parseCommaParts(str: string) {\n if (!str) {\n return ['']\n }\n\n const parts: string[] = []\n const m = balanced('{', '}', str)\n\n if (!m) {\n return str.split(',')\n }\n\n const { pre, body, post } = m\n const p = pre.split(',')\n\n p[p.length - 1] += '{' + body + '}'\n const postParts = parseCommaParts(post)\n if (post.length) {\n ;(p[p.length - 1] as string) += postParts.shift()\n p.push.apply(p, postParts)\n }\n\n parts.push.apply(parts, p)\n\n return parts\n}\n\nexport type BraceExpansionOptions = {\n max?: number\n maxLength?: number\n}\n\nexport function expand(str: string, options: BraceExpansionOptions = {}) {\n if (!str) {\n return []\n }\n\n const { max = EXPANSION_MAX, maxLength = EXPANSION_MAX_LENGTH } = options\n\n // I don't know why Bash 4.3 does this, but it does.\n // Anything starting with {} will have the first two bytes preserved\n // but *only* at the top level, so {},a}b will not expand to anything,\n // but a{},b}c will be expanded to [a}c,abc].\n // One could argue that this is a bug in Bash, but since the goal of\n // this module is to match Bash's rules, we escape a leading {}\n if (str.slice(0, 2) === '{}') {\n str = '\\\\{\\\\}' + str.slice(2)\n }\n\n return expand_(escapeBraces(str), max, maxLength, true).map(unescapeBraces)\n}\n\nfunction embrace(str: string) {\n return '{' + str + '}'\n}\n\nfunction isPadded(el: string) {\n return /^-?0\\d/.test(el)\n}\n\nfunction lte(i: number, y: number) {\n return i <= y\n}\n\nfunction gte(i: number, y: number) {\n return i >= y\n}\n\n// Build `{ acc[a] + pre + values[v] }` for every combination, capping the\n// number of results at `max` and the total number of characters at `maxLength`.\n// This is the one place output grows, so bounding it here keeps the single\n// accumulator - and therefore memory - flat regardless of how many brace groups\n// are combined (CVE-2026-14257).\nfunction combine(\n acc: string[],\n pre: string,\n values: string[],\n max: number,\n maxLength: number,\n dropEmpties: boolean,\n): string[] {\n const out: string[] = []\n let length = 0\n for (let a = 0; a < acc.length; a++) {\n for (let v = 0; v < values.length; v++) {\n if (out.length >= max) return out\n const expansion = (acc[a] as string) + pre + values[v]\n // Bash drops empty results at the top level. Skip them before they count\n // against `max`, so `max` bounds the number of *kept* results.\n if (dropEmpties && !expansion) continue\n if (length + expansion.length > maxLength) return out\n out.push(expansion)\n length += expansion.length\n }\n }\n return out\n}\n\n// The expansion values of a single numeric (`1..5`) or alphabetic (`a..e..2`)\n// sequence body.\nfunction expandSequence(\n body: string,\n isAlphaSequence: boolean,\n max: number,\n): string[] {\n const n = body.split(/\\.\\./)\n const N: string[] = []\n // A sequence body always splits into two or three parts, but the compiler\n // can't know that.\n /* c8 ignore start */\n if (n[0] === undefined || n[1] === undefined) {\n return N\n }\n /* c8 ignore stop */\n const x = numeric(n[0])\n const y = numeric(n[1])\n const width = Math.max(n[0].length, n[1].length)\n let incr =\n n.length === 3 && n[2] !== undefined ?\n Math.max(Math.abs(numeric(n[2])), 1)\n : 1\n let test = lte\n const reverse = y < x\n if (reverse) {\n incr *= -1\n test = gte\n }\n const pad = n.some(isPadded)\n\n for (let i = x; test(i, y) && N.length < max; i += incr) {\n let c\n if (isAlphaSequence) {\n c = String.fromCharCode(i)\n if (c === '\\\\') {\n c = ''\n }\n } else {\n c = String(i)\n if (pad) {\n const need = width - c.length\n if (need > 0) {\n const z = new Array(need + 1).join('0')\n if (i < 0) {\n c = '-' + z + c.slice(1)\n } else {\n c = z + c\n }\n }\n }\n }\n N.push(c)\n }\n return N\n}\n\nfunction expand_(\n str: string,\n max: number,\n maxLength: number,\n isTop: boolean,\n): string[] {\n // Consume the string's top-level brace groups left to right, threading a\n // running set of combined prefixes (`acc`). Expanding the tail iteratively -\n // rather than recursing on `m.post` once per group - keeps the native stack\n // depth constant, so deeply chained input (`'{a,b}'.repeat(3000)`) can no\n // longer overflow the stack, and leaves a single accumulator whose size\n // `maxLength` bounds directly (CVE-2026-14257).\n let acc: string[] = ['']\n\n // Bash drops empty results, but only when the *first* top-level group is a\n // comma set - a sequence like `{a..\\}` may legitimately yield ''. The drop\n // is on the final strings, so it is applied to whichever `combine` produces\n // them (the one with no brace set left in the tail).\n let dropEmpties = false\n let firstGroup = true\n\n for (;;) {\n const m = balanced('{', '}', str)\n\n // No brace set left: the rest of the string is literal.\n if (!m) {\n return combine(acc, str, [''], max, maxLength, dropEmpties)\n }\n\n // no need to expand pre, since it is guaranteed to be free of brace-sets\n const pre = m.pre\n\n if (/\\$$/.test(pre)) {\n acc = combine(\n acc,\n pre + '{' + m.body + '}',\n [''],\n max,\n maxLength,\n dropEmpties && !m.post.length,\n )\n firstGroup = false\n if (!m.post.length) break\n str = m.post\n continue\n }\n\n const isNumericSequence = /^-?\\d+\\.\\.-?\\d+(?:\\.\\.-?\\d+)?$/.test(m.body)\n const isAlphaSequence = /^[a-zA-Z]\\.\\.[a-zA-Z](?:\\.\\.-?\\d+)?$/.test(\n m.body,\n )\n const isSequence = isNumericSequence || isAlphaSequence\n const isOptions = m.body.indexOf(',') >= 0\n if (!isSequence && !isOptions) {\n // {a},b}\n if (m.post.match(/,(?!,).*\\}/)) {\n str = m.pre + '{' + m.body + escClose + m.post\n isTop = true\n continue\n }\n // Nothing here expands, so the whole remaining string is literal.\n return combine(\n acc,\n pre + '{' + m.body + '}' + m.post,\n [''],\n max,\n maxLength,\n dropEmpties,\n )\n }\n\n if (firstGroup) {\n dropEmpties = isTop && !isSequence\n firstGroup = false\n }\n\n let values: string[]\n if (isSequence) {\n values = expandSequence(m.body, isAlphaSequence, max)\n } else {\n let n = parseCommaParts(m.body)\n if (n.length === 1 && n[0] !== undefined) {\n // x{{a,b}}y ==> x{a}y x{b}y\n n = expand_(n[0], max, maxLength, false).map(embrace)\n //XXX is this necessary? Can't seem to hit it in tests.\n /* c8 ignore start */\n if (n.length === 1) {\n acc = combine(\n acc,\n pre + n[0],\n [''],\n max,\n maxLength,\n dropEmpties && !m.post.length,\n )\n if (!m.post.length) break\n str = m.post\n continue\n }\n /* c8 ignore stop */\n }\n\n values = []\n for (let j = 0; j < n.length; j++) {\n values.push.apply(values, expand_(n[j] as string, max, maxLength, false))\n }\n }\n\n acc = combine(acc, pre, values, max, maxLength, dropEmpties && !m.post.length)\n if (!m.post.length) break\n str = m.post\n }\n\n return acc\n}\n"]}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,8 @@
1
+ export declare const EXPANSION_MAX = 100000;
2
+ export declare const EXPANSION_MAX_LENGTH = 4000000;
3
+ export type BraceExpansionOptions = {
4
+ max?: number;
5
+ maxLength?: number;
6
+ };
7
+ export declare function expand(str: string, options?: BraceExpansionOptions): string[];
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAkBA,eAAO,MAAM,aAAa,SAAU,CAAA;AAYpC,eAAO,MAAM,oBAAoB,UAAY,CAAA;AAwD7C,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,qBAA0B,YAkBtE"}