Skip to content

feat(security): add Stage-2 LLM semantic scan for third-party skills#4696

Merged
bug-ops merged 3 commits into
mainfrom
skill-sch-scan
May 30, 2026
Merged

feat(security): add Stage-2 LLM semantic scan for third-party skills#4696
bug-ops merged 3 commits into
mainfrom
skill-sch-scan

Conversation

@bug-ops

@bug-ops bug-ops commented May 29, 2026

Copy link
Copy Markdown
Owner

Summary

Implements defense against Semantic Compliance Hijacking (SCH) attacks (arXiv:2605.14460), where malicious third-party skills encode harmful behavior through natural language instructions in SKILL.md without any explicit code payload, bypassing static security scans.

  • zeph-skills: new SkillSemanticScanner (semantic_scanner.rs) — LLM-based compliance check using chat_typed_erased with a configurable fast provider; 8 KiB content cap with head+tail sampling; XML delimiter-escape neutralization before prompt interpolation; ScanVerdict::{Allow, Warn, Block} with unknown-token fallback to Block
  • zeph-plugins: scan_targets() method extracts SKILL.md candidates from archive before installation, keeping the crate LLM-free; includes canonicalize/starts_with path-traversal guard
  • zeph-core: semantic_scan_plugin_add wires the scanner into handle_plugins; fail-closed on Block; returns config error when semantic_scan = true but semantic_scan_provider is empty
  • zeph-config: doc comments corrected for semantic_scan, semantic_scan_provider, and SemanticViolation

Opt-in: [skill] semantic_scan = true + semantic_scan_provider = "<provider-name>" in config.

Test plan

  • cargo nextest run --config-file .github/nextest.toml --workspace --lib --bins — 10341 tests pass (10339 existing + 2 new security tests)
  • cargo clippy --workspace -- -D warnings — clean
  • cargo +nightly fmt --check — clean
  • RUSTFLAGS="-D warnings" cargo check --workspace --all-targets --features desktop,ide,server,chat,pdf,scheduler — clean
  • LLM serialization gate: live API test required before merge (scanner uses chat_typed_erased); use local Ollama provider (OpenAI 429 gate currently blocked)
  • Verify semantic_scan = true + valid provider → scan runs on zeph plugins add <url>
  • Verify semantic_scan = true + empty provider → config error returned

Closes #3947

@bug-ops bug-ops added skills zeph-skills crate security Security-related issue labels May 29, 2026
@github-actions github-actions Bot added enhancement New feature or request documentation Improvements or additions to documentation rust Rust code changes core zeph-core crate size/XL Extra large PR (500+ lines) and removed enhancement New feature or request labels May 29, 2026
bug-ops added 2 commits May 30, 2026 01:55
Implements defense against Semantic Compliance Hijacking (SCH) attacks
(arXiv:2605.14460) where malicious third-party skills encode harmful
instructions in SKILL.md without explicit code payloads.

- zeph-skills: new SkillSemanticScanner using chat_typed_erased with a
  configurable fast provider; 8 KiB content cap with head+tail sampling;
  XML delimiter-escape neutralization (replaces </skill_content> before
  interpolation); ScanVerdict::{Allow, Warn, Block} with unknown-token
  fallback to Block
- zeph-plugins: scan_targets() extracts SKILL.md candidates from archive
  before installation, keeping the crate LLM-free; includes canonicalize
  path-traversal guard matching add()
- zeph-core: semantic_scan_plugin_add wires the scanner into handle_plugins;
  fail-closed on Block verdict; returns config error when semantic_scan is
  enabled but semantic_scan_provider is empty
- zeph-config: corrected doc comments for semantic_scan and
  semantic_scan_provider fields; SemanticViolation doc scoped to Stage-1 only

Opt-in via [skill] semantic_scan = true and semantic_scan_provider in config.
Closes #3947
@bug-ops bug-ops enabled auto-merge (squash) May 29, 2026 23:55
…d read size

skill_name and declared_purpose from untrusted SKILL.md frontmatter were
interpolated raw outside <skill_content> delimiters, allowing delimiter-escape
injection via newlines or </skill_content> tokens in remote skill metadata.

- Strip \r\n and neutralize </skill_content> in skill_name and declared_purpose
  before prompt interpolation in build_user_prompt
- Add 512 KiB pre-read size cap in scan_targets() to prevent memory DoS
  on oversized SKILL.md files from local plugin add
@bug-ops bug-ops merged commit 527b5e8 into main May 30, 2026
32 checks passed
@bug-ops bug-ops deleted the skill-sch-scan branch May 30, 2026 00:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core zeph-core crate documentation Improvements or additions to documentation enhancement New feature or request rust Rust code changes security Security-related issue size/XL Extra large PR (500+ lines) skills zeph-skills crate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

research(security): skill marketplace supply chain — payload-less Semantic Compliance Hijacking via third-party skills (arXiv:2605.14460)

1 participant