Skip to content

Shell approval includes bare file operands in persisted verb patterns #1755

Description

@Aaronontheweb

Summary

The shell approval matcher treats a bare filename as part of the verb.
The defect affects Netclaw 0.25.2 and the current dev branch.

Reproduction

Assume the command current directory is /home/alice/repo.
Run this command through shell_execute:

git diff install-skills.sh

Select Always here or Always anywhere.

Actual result

The daemon extracts this candidate:

verb: git diff install-skills.sh
directory: null

Always here saves this record:

{ "verb": "git diff install-skills.sh", "directory": "/home/alice/repo" }

Always anywhere saves this record:

{ "verb": "git diff install-skills.sh" }

The omitted directory means null.
It represents an approval for all directories.

Expected result

The daemon must extract this candidate:

verb: git diff
directory: /home/alice/repo

The directory is the parent of the relative file operand.

Always here must save this record:

{ "verb": "git diff", "directory": "/home/alice/repo" }

Always anywhere must save this record:

{ "verb": "git diff" }

The v2 store does not use the legacy git diff:* text form.
The typed record carries the wildcard through a null directory.

A git diff grant must match another file operand within the selected directory scope.

Root cause

ShellSyntaxTree performs two relevant passes.

  1. The greedy verb pass accepts lowercase tokens with letters, digits, hyphens, dots, and underscores.
  2. The argument pass classifies remaining tokens as paths and resolves them.

The first pass consumes install-skills.sh as a verb token.
The second pass never receives that token.

The package path resolver does recognize .sh as a file suffix.
The classification works when syntax stops the verb pass first.

git diff install-skills.sh
  verb: git diff install-skills.sh
  args: none

git diff -- install-skills.sh
  verb: git diff
  arg: install-skills.sh, path=true, resolved=/home/alice/repo/install-skills.sh

cat install-skills.sh
  verb: cat
  arg: install-skills.sh, path=true, resolved=/home/alice/repo/install-skills.sh

Netclaw then trusts Clause.Verb.Tokens as its approval input.
Netclaw removes trailing digit-bearing values, but it does not remove a trailing file-shaped token.

Ownership

The correction belongs in Netclaw.

ShellSyntaxTree documents the greedy verb as a best-effort hint.
Upstream issue Aaronontheweb/ShellSyntaxTree#27 assigns security-grade verb depth to the consumer.
The package also preserves narrow output when syntax cannot distinguish a subcommand from an operand.

Netclaw already owns approval-specific post-processing through TrimTrailingValueTokens.
That layer must also separate a trailing file-shaped token from the approval verb.
It must resolve the file parent against WorkingDirectory for the candidate directory.

An upstream API could expose token classifications before the greedy verb decision.
Such an API could reduce duplicate heuristics, but it is not required for this correction.

Client impact

All interactive clients send only the selected option key.
Therefore, the TUI, Slack, and Discord use the same daemon candidate and persistence path.
This defect is not specific to the TUI.

Verification

Add the case to the shell approval disposition matrix.
Add matcher tests for candidate extraction and stored-grant reuse.
The tests must cover a bare filename with a lowercase name and a file extension.

Risk

This defect creates narrow and ineffective approvals.
It does not create a broader grant than the user selected.

Related: #1331, #1406, and Aaronontheweb/ShellSyntaxTree#27.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity-related changesshellIssues related to the shell tool, since it has the largest security perimeter.testsAll issues related to testing, quality assurance, and smoke testing.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions