Skip to content

fix(exec): support bare command patterns in approvals allowlist#61208

Closed
mvanhorn wants to merge 4 commits intoopenclaw:mainfrom
mvanhorn:fix/61193-exec-approvals-bare-patterns
Closed

fix(exec): support bare command patterns in approvals allowlist#61208
mvanhorn wants to merge 4 commits intoopenclaw:mainfrom
mvanhorn:fix/61193-exec-approvals-bare-patterns

Conversation

@mvanhorn
Copy link
Copy Markdown
Contributor

@mvanhorn mvanhorn commented Apr 5, 2026

Summary

  • Problem: exec approvals allowlist silently skips patterns without path separators (/, \, ~). Patterns like python3 or node are accepted by openclaw approvals allowlist add but never matched during command evaluation.
  • Why it matters: users configure allowlist rules expecting python3 to match /usr/bin/python3, but the pattern is silently ignored. Commands that should be auto-approved still require manual approval.
  • What changed: when a pattern has no path separators, matchAllowlist() now matches it against executableName (the basename) instead of skipping it entirely.
  • What did NOT change: path-based patterns still match against resolvedPath as before. The bare * wildcard shortcut is unchanged.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

Root Cause

matchAllowlist() in src/infra/exec-command-resolution.ts:353-355 has a guard that checks hasPath and skips any pattern without /, \, or ~. Bare executable names like python3 fail this check and are silently dropped from evaluation. The fix routes bare patterns through matchesExecAllowlistPattern() with executableName as the target instead of resolvedPath, preserving argPattern semantics on Windows.

This contribution was developed with AI assistance (Claude Code).

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 5, 2026

Greptile Summary

This PR fixes the silent-skip of bare executable name patterns (e.g. python3, node) in matchAllowlist() by routing them through matchesExecAllowlistPattern() against executableName instead of discarding them when no path separator is present. The fix is correct for Linux and macOS, but on Windows executableName includes the .exe extension (e.g. python3.exe), so a bare pattern python3 still won't produce a match, leaving the original bug unfixed on that platform.

Confidence Score: 4/5

Safe to merge for Linux/macOS users, but Windows users will still experience silent allowlist failures for bare patterns.

One P1 remains: the bare-pattern matching against executableName doesn't account for the .exe extension Windows adds, so the bug is not fixed on that platform. Scoring 4 rather than 5 because this is a present defect on the changed code path for a security-adjacent feature (exec approvals).

src/infra/exec-command-resolution.ts lines 355-371 (bare-pattern branch); src/infra/exec-allowlist-matching.test.ts (missing Windows/.exe coverage)

Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/infra/exec-command-resolution.ts
Line: 358-371

Comment:
**Bare patterns still silently fail on Windows due to `.exe` extension mismatch**

The new branch matches `pattern` against `resolution.executableName`, which on Windows is `path.basename(resolvedPath)` — e.g. `python3.exe` — because Windows resolves `python3``C:\Python39\python3.exe`. Inside `matchesExecAllowlistPattern`, a non-wildcard pattern on win32 has `tryRealpath("python3")` return null (not an absolute path), so `normalizedPattern` stays `python3` while `normalizedTarget` stays `python3.exe`. The compiled regex `^python3$` does not match `python3.exe`, so the entry is silently skipped — the same class of bug this PR intended to fix. The PR description doesn't acknowledge this Windows caveat.

A targeted fix is to strip the `.exe` suffix from `executableName` before the comparison when on Windows:

```typescript
      // On Windows, executableName includes the .exe extension that bare patterns lack
      const effectiveExecName =
        useArgPattern && resolution.executableName.toLowerCase().endsWith(".exe")
          ? resolution.executableName.slice(0, -4)
          : resolution.executableName;
      if (matchesExecAllowlistPattern(pattern, effectiveExecName)) {
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/infra/exec-allowlist-matching.test.ts
Line: 22-39

Comment:
**No test coverage for Windows `.exe` bare-pattern scenario**

The new test block only exercises Unix-style `executableName` values (e.g. `python3`, `rg`). There is no case where `executableName` carries a `.exe` suffix (the Windows norm), so the regression described above — bare pattern `python3` not matching `executableName = "python3.exe"` — would not be caught by CI on Linux runners.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "fix(exec): support bare command patterns..." | Re-trigger Greptile

Comment thread src/infra/exec-command-resolution.ts Outdated
Comment on lines +358 to +371
if (matchesExecAllowlistPattern(pattern, resolution.executableName)) {
if (!useArgPattern) {
return entry;
}
if (!entry.argPattern) {
if (!pathOnlyMatch) {
pathOnlyMatch = entry;
}
continue;
}
if (argv && matchArgPattern(entry.argPattern, argv, platform)) {
return entry;
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Bare patterns still silently fail on Windows due to .exe extension mismatch

The new branch matches pattern against resolution.executableName, which on Windows is path.basename(resolvedPath) — e.g. python3.exe — because Windows resolves python3C:\Python39\python3.exe. Inside matchesExecAllowlistPattern, a non-wildcard pattern on win32 has tryRealpath("python3") return null (not an absolute path), so normalizedPattern stays python3 while normalizedTarget stays python3.exe. The compiled regex ^python3$ does not match python3.exe, so the entry is silently skipped — the same class of bug this PR intended to fix. The PR description doesn't acknowledge this Windows caveat.

A targeted fix is to strip the .exe suffix from executableName before the comparison when on Windows:

      // On Windows, executableName includes the .exe extension that bare patterns lack
      const effectiveExecName =
        useArgPattern && resolution.executableName.toLowerCase().endsWith(".exe")
          ? resolution.executableName.slice(0, -4)
          : resolution.executableName;
      if (matchesExecAllowlistPattern(pattern, effectiveExecName)) {
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/exec-command-resolution.ts
Line: 358-371

Comment:
**Bare patterns still silently fail on Windows due to `.exe` extension mismatch**

The new branch matches `pattern` against `resolution.executableName`, which on Windows is `path.basename(resolvedPath)` — e.g. `python3.exe` — because Windows resolves `python3``C:\Python39\python3.exe`. Inside `matchesExecAllowlistPattern`, a non-wildcard pattern on win32 has `tryRealpath("python3")` return null (not an absolute path), so `normalizedPattern` stays `python3` while `normalizedTarget` stays `python3.exe`. The compiled regex `^python3$` does not match `python3.exe`, so the entry is silently skipped — the same class of bug this PR intended to fix. The PR description doesn't acknowledge this Windows caveat.

A targeted fix is to strip the `.exe` suffix from `executableName` before the comparison when on Windows:

```typescript
      // On Windows, executableName includes the .exe extension that bare patterns lack
      const effectiveExecName =
        useArgPattern && resolution.executableName.toLowerCase().endsWith(".exe")
          ? resolution.executableName.slice(0, -4)
          : resolution.executableName;
      if (matchesExecAllowlistPattern(pattern, effectiveExecName)) {
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +22 to +39
it("matches bare executable name patterns without path separators", () => {
// Exact bare name match
expect(matchAllowlist([{ pattern: "rg" }], baseResolution)?.pattern).toBe("rg");

// Bare name should be case-sensitive (no match for wrong case)
expect(matchAllowlist([{ pattern: "RG" }], baseResolution)?.pattern ?? null).toBe(null);

// Bare name matches regardless of resolved path
const pythonResolution = {
rawExecutable: "python3",
resolvedPath: "/usr/bin/python3",
executableName: "python3",
};
expect(matchAllowlist([{ pattern: "python3" }], pythonResolution)?.pattern).toBe("python3");

// Bare name does not match a different executable
expect(matchAllowlist([{ pattern: "node" }], pythonResolution)?.pattern ?? null).toBe(null);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No test coverage for Windows .exe bare-pattern scenario

The new test block only exercises Unix-style executableName values (e.g. python3, rg). There is no case where executableName carries a .exe suffix (the Windows norm), so the regression described above — bare pattern python3 not matching executableName = "python3.exe" — would not be caught by CI on Linux runners.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/infra/exec-allowlist-matching.test.ts
Line: 22-39

Comment:
**No test coverage for Windows `.exe` bare-pattern scenario**

The new test block only exercises Unix-style `executableName` values (e.g. `python3`, `rg`). There is no case where `executableName` carries a `.exe` suffix (the Windows norm), so the regression described above — bare pattern `python3` not matching `executableName = "python3.exe"` — would not be caught by CI on Linux runners.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9425a2f200

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/infra/exec-command-resolution.ts Outdated
Comment on lines +359 to +360
if (!useArgPattern) {
return entry;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep wildcard+argPattern entries from becoming global allow

The new bare-pattern branch now returns early on non-Windows whenever matchesExecAllowlistPattern() succeeds, so an entry like { pattern: "*", argPattern: "..." } becomes an unconditional allow for every executable on Linux/macOS. Previously, the code intentionally only treated bare * as a wildcard when argPattern was absent (bareWild check), and * with argPattern did not match at all. This is a policy-widening regression for any approvals JSON that contains wildcard entries with argPattern (manual edits, imported files, or future tooling), and it can silently bypass expected exec gating.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c41f835898

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +373 to +374
if (argv && matchArgPattern(entry.argPattern, argv, platform)) {
return entry;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Prevent wildcard argPattern from bypassing executable scoping

In normal allowlist evaluation, resolveSegmentAllowlistMatch() calls matchAllowlist(..., effectiveArgv, ...), so argv is present for real command checks; with that input, a rule like { pattern: "*", argPattern: "..." } now matches any executable on Linux/macOS whenever the arg regex matches because * passes matchesExecAllowlistPattern() for every bareTarget and the branch then returns on argPattern alone. Fresh evidence compared with the prior comment is that this widened path is exercised in production via src/infra/exec-approvals-allowlist.ts:427-431.

Useful? React with 👍 / 👎.

Comment thread src/infra/exec-command-resolution.ts Outdated
Comment on lines +360 to +361
if (useArgPattern && bareTarget.toLowerCase().endsWith(".exe")) {
bareTarget = bareTarget.slice(0, -4);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve .exe bare-pattern matching on Windows

This always strips .exe from the executable name before bare-pattern matching when Windows logic is enabled, which means explicit bare rules such as python3.exe or *.exe can never match (they are compared against python3). That silently breaks valid user-entered bare patterns on Windows and makes part of the new bare-pattern support unreliable.

Useful? React with 👍 / 👎.

@mvanhorn mvanhorn force-pushed the fix/61193-exec-approvals-bare-patterns branch from c41f835 to c9fe485 Compare April 5, 2026 06:29
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9fe485de4

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

expect(matchAllowlist([{ pattern: "rg" }], baseResolution)?.pattern).toBe("rg");

// Bare name should be case-sensitive (no match for wrong case)
expect(matchAllowlist([{ pattern: "RG" }], baseResolution)?.pattern ?? null).toBe(null);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Make bare-name case test platform-aware

The new assertion that "RG" should not match "rg" is only true on non-Windows platforms, but matchAllowlist() uses Windows-style case-insensitive matching when process.platform === "win32" (via matchesExecAllowlistPattern), so this test now fails in Windows CI (checks-windows-node-test) even though the runtime behavior is expected there. Guard this expectation by platform (or split per-platform expectations) so the suite remains deterministic across runners.

Useful? React with 👍 / 👎.

@mvanhorn mvanhorn force-pushed the fix/61193-exec-approvals-bare-patterns branch from 8e56b07 to 3fe336e Compare April 5, 2026 15:11
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3fe336ec24

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/infra/exec-command-resolution.ts Outdated
if (useArgPattern && bareTarget.toLowerCase().endsWith(".exe")) {
bareTarget = bareTarget.slice(0, -4);
}
if (matchesExecAllowlistPattern(pattern, bareTarget)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Honor target platform when matching bare executables

This new bare-pattern branch uses the caller-supplied platform to enable Windows behavior (including .exe stripping), but the actual pattern check still goes through matchesExecAllowlistPattern, which derives case/path semantics from process.platform. In mixed-host setups (for example, a Linux gateway evaluating a Windows node command with platform: "win32"), bare rules can fail unexpectedly ("RG" won’t match "rg.exe") because matching stays host-case-sensitive. That makes bare-name approvals dependent on gateway OS rather than the target command platform.

Useful? React with 👍 / 👎.

@mvanhorn mvanhorn force-pushed the fix/61193-exec-approvals-bare-patterns branch from 3fe336e to 4198be4 Compare April 5, 2026 15:16
…rrectness

matchesExecAllowlistPattern now accepts an optional platform parameter
so that a Linux host evaluating Windows-target commands uses
case-insensitive matching as the target platform expects, rather than
the host's process.platform.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e7266a572f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/infra/exec-command-resolution.ts Outdated
Comment on lines +360 to +361
if (useArgPattern && bareTarget.toLowerCase().endsWith(".exe")) {
bareTarget = bareTarget.slice(0, -4);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Match bare names against all Windows PATHEXT shims

The new bare-name logic only strips .exe before matching, so on Windows a rule like pattern: "npm" will not match common shim executables such as npm.cmd/npm.bat even though resolveExecutablePath() resolves commands through PATHEXT entries. This means the bare-pattern fix still misses many real Windows commands and users will continue getting unexpected approval prompts for those binaries.

Useful? React with 👍 / 👎.

…hing

Use path.parse to strip extensions instead of hardcoded .exe check.
Try matching both original and stripped executable names so explicit
extension patterns (python3.exe) still work alongside bare patterns
(python3). Gate extension handling on win32 platform, not useArgPattern.
@aisle-research-bot
Copy link
Copy Markdown

aisle-research-bot Bot commented Apr 9, 2026

🔒 Aisle Security Analysis

We found 2 potential security issue(s) in this PR:

# Severity Title
1 🟠 High Allowlist bypass via bare executable-name matching (PATH hijacking)
2 🟠 High Allowlist argPattern bypass via spoofed/invalid platform parameter in matchAllowlist()
1. 🟠 Allowlist bypass via bare executable-name matching (PATH hijacking)
Property Value
Severity High
CWE CWE-284
Location src/infra/exec-command-resolution.ts:354-387

Description

matchAllowlist now treats allowlist patterns without path separators as matching only the resolved executable's basename (resolution.executableName), not the resolved path.

This weakens the allowlist from "approved binary at an approved path" to "any binary with an approved name", enabling allowlist bypass in environments where an attacker can influence resolution (e.g., by controlling PATH, current working directory resolution for relative paths, or placing a malicious executable earlier in PATH).

  • Input: allowlist entry pattern (e.g., "python3", "node")
  • Input/Influence: resolution.resolvedPath is obtained by searching PATH (resolveExecutablePath), which can use caller-supplied env (options.env.PATH).
  • Sink: approval decision in matchAllowlist returns allowlist entry based only on basename match, ignoring the directory/realpath.

Vulnerable code:

const hasPath = pattern.includes("/") || pattern.includes("\\") || pattern.includes("~");
if (!hasPath) {
  const bareTargets = [resolution.executableName];// ...
  if (bareTargets.some((target) =>
      matchesExecAllowlistPattern(pattern, target, effectivePlatform))) {
    return entry; // (non-Windows)
  }
}

Impact examples:

  • Allowlist contains node; attacker places a trojan node earlier in PATH → execution is allowed.
  • On Windows, python3 allowlist matches python3.exe anywhere due to stripped-extension matching.

Recommendation

Re-pin allowlist matching to a path identity rather than only a basename.

Options (choose based on intended security model):

  1. Require path separators for executable allowlisting (safest): treat bare patterns as invalid / non-matching and require explicit absolute paths or anchored path globs.

  2. If bare names must be supported, restrict them to a trusted set of directories or a verified realpath:

    • Resolve to resolvedRealPath and compare against an allowlisted directory prefix list
    • Or compare resolvedRealPath to a precomputed expected path for that name (no PATH search)

Example safer approach (require full path match):

// Only allow path patterns; bare patterns do not authorize execution
if (!hasPath) continue;
if (!matchesExecAllowlistPattern(pattern, resolution.resolvedRealPath ?? resolvedPath, effectivePlatform)) {
  continue;
}

Also consider:

  • Avoid using caller-controlled env.PATH when deciding policy, or explicitly pass a sanitized PATH for resolution.
  • Document that name-only patterns are insecure in adversarial environments if they remain supported.
2. 🟠 Allowlist argPattern bypass via spoofed/invalid platform parameter in matchAllowlist()
Property Value
Severity High
CWE CWE-285
Location src/infra/exec-command-resolution.ts:345-395

Description

matchAllowlist() disables argPattern enforcement unless the (caller-supplied) platform string starts with "win". When useArgPattern is false, any path-matched allowlist entry is treated as a match even if it has an argPattern, preserving legacy non-Windows behavior.

This becomes a security issue when platform originates from untrusted/remote metadata (e.g., node info from the gateway): an attacker can supply a non-Windows platform value (or otherwise influence it) to force useArgPattern=false, thereby bypassing the intended argument restrictions on Windows-target allowlist entries.

Relevant behavior:

  • useArgPattern is derived from platform (string) rather than a trusted local platform value.
  • When useArgPattern is false, argPattern is ignored and the first path match returns.

Vulnerable code:

const effectivePlatform = (platform ?? process.platform) as NodeJS.Platform;
const normalizedPlatform = String(effectivePlatform).trim().toLowerCase();
const useArgPattern = normalizedPlatform.startsWith("win");
...
if (!useArgPattern) {// Non-Windows: first path match wins (legacy behaviour).
  return entry;
}

And one concrete call site where platform comes from remote node metadata:

platform: nodeInfo?.platform,

(from src/agents/bash-tools.exec-host-node.ts).

Impact depends on deployment, but if allowlist entries rely on argPattern to constrain dangerous binaries on Windows nodes, spoofing the platform can widen allowlist matches and enable execution of unintended argument variants.

Recommendation

Fail closed and/or remove trust in caller-supplied platform for security decisions.

Recommended options:

  1. Validate and canonicalize platform against an allowlist of known values ("win32", "linux", "darwin", etc.). Treat unknown/invalid values as requiring argPattern checks (or reject matching):
const raw = (platform ?? process.platform);
const normalized = String(raw).trim().toLowerCase();
const known = new Set(["win32","linux","darwin","aix","freebsd","openbsd","sunos","android","cygwin","netbsd"]);
const safePlatform = known.has(normalized) ? (normalized as NodeJS.Platform) : process.platform;
const useArgPattern = safePlatform === "win32";
  1. Enforce argPattern whenever an entry has one, regardless of platform (or at minimum when platform is provided externally):
if (entry.argPattern) {
  if (!argv) continue;            // or return null / fail closed
  if (!matchArgPattern(entry.argPattern, argv, safePlatform)) continue;
  return entry;
}
  1. At call sites that use remote node metadata (e.g., nodeInfo.platform), do not trust the value for policy enforcement unless it is authenticated/verified. Consider deriving platform from an authenticated node capability handshake or enforce stricter policy when platform is missing/unknown.

Analyzed PR: #61208 at commit 74e8cb7

Last updated on: 2026-04-09T14:06:11Z

@mvanhorn
Copy link
Copy Markdown
Contributor Author

mvanhorn commented Apr 9, 2026

Addressed the bot feedback on bare-pattern matching:

  • Fixed .exe stripping condition: now gates on effectivePlatform === 'win32' instead of useArgPattern. Extension stripping should happen on Windows regardless of whether argv was provided.
  • Handles all PATHEXT extensions via path.parse().name instead of hardcoded .exe check. This catches .cmd, .bat, .ps1, .com, etc.
  • Tests both original and stripped executable names, so explicit extension patterns like python3.exe still match while bare patterns like python3 also work.
  • Added test cases for .cmd extension matching and explicit .exe pattern matching.

Pushed in 74e8cb7.

@mvanhorn
Copy link
Copy Markdown
Contributor Author

Closing - 17 days with no maintainer signal and base has drifted. The allowlist still silently skips patterns without path separators like python3 and node. Happy to resubmit if the team wants it.

@mvanhorn mvanhorn closed this Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: exec approvals allowlist glob pattern not matching commands

1 participant