Skip to content

sec (1/9): restrict user-defined scanner IDs to lowercase#25

Open
jesse-merhi wants to merge 3 commits into
pr-a2-gatefrom
sec/01-lowercase-scanner-ids
Open

sec (1/9): restrict user-defined scanner IDs to lowercase#25
jesse-merhi wants to merge 3 commits into
pr-a2-gatefrom
sec/01-lowercase-scanner-ids

Conversation

@jesse-merhi

@jesse-merhi jesse-merhi commented Jul 23, 2026

Copy link
Copy Markdown
Member

What changes

A user-defined scanner ID from profile/config must now be lowercase
(^[a-z0-9][a-z0-9_-]*$) and at most 64 characters. Mixed-case or oversized
IDs are rejected at config-resolution time, before any scanner runs.

Why it matters

Scanner IDs are used as map keys and as path/registry segments. Two IDs that
differ only by case (Foo vs foo) can collide when case-folded, letting one
config entry silently shadow another entry or a built-in scanner such as
clawscan-static. A single canonical spelling removes that ambiguity; the
length cap stops an ID from being an unbounded string.

Before / after (runnable)

up.yml:

version: 1
profiles:
  demo:
    scanners:
      - id: Foo
        command: "scan {{target}}"
Behavior
Before Foo accepted; can resolve alongside foo — collision possible
After run aborts before scanning:
$ clawscan ./skill --config up.yml --profile demo --sandbox off --json
User-defined scanner Foo in profile demo has invalid id; use lowercase letters,
digits, underscores, and hyphens, starting with a letter or digit

Verify

go test ./internal/profiles/ -run 'UserDefinedScannerID' -count=1

Scanner entries in a profile may now be objects declaring id, command,
env (required variable names), and targets. Custom scanners register
into a run-local registry and execute through the standard sandboxed
command path with {{target}} passed positionally to prevent shell
injection. Raw stdout is preserved as artifact evidence; env presence
is recorded as present/missing only.
Object-form scanner entries accept a nested gate with blockOnExitCode /
warnOnExitCode (int, int list, or "nonzero"). The runner captures
user-defined scanner exit codes, evaluates rules after all scanners
complete, and records gate: pass|warn|block plus fired gateRules in the
artifact. Rules referencing unrequested scanners fail before scanning.
Abnormal termination (signal/timeout) never fires exit-code rules.
Copilot AI review requested due to automatic review settings July 23, 2026 12:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Scanner evidence is written to a file named after the scanner ID, and that
name is lowercased. Allowing uppercase IDs let two case-distinct IDs (Foo and
foo) pass validation yet collide on the same evidence file, silently
overwriting each other. Restrict IDs to lowercase and cap length at 64
characters, since IDs are used as file names.
@clawsweeper

clawsweeper Bot commented Jul 24, 2026

Copy link
Copy Markdown

ClawSweeper status: review started.

I am starting a fresh review of this pull request: sec (1/9): restrict user-defined scanner IDs to lowercase This is item 1/1 in the current shard. Shard 0/1.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

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