reasonix 0.26.0 → 0.26.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/dist/index.d.ts CHANGED
@@ -1191,7 +1191,7 @@ interface ShellToolsOptions {
1191
1191
  declare function tokenizeCommand(cmd: string): string[];
1192
1192
  /** Up-front detection — without it, `dir | findstr foo` quotes `|` literal and pipe silently fails. */
1193
1193
  declare function detectShellOperator(cmd: string): string | null;
1194
- /** Match on space-normalized leading tokens `git status -s` matches the `git status` prefix. */
1194
+ /** Allowlist match on leading argv tokens; demoted by `RISKY_ARGS` when a destructive flag appears in the tail. */
1195
1195
  declare function isAllowed(cmd: string, extra?: readonly string[]): boolean;
1196
1196
  interface RunCommandResult {
1197
1197
  exitCode: number | null;
package/dist/index.js CHANGED
@@ -6406,12 +6406,65 @@ function detectShellOperator(cmd) {
6406
6406
  if (quote) return null;
6407
6407
  return check();
6408
6408
  }
6409
+ var RISKY_ARGS = {
6410
+ // Branch / remote mutation
6411
+ "git branch": ["-d", "-D", "--delete", "-m", "-M", "--move", "-c", "-C", "--copy", "--force"],
6412
+ "git remote": ["add", "remove", "rm", "rename", "set-url", "set-head", "prune"],
6413
+ // `--output` writes to an arbitrary path; `--ext-diff` invokes user-config'd external programs.
6414
+ "git diff": ["--output", "--ext-diff"],
6415
+ "git log": ["--output"],
6416
+ "git show": ["--output"],
6417
+ // `-exec*` / `-ok*` are RCE; `-delete` and `-fprint*` / `-fls` write to arbitrary paths.
6418
+ find: [
6419
+ "-delete",
6420
+ "-exec",
6421
+ "-execdir",
6422
+ "-ok",
6423
+ "-okdir",
6424
+ "-fprint",
6425
+ "-fprint0",
6426
+ "-fprintf",
6427
+ "-fls"
6428
+ ],
6429
+ // `-o FILE` writes the tree to an arbitrary path.
6430
+ tree: ["-o"],
6431
+ // Auto-fix mutates source files.
6432
+ "npx eslint": ["--fix", "--fix-dry-run"],
6433
+ "npx biome check": ["--write", "--apply", "--apply-unsafe"],
6434
+ ruff: ["--fix", "--unsafe-fixes", "format"]
6435
+ };
6436
+ function tailHasRisky(tail, risky) {
6437
+ for (const a of tail) {
6438
+ for (const r of risky) {
6439
+ if (a === r) return true;
6440
+ if (a.startsWith(`${r}=`)) return true;
6441
+ }
6442
+ }
6443
+ return false;
6444
+ }
6409
6445
  function isAllowed(cmd, extra = []) {
6410
- const normalized = cmd.trim().replace(/\s+/g, " ");
6446
+ let argv;
6447
+ try {
6448
+ argv = tokenizeCommand(cmd);
6449
+ } catch {
6450
+ return false;
6451
+ }
6452
+ if (argv.length === 0) return false;
6411
6453
  const allowlist = [...BUILTIN_ALLOWLIST, ...extra];
6412
6454
  for (const prefix of allowlist) {
6413
- if (normalized === prefix) return true;
6414
- if (normalized.startsWith(`${prefix} `)) return true;
6455
+ const prefixTokens = prefix.split(" ");
6456
+ if (argv.length < prefixTokens.length) continue;
6457
+ let match = true;
6458
+ for (let i = 0; i < prefixTokens.length; i++) {
6459
+ if (argv[i] !== prefixTokens[i]) {
6460
+ match = false;
6461
+ break;
6462
+ }
6463
+ }
6464
+ if (!match) continue;
6465
+ const risky = RISKY_ARGS[prefix];
6466
+ if (risky && tailHasRisky(argv.slice(prefixTokens.length), risky)) return false;
6467
+ return true;
6415
6468
  }
6416
6469
  return false;
6417
6470
  }