Skip to content

fix(lp1): backport scoped allowed-tools support to 2.13.x - #976

Merged
rng1995 merged 4 commits into
yashraj/v2.13.0-basefrom
codex/scoped-bash-maintenance
Nov 2, 2026
Merged

rng1995 merged 4 commits into
yashraj/v2.13.0-basefrom
codex/scoped-bash-maintenance

Conversation

@rng1995

@rng1995 rng1995 commented Nov 2, 2026 •

Copy link
Copy Markdown
Collaborator

SkillSpector 2.13.3 still treats scoped declarations such as Bash(git:*) as unknown tools and splits Bash(git rev-parse:*) Read inside the scope. This produces a false HIGH LP1 undeclared-shell finding even though shell capability is declared.

Backport the existing fix from #768 onto the 2.13.x maintenance base, preserving its shared scope parser, malformed-grant checks, declaration limits, and original author/sign-offs. The manifest retains the command restrictions. This branch does not change release versions or publish an artifact.

Validation:

  • Replayed upstream regression tests before implementation: 29 expected failures on unmodified v2.13.3.
  • All 41 focused scoped-grant regression tests pass after the backport.
  • Built and installed a wheel, then exercised five real frontmatter-to-LP cases, including Bash(git rev-parse:*), comma formatting, malformed Bash, and Bash text embedded in a Read scope. All pass.
  • Repository Ruff checks and formatting checks for the changed Python files pass.
  • Independent review found no blocking issue.
  • Final focused run with locked Click/Typer and a dedicated temporary directory: 77 passed.
  • Expanded LP/build-context/CLI run: 208 passed; two 30-second CLI-import timeouts passed on serial retry. The dense-directory timing guard also passed on that retry (3 passed).
  • CI Docker smoke, lint, OpenCode TypeScript, changes, and DCO checks pass. The full CI unit job is pending.

Local full-suite validation was not completed: an earlier run stopped after 2,274 passes and five CLI stderr-capture failures under inherited Click 8.1.8. All affected test_recursive_incomplete_hidden_discovery_preserves_existing_output and test_cli_mcp_registry_rejects_ignored_options_before_scanning cases now pass with lockfile Click 8.4.2 / Typer 0.23.2. No production changes were made for the local test environment.

Targets yashraj/v2.13.0-base because main already contains #768. Related issue: #766.

Zhuoxi2000 and others added 4 commits November 2, 2026 10:30
… name

_map_allowed_tools_to_categories looked up the whole allowed-tools entry,
so a scoped grant in the Tool(specifier) form (the Agent Skills spec's own
example syntax) mapped to no category. A skill declaring Bash(git:*) then
got LP1 HIGH for shell, while the broader bare Bash grant got nothing.

Look up only the tool name before an optional "(", bounding the search so
long specifiers are not copied. Add tests for the list, space and comma
forms and a negative control where Read(...) must not cover shell.

Signed-off-by: Edson <zhuoxi2000@gmail.com>
(cherry picked from commit 4666a72)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
… ones

Splitting a string allowed-tools value on every comma or whitespace cut
scoped grants apart: "Read(./docs Bash(notes).md)" became "Read(./docs"
and "Bash(notes).md)", and the tool-name lookup then read the second
fragment as a Bash grant. LP1 was suppressed for shell code although
only Read was declared. An incomplete entry such as "Bash(" also mapped
to shell.

Add skillspector.allowed_tools with a splitter that only splits on
separators outside parentheses, choosing the comma form only when a
comma appears outside parentheses, and a validator that accepts a bare
tool name or Tool(specifier) with a non-blank, balanced specifier whose
closing parenthesis ends the entry. build_context and the LP analyzer
share the splitter, and only valid grants map to a category. Malformed
entries still count as an allowed-tools declaration for LP3 but cover
no capability.

Signed-off-by: Edson <zhuoxi2000@gmail.com>
(cherry picked from commit 2ca88a3)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Claude Code's permission rule syntax treats parentheses inside a
Tool(specifier) specifier as literal characters. The grant validator
required them to balance and the string splitter counted nesting depth,
so a complete grant such as Bash(echo '(') or Bash(echo ')') mapped to
no tool, and LP1 was raised for shell code the grant covers. In a string
value, "Bash(echo '(') Read" was also kept as a single entry.

The validator now takes the specifier as everything between the first
"(" and the final ")", which must end the entry, and only requires it
to be non-blank. The splitter opens a specifier at "(" and closes it at
the first ")" followed by a comma, whitespace or the end of the value;
parentheses in between are literal. Incomplete grants such as "Bash(",
"Bash(notes" or "Bash(echo '('" and blank ones such as "Bash()" still
map to nothing, and "Read(./docs Bash(notes).md)" stays one Read grant.

Under the literal reading, the list entries "Bash(notes).md)" and
"Bash(a)(b)" are complete Bash grants, so their tests move from the
malformed cases to the valid ones.

Signed-off-by: Edson <zhuoxi2000@gmail.com>
(cherry picked from commit 318b972)
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
Signed-off-by: Narendran Raghavan <nraghavan@nvidia.com>
@rng1995
rng1995 marked this pull request as ready for review November 2, 2026 18:53
@rng1995
rng1995 merged commit 8882c8f into yashraj/v2.13.0-base Nov 2, 2026
6 checks passed
@rng1995
rng1995 deleted the codex/scoped-bash-maintenance branch November 2, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants