Skip to content

Single-line quoted free-text args still inflate stored approval patterns #1406

@Aaronontheweb

Description

@Aaronontheweb

Context

Follow-up to #1402, which made multi-line quoted arguments a termination condition for shell approval pattern extraction. That fix keys on the symptom (an embedded line break) rather than the underlying category (quoted free-text content is call-specific), so the single-line variant of the same bug remains.

Problem

A single-line quoted message body flows verbatim into the stored pattern — neither existing termination rule fires:

freshdesk ticket reply --message "Single line body"

Current stored pattern:

freshdesk ticket reply --message Single line body

Every unique body becomes a new pattern — the same bloat class as #1402, minus the newline. Approve-once retry keys are overly specific, and the prompt's pattern line carries call-specific content.

Note: the digit rule masks this for many real invocations (freshdesk ticket reply 605 --message "..." terminates at 605), so the bug only manifests when no digit-bearing token precedes the quoted arg.

Possible approach

ShellSyntaxTree.Arg.Raw preserves outer quotes (the SummarizeMultilineArg helper added in #1402 already sniffs them), so quoted args are structurally detectable without package changes. Two candidate predicates, from narrower to broader:

  1. Whitespace-containing arg — an unquoted arg cannot contain whitespace, so Raw containing a space proves it was quoted free text. Catches "Single line body" but not "fix".
  2. Any quote-leading arg — catches single-word quoted values too (git commit -m "fix"), but quoted and unquoted variants of the same command would then normalize differently (git commit -m fix keeps the operand, git commit -m "fix" drops it).

Why this needs design discussion (deferred from #1402)

This is a behavior change with grant-semantics implications, not a pure bug fix:

  • git commit -m "fix the bug" would normalize to git commit -m — pattern-store consumers and any tests pinning current normalization need review.
  • Quoted globs and patterns are arguably invocation intent, not free text: find . -name "*.cs", grep "foo bar" file. Dropping them may be fine (they are call-specific) but should be a deliberate choice.
  • The spec's "Shell command pattern matching" requirement (openspec/specs/tool-approval-gates/spec.md) currently defines call-specific classification as "one morphological rule" (digit-bearing); adding a quoted-content rule should be reconciled with that framing rather than bolted on.

Affected code

  • src/Netclaw.Security/IToolApprovalMatcher.csReconstructClauseText(), IsCallSpecificValueToken()
  • openspec/specs/tool-approval-gates/spec.md — "Shell command pattern matching" requirement

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions