Skip to content

Harden skill-validator against malicious skill packages#78

Open
aminmesbahi wants to merge 1 commit into
agent-ecosystem:mainfrom
aminmesbahi:main
Open

Harden skill-validator against malicious skill packages#78
aminmesbahi wants to merge 1 commit into
agent-ecosystem:mainfrom
aminmesbahi:main

Conversation

@aminmesbahi
Copy link
Copy Markdown

Address the threat model in SECURITY.md by closing several paths an untrusted
skill package could use to exfiltrate local data, reach internal hosts, exhaust
resources, or corrupt CI output.

  • links/safenet: expand SSRF block list to cover 0.0.0.0/8, 100.64/10, 198.18/15, 224/4, 240/4, 192.0.0/24, TEST-NETs, IPv6 unspecified/multicast/ doc ranges (previously only loopback + RFC1918 + link-local were blocked, so http://0.0.0.0/ and CGNAT addresses bypassed the dialer check)
  • links/safenet: reject non-http(s) redirect targets explicitly in CheckRedirect
  • util: add SafeReadFile / IsRegularFile that os.Lstat before reading; wire through skill, skillcheck, structure/{orphans,tokens,markdown} so a skill containing references/innocent.md -> /etc/passwd no longer reads or ships the target to the LLM judge
  • judge: wrap untrusted skill content in <<<UNTRUSTED_CONTENT_START/END>>>
    delimiters with an isolation reminder, scrub injected delimiters, clamp scores to [0,5], strip control chars from string fields and cap their length
  • judge/client: append -- before positional user content in the claude CLI invocation so future callers cannot accidentally pass flag-like content
  • judge/client: refuse non-https LLM base URLs by default (opt out via AllowInsecureBaseURL) so misconfigured --base-url cannot ship bearer tokens in plaintext
  • judge/cache: tighten cache dir/file modes to 0700/0600 since cached output may include reflected file content
  • links/check: cap link checking at 16 concurrent requests and 500 links per skill to bound goroutine/FD use
  • structure/tokens: cap per-file read at 8 MiB before tokenizing to bound memory use on pathological inputs
  • report/annotations: encode %, CR, LF (and : , in property values) so a skill name/filename containing a newline cannot inject extra GitHub Actions workflow commands

Tests added for each fix; full suite passes under -race.

What this PR does

How to test

Checklist

  • Tests pass locally (go test -race ./... -count=1)
  • Lint passes locally (golangci-lint run)
  • New functionality includes tests
  • Breaking changes are noted above (if any)

  Address the threat model in SECURITY.md by closing several paths an untrusted
  skill package could use to exfiltrate local data, reach internal hosts, exhaust
  resources, or corrupt CI output.

  - links/safenet: expand SSRF block list to cover 0.0.0.0/8, 100.64/10,
    198.18/15, 224/4, 240/4, 192.0.0/24, TEST-NETs, IPv6 unspecified/multicast/
    doc ranges (previously only loopback + RFC1918 + link-local were blocked, so
    http://0.0.0.0/ and CGNAT addresses bypassed the dialer check)
  - links/safenet: reject non-http(s) redirect targets explicitly in CheckRedirect
  - util: add SafeReadFile / IsRegularFile that os.Lstat before reading; wire
    through skill, skillcheck, structure/{orphans,tokens,markdown} so a skill
    containing references/innocent.md -> /etc/passwd no longer reads or ships
    the target to the LLM judge
  - judge: wrap untrusted skill content in <<<UNTRUSTED_CONTENT_START/END>>>
    delimiters with an isolation reminder, scrub injected delimiters, clamp
    scores to [0,5], strip control chars from string fields and cap their length
  - judge/client: append `--` before positional user content in the claude CLI
    invocation so future callers cannot accidentally pass flag-like content
  - judge/client: refuse non-https LLM base URLs by default (opt out via
    AllowInsecureBaseURL) so misconfigured --base-url cannot ship bearer tokens
    in plaintext
  - judge/cache: tighten cache dir/file modes to 0700/0600 since cached output
    may include reflected file content
  - links/check: cap link checking at 16 concurrent requests and 500 links per
    skill to bound goroutine/FD use
  - structure/tokens: cap per-file read at 8 MiB before tokenizing to bound
    memory use on pathological inputs
  - report/annotations: encode %, CR, LF (and : , in property values) so a
    skill name/filename containing a newline cannot inject extra GitHub Actions
    workflow commands

  Tests added for each fix; full suite passes under -race.
@aminmesbahi
Copy link
Copy Markdown
Author

Hi @masukomi,
are you Ok with these fixes?

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.

1 participant