@wrongstack/core 0.3.2 → 0.3.4

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.
@@ -4,7 +4,7 @@ import { e as AttachmentStore, A as AddAttachmentInput, d as AttachmentRef, a as
4
4
  export { D as DefaultSessionReader } from '../session-reader-CcPi4BQ8.js';
5
5
  import { b as MemoryStore, a as MemoryScope } from '../memory-CEXuo7sz.js';
6
6
  import { a as WstackPaths } from '../wstack-paths-BGu2INTm.js';
7
- import { c as ConfigStore, a as Config, b as ConfigLoader } from '../config-D2qvAxVd.js';
7
+ import { c as ConfigStore, a as Config, b as ConfigLoader } from '../config-DgE3JslD.js';
8
8
  import { S as SecretVault } from '../secret-vault-DoISxaKO.js';
9
9
  import '../models-registry-Y2xbog0E.js';
10
10
 
@@ -1357,6 +1357,42 @@ function defaultIsPidAlive(pid) {
1357
1357
  }
1358
1358
  }
1359
1359
 
1360
+ // src/utils/regex-guard.ts
1361
+ var MAX_PATTERN_LEN = 512;
1362
+ var DANGEROUS_PATTERNS = [
1363
+ /(\([^)]*[+*][^)]*\))[+*]/,
1364
+ // (a+)+, (.*)+, etc
1365
+ /(\(\?:[^)]*[+*][^)]*\))[+*]/
1366
+ // same, with non-capturing group
1367
+ ];
1368
+ function compileUserRegex(pattern, flags) {
1369
+ if (typeof pattern !== "string") {
1370
+ return { ok: false, reason: "pattern must be a string" };
1371
+ }
1372
+ if (pattern.length === 0) {
1373
+ return { ok: false, reason: "pattern is empty" };
1374
+ }
1375
+ if (pattern.length > MAX_PATTERN_LEN) {
1376
+ return { ok: false, reason: `pattern exceeds ${MAX_PATTERN_LEN} characters` };
1377
+ }
1378
+ for (const rx of DANGEROUS_PATTERNS) {
1379
+ if (rx.test(pattern)) {
1380
+ return {
1381
+ ok: false,
1382
+ reason: "pattern looks vulnerable to catastrophic backtracking \u2014 rewrite without nested quantifiers"
1383
+ };
1384
+ }
1385
+ }
1386
+ try {
1387
+ return { ok: true, regex: new RegExp(pattern, flags) };
1388
+ } catch (err) {
1389
+ return {
1390
+ ok: false,
1391
+ reason: err instanceof Error ? err.message : "invalid regex"
1392
+ };
1393
+ }
1394
+ }
1395
+
1360
1396
  // src/storage/session-reader.ts
1361
1397
  var DefaultSessionReader = class {
1362
1398
  store;
@@ -1451,7 +1487,11 @@ function buildMatcher(q) {
1451
1487
  const ci = q.caseInsensitive ?? true;
1452
1488
  if (q.regex) {
1453
1489
  const flags = ci ? "i" : "";
1454
- const re = new RegExp(q.query, flags);
1490
+ const compiled = compileUserRegex(q.query, flags);
1491
+ if (!compiled.ok) {
1492
+ throw new Error(`Invalid search regex "${q.query}": ${compiled.reason}`);
1493
+ }
1494
+ const re = compiled.regex;
1455
1495
  return (text) => {
1456
1496
  const m = re.exec(text);
1457
1497
  return m ? { start: m.index, end: m.index + m[0].length } : null;