SHIELD Detection System
Added: June 2026 (
feat(shield)commitsbe1bfc61→28b1610d) Package:assistant/shield/
SHIELD is a prompt-injection / suspicious-content detection layer that runs as a hard gate before the assistant ReAct loop. It scans user input and tool output for known malicious patterns and hard-blocks protected roles (infrastructure, sysadmin) when critical/suspicious matches fire.
🎯 Purpose
- Protect infrastructure agents (Sasha, Sysadmin, Architect, Sysafe) from prompt-injection embedded in tool output, web content, or async messages.
- Surface decisions to Mission Control via dedicated SHIELD tabs so admins can review what was blocked.
- Sync threat intel from a remote PromptIntel feed so detection rules stay current.
🏗️ Architecture
Core (shield.go)
| Symbol | Purpose |
|---|---|
Init() |
Initialize detector, load seeds + syncer, mark ready |
IsReady() / WasInitialized() |
Liveness checks used by QueryAssistantWithOptions |
Check(content, role) |
Run content against rules; returns Decision (Allow / Suspicious / Critical) |
GetRecentDecisions(limit) |
Recent decisions for MC SHIELD tabs |
GetLastSync*() |
Latest sync timestamps/errors for status display |
GenerateSHIELDMD() / generateAndWrite() |
Produce data/shield/SHIELD.md from current rules + decisions (runs on Init) |
Feed Syncer (shield_sync.go)
Added in Phase 2 (88572533) and refined through 28b1610d. Pulls indicators/prompts from the PromptIntel API.
| Symbol | Purpose |
|---|---|
StartFeedSync(ctx) |
Background goroutine; periodic pull |
SyncNow() |
Manual / triggered resync (used by MC admin endpoints) |
GetLastSyncError() |
Returns last sync error (nil on success) |
Initialisation: Wired via sync.Once inside QueryAssistantWithOptions after shield.Init() — lazy init prevents the bot from blocking on remote API at startup (commit 29b4ebae).
Response-shape handling (commit 03f9b54a, ebb9a312, 28b1610d): PromptIntel returns data as either an array or an object depending on endpoint/version. The decoder uses json.RawMessage for Data and inspects the first non-whitespace byte to dispatch:
[→ flat array of items (current API behaviour){→ legacy object withindicators/prompts/total/page- root-level
indicators/promptsfallbacks run if both above are empty
🔐 Hard Block Behaviour
Commit be1bfc61 wired the actual early return + hard block. For protected roles, a Critical or Suspicious decision:
- Skips the LLM call entirely (no prompt reaches the model).
- Logs the decision with full content + matched rules.
- Returns a fixed safety response to the channel (Discord/WhatsApp/voice).
- Records the decision for MC review.
Non-protected roles still get the visibility (decisions logged) but the assistant continues — this keeps non-sensitive agents from being DOS'd by false positives.
📊 Mission Control Integration
Added in 318aa581. Dedicated SHIELD tab(s) in the MC dashboard expose:
- Recent decisions (Allow / Suspicious / Critical colour coding)
- Sync status (last sync time, last error, sync-now button)
- Current rule inventory (seeds + synced indicators)
- SHIELD.md rendered view (
data/shield/SHIELD.md— generated on each Init)
Frontend wired via assistant/static/mission_control.js switchTab hook + mission_control_console.js patterns.
📁 Key Files
| File | Purpose |
|---|---|
assistant/shield/shield.go |
Core detector, decisions, generator |
assistant/shield/shield_sync.go |
PromptIntel feed syncer |
assistant/assistant.go |
QueryAssistantWithOptions integration — early-return gate |
assistant/templates/missioncontrol/* |
SHIELD tab templates |
assistant/static/mission_control.js |
Tab switching + sync-now wiring |
data/shield/SHIELD.md |
Generated human-readable rule + decision summary |
data/shield/seeds/*.json |
Seeded detection rules (e.g. broad_simple_examples.json) |
assistant/SHIELD_DEV_LOG.md |
Development log (internal reference) |
🛡️ Seeding
Seeds (data/shield/seeds/broad_simple_examples.json) provide baseline detection rules to avoid overblocking normal technical content while still catching injection patterns. Commit 64678479 tuned broad-rule seeds to reduce false positives in legitimate tool output.
📜 Git History (relevant commits)
| Hash | Summary |
|---|---|
be1bfc61 |
Wire early return + hard block for protected roles on critical/suspicious matches |
88572533 |
Phase 2 feed syncer (shield_sync.go) implemented via subagent |
d93b0934 |
Integrate syncer startup (StartFeedSync + SyncNow) via sync.Once |
91365cba |
SHIELD.md generator (GenerateSHIELDMD + generateAndWrite on Init) + base file |
318aa581 |
MC SHIELD tab(s) integration + prerequisite enhancements |
6ec08e26 / f66d0d57 |
Resolve duplicate declarations for GetRecentDecisions / GetLast* getters |
29b4ebae |
Hardcode PromptIntel API key, lazy syncer init, improved MC status |
ebb9a312 / 03f9b54a / 28b1610d |
Fix PromptIntel response parsing (array vs object shapes) |
🔗 Related
- Security & RBAC — Role-level access controls SHIELD consults
- Mission Control API — SHIELD + other endpoints
- System Logging — Where blocked decisions land