@cnwenf/occ 2.1.312 → 2.1.313

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.
Files changed (2) hide show
  1. package/dist/cli.js +89 -6
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bun
2
- globalThis.MACRO={"VERSION":"2.1.312","BINARY_NAME":"occ","BUILD_TIME":"2026-08-25T20:28:13.846Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
2
+ globalThis.MACRO={"VERSION":"2.1.313","BINARY_NAME":"occ","BUILD_TIME":"2026-08-26T18:15:46.386Z","FEEDBACK_CHANNEL":"","ISSUES_EXPLAINER":"","NATIVE_PACKAGE_URL":"","PACKAGE_URL":"@cnwenf/occ","VERSION_CHANGELOG":""};
3
3
  // @bun
4
4
  var __create = Object.create;
5
5
  var __getProtoOf = Object.getPrototypeOf;
@@ -59313,7 +59313,39 @@ function hasUnescapedEmptyParens(str) {
59313
59313
  }
59314
59314
  return false;
59315
59315
  }
59316
- function validatePermissionRule(rule) {
59316
+ function isOperatorToken(token) {
59317
+ return OPERATOR_TOKEN_RE.test(token);
59318
+ }
59319
+ function hasUnescapedStar(str) {
59320
+ for (let i2 = 0;i2 < str.length; i2++) {
59321
+ if (str[i2] === "*" && !isEscaped(str, i2))
59322
+ return true;
59323
+ }
59324
+ return false;
59325
+ }
59326
+ function wildcardBeforeSubcommand(content) {
59327
+ if (content.endsWith(":*"))
59328
+ return;
59329
+ const tokens = content.trim().split(/\s+/).filter(Boolean);
59330
+ const first = tokens[0];
59331
+ if (tokens.length < 3 || first === undefined || hasUnescapedStar(first)) {
59332
+ return;
59333
+ }
59334
+ let sawWildcard = false;
59335
+ for (const token of tokens.slice(1)) {
59336
+ if (isOperatorToken(token))
59337
+ return;
59338
+ if (hasUnescapedStar(token)) {
59339
+ sawWildcard = true;
59340
+ continue;
59341
+ }
59342
+ if (token.startsWith("-"))
59343
+ continue;
59344
+ return sawWildcard ? first : undefined;
59345
+ }
59346
+ return;
59347
+ }
59348
+ function validatePermissionRule(rule, behavior) {
59317
59349
  if (!rule || rule.trim() === "") {
59318
59350
  return { valid: false, error: "Permission rule cannot be empty" };
59319
59351
  }
@@ -59397,6 +59429,18 @@ function validatePermissionRule(rule) {
59397
59429
  examples: ["Bash(npm:*)", "Bash(git:*)"]
59398
59430
  };
59399
59431
  }
59432
+ if (behavior === "allow") {
59433
+ const flaggedCommand = wildcardBeforeSubcommand(content);
59434
+ if (flaggedCommand !== undefined) {
59435
+ const isGit = flaggedCommand === "git";
59436
+ const gitNote = isGit ? " For git, options such as -c and --exec-path can run arbitrary commands." : "";
59437
+ const gitExample = isGit ? " (for example Bash(git status *))" : "";
59438
+ return {
59439
+ valid: true,
59440
+ warning: `${permissionRuleValueToString(parsed)} has a wildcard before the rest of the command, so it also matches any options inserted at that position and approves them without a prompt.${gitNote} Replace that * with the exact value you mean, or only use * after the subcommand${gitExample}.`
59441
+ };
59442
+ }
59443
+ }
59400
59444
  }
59401
59445
  if (isFilePatternTool(parsed.toolName) && parsed.ruleContent !== undefined) {
59402
59446
  const content = parsed.ruleContent;
@@ -59436,13 +59480,14 @@ function validatePermissionRule(rule) {
59436
59480
  }
59437
59481
  return { valid: true };
59438
59482
  }
59439
- var PermissionRuleSchema;
59483
+ var OPERATOR_TOKEN_RE, PermissionRuleSchema;
59440
59484
  var init_permissionValidation = __esm(() => {
59441
59485
  init_v4();
59442
59486
  init_mcpStringUtils();
59443
59487
  init_permissionRuleParser();
59444
59488
  init_stringUtils();
59445
59489
  init_toolValidationConfig();
59490
+ OPERATOR_TOKEN_RE = /^(?:[|&;<>]|\d+[<>])/;
59446
59491
  PermissionRuleSchema = lazySchema(() => exports_external.string().superRefine((val, ctx) => {
59447
59492
  const result = validatePermissionRule(val);
59448
59493
  if (!result.valid) {
@@ -385289,6 +385334,35 @@ function hasQuotedBracketCloserInConditional(command4) {
385289
385334
  }
385290
385335
  return false;
385291
385336
  }
385337
+ function hasDanglingBooleanOperator(command4) {
385338
+ if (!command4.includes("&&") && !command4.includes("||"))
385339
+ return false;
385340
+ let inSingle = false;
385341
+ let inDouble = false;
385342
+ let lastBoolOpEnd = -1;
385343
+ for (let i6 = 0;i6 < command4.length; i6++) {
385344
+ const ch2 = command4[i6];
385345
+ if (ch2 === "\\" && !inSingle) {
385346
+ i6++;
385347
+ continue;
385348
+ }
385349
+ if (ch2 === "'" && !inDouble) {
385350
+ inSingle = !inSingle;
385351
+ continue;
385352
+ }
385353
+ if (ch2 === '"' && !inSingle) {
385354
+ inDouble = !inDouble;
385355
+ continue;
385356
+ }
385357
+ if (inSingle || inDouble)
385358
+ continue;
385359
+ if (ch2 === "&" && command4[i6 + 1] === "&" || ch2 === "|" && command4[i6 + 1] === "|") {
385360
+ lastBoolOpEnd = i6 + 2;
385361
+ i6++;
385362
+ }
385363
+ }
385364
+ return lastBoolOpEnd !== -1 && command4.slice(lastBoolOpEnd).trim() === "";
385365
+ }
385292
385366
  async function bashToolHasPermission(input, context4, getCommandSubcommandPrefixFn = getCommandSubcommandPrefix) {
385293
385367
  let appState = context4.getAppState();
385294
385368
  {
@@ -385388,6 +385462,15 @@ async function bashToolHasPermission(input, context4, getCommandSubcommandPrefix
385388
385462
  };
385389
385463
  }
385390
385464
  }
385465
+ {
385466
+ const mode = appState.toolPermissionContext.mode;
385467
+ if (mode !== "bypassPermissions" && hasDanglingBooleanOperator(input.command)) {
385468
+ return {
385469
+ behavior: "ask",
385470
+ message: "Malformed command with a dangling && or || operator requires confirmation."
385471
+ };
385472
+ }
385473
+ }
385391
385474
  const injectionCheckDisabled = isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_COMMAND_INJECTION_CHECK);
385392
385475
  const shadowEnabled = feature("TREE_SITTER_BASH_SHADOW") ? getFeatureValue_CACHED_MAY_BE_STALE("tengu_birch_trellis", true) : false;
385393
385476
  let astRoot = injectionCheckDisabled ? null : feature("TREE_SITTER_BASH_SHADOW") && !shadowEnabled ? null : await parseCommandRaw(input.command);
@@ -635547,19 +635630,19 @@ async function initializeToolPermissionContext({
635547
635630
  }
635548
635631
  for (const rule of rulesFromDisk) {
635549
635632
  const ruleStr = permissionRuleValueToString(rule.ruleValue);
635550
- const result = validatePermissionRule(ruleStr);
635633
+ const result = validatePermissionRule(ruleStr, rule.ruleBehavior);
635551
635634
  if (result.valid && result.warning) {
635552
635635
  warnings.push(`Permission ${rule.ruleBehavior} rule (${formatPermissionSource(rule.source)}): ${result.warning}`);
635553
635636
  }
635554
635637
  }
635555
635638
  for (const ruleStr of parsedAllowedToolsCli) {
635556
- const result = validatePermissionRule(ruleStr);
635639
+ const result = validatePermissionRule(ruleStr, "allow");
635557
635640
  if (result.valid && result.warning) {
635558
635641
  warnings.push(`Permission allow rule (--allowed-tools): ${result.warning}`);
635559
635642
  }
635560
635643
  }
635561
635644
  for (const ruleStr of parsedDisallowedToolsCli) {
635562
- const result = validatePermissionRule(ruleStr);
635645
+ const result = validatePermissionRule(ruleStr, "deny");
635563
635646
  if (result.valid && result.warning) {
635564
635647
  warnings.push(`Permission deny rule (--disallowed-tools): ${result.warning}`);
635565
635648
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cnwenf/occ",
3
- "version": "2.1.312",
3
+ "version": "2.1.313",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "bin": {