Releases: 0xsl1m/shadowshield
Release list
ShadowShield 0.10.1
ShadowShield 0.10.1
ShadowShield 0.10.1 extends native gateway inspection for Anthropic Messages
and OpenAI Responses while retaining Chat Completions and legacy Completions
coverage. Supported request text, non-streaming response text, structured tool
content, and SSE events now use protocol-aware extraction and native policy
failures.
Enforcing modes fail closed when supported content cannot be inspected within
the bounded extraction, response-body, or SSE-event limits. Shadow mode keeps
its observation contract and preserves original request bodies and stream bytes.
Coverage receipts contain fixed metadata and counters without traffic content.
The release also adds an offline qualification runner with network denial and
source hashing. Stored-response retrieval, WebSocket transport, provider-retained
context, and opaque or media content remain outside the qualified inspection
boundary. This source release does not change any gateway mode, credential,
route, deployment, or running service.
ShadowShield 0.10.0
ShadowShield 0.10.0
Highlights
- Engine-enforced shadow mode — a payload-preserving observation lane enforced by the engine, not the proxy layer. Shadow mode observes and logs without ever mutating or blocking the stream.
- Isolated API-key resolution — upstream keys are resolved with
include_environment=Falseand fail closed when no explicit key is configured; ambient environment keys can no longer leak into upstream requests. - New guarded routes — Anthropic
/v1/messagesand OpenAI/v1/responsesproxies with protocol-native extraction of messages, tool calls, tool results, and streamed events. - Extraction-completeness guards — malformed or over-limit structured payloads fail closed instead of passing unscanned.
Breaking changes
- Fail-open → fail-closed reversal — scanner failures, invalid JSON on guarded routes, oversized bodies/SSE events, and tail-attack patterns now return 403/503 instead of passing traffic through. See CHANGELOG for the full condition matrix.
Limits
- Request body cap: 1 MiB (256 KiB per SSE event).
Also in this release
/healthrequest accounting (proxied-request counter).- Log-hygiene fix: detector-failure paths no longer log payload content.
- Build toolchain:
build1.6.0 (lockfile regenerated), Docker basepython:3.14-slimdigest refresh.
Full changelog and migration notes: see CHANGELOG.md in the repository.
v0.9.0 — shadow mode + usage heartbeat
Added
shadowmode: a fourth preset posture for pure observation — every severity band flags/logs and nothing ever blocks or sanitizes, including via theblock_thresholdfloor (a threshold of 1.0 now disables the floor). This is the true canary/rollout posture:permissivestill blocks critical-severity payloads by design (unchanged), which bit real gateway deployments when benign-but-credential-shaped context scored ≥ 0.85. Use--mode shadowonserve/proxy/dashboard for measure-first rollouts.- Opt-in usage heartbeat: when
SHADOWSHIELD_HEARTBEAT=1andSHADOWSHIELD_HEARTBEAT_URLare both set,servesends one anonymous packet per 24h —{anon_install_id, version, num_services_seen, ts}and nothing else (no hostnames, IPs, keys, or payloads). Default is fully off; state lives in~/.shadowshield/heartbeat.json; fail-open on any error.
Install: pip install -U shadowshield · Full changelog: https://github.com/0xsl1m/shadowshield/blob/main/CHANGELOG.md
v0.8.2 — mcp 2.x support
Added
build_mcp_serversupportsmcp2.x: targetsmcp.server.MCPServer(2.x) with a fallback tomcp.server.fastmcp.FastMCP(1.x); the[mcp]extra is unpinned tomcp>=1.0. Verified against both mcp 1.29.0 and 2.0.0 (stdio smoke + full suite).on_activitycallback onbuild_mcp_server: invoked on every guarded tool call so long-lived stdio launchers can run idle-timeout watchdogs without redefining the tools locally.
Full changelog: https://github.com/0xsl1m/shadowshield/blob/main/CHANGELOG.md
ShadowShield 0.8.1
Patch release
- Proxy fail-open on scanner exceptions (#27) — a detector bug can no longer 500 a wired harness's LLM request; logged and treated as no-verdict
- Shadow logging at proxy scope (#27) — permissive mode now logs
request_flagged/response_flaggedfor every non-terminal finding, so shadow deployments see what enforcing modes would do - New
[mcp]extra —pip install "shadowshield[mcp]"; the MCP guard server integration now has a declared, working dependency (mcp>=1.0,<2; mcp 2.0 moved FastMCP — port to the 2.0 API is tracked for a later release)
pip install -U shadowshieldFull Changelog: https://github.com/0xsl1m/shadowshield/blob/main/CHANGELOG.md
ShadowShield 0.8.0
The classifier-tranche release
The semantic-pretext attack class — the documented ceiling of deterministic injection detection — is now closed.
Headline results (all measured, reproducible)
- InjecAgent (1,054 cases, enhanced): ASR 18.8% → 0.1% (−99.5%) at 76.9% utility via segment-span sanitization — 3× the utility of the redact arm at the same ~0% ASR
- AgentDojo classifier arm: ASR 0% on banking/travel/slack, 1.8% on workspace (baselines 27–62%), no abort-driven utility loss
- LLMail-Inject: 96.75% catch / 0% FPR on 2,000 real attack submissions
- Full matrix: docs/INDUSTRY_BENCHMARKS.md
What's new
TransformerDetector(segment_spans=True)— sentence-level spans redacted, legitimate tool data survives; fail-closed backstop- Chinese (Simplified) signatures — first CJK deterministic-tier coverage, first external contribution (#9, thanks @01luyicheng)
- AgentDojo adapter fix (content-block key, scan cache, block-only abort) with published disclosure of the corrected 2026-08-07/08 numbers
- Offline calibration harness (
scripts/classifier_calib.py) — predicted the live results before spending a cent of API budget
pip install -U shadowshieldFull Changelog: https://github.com/0xsl1m/shadowshield/blob/main/CHANGELOG.md
ShadowShield 0.7.0
ShadowShield 0.7.0 — comprehensive audit remediation plus streaming, calibration, parallel, gateway, and middleware-breadth features from the 2026-08-05 upgrade plan.
Highlights
- Gateway mode (zero code changes).
shadowshield proxy --upstream https://api.openai.computs the shield in front of any OpenAI-compatible endpoint: chat messages scanned pre-flight (blocked requests return an OpenAI-style403and never reach the upstream), completions scanned post-flight, and malicious SSE streams cut mid-flight with a conventionalfinish_reason="content_filter"chunk. Embed in-process instead with the new pure-ASGIShieldASGIMiddleware. - StreamScanner. Scan a completion while it streams — bounded memory, carry-over window so split signatures still match, terminal BLOCK/ESCALATE returned the moment the stream must stop (
shield.stream_scanner()). - Middleware breadth.
ShieldedAnthropicClient(incl.systemprompt and text blocks),shielded_completion/ShieldedLiteLLM, and RAG guardrails:scan_retrieved_chunkswith drop/keep/raise policies plus duck-typed LlamaIndex/Haystack retriever wrappers. - Score calibration. Isotonic calibration (
IsotonicCalibrator,fit_isotonic,fit_from_examples), engine hook,benchmark --calibration PATHraw-vs-calibrated view, and a newshadowshield calibratecommand. - Opt-in parallel detector fan-out (
parallel_detectors: true): identical verdicts/ordering/error accounting; measured ~3x wall-clock speedup with three 20 ms detectors. - Operations. Control-plane package split, config hot-reload (
POST /api/reload), vector-detector attack persistence, and a hardened Helm chart (deploy/helm/shadowshield/) mirroring the compose hardening. - Blind benchmark v4. New 58-example snapshot (indirect tool-result, multilingual, semantic-pretext): 58.6% recall / 6.9% FPR balanced; 148-row aggregate 36.5% / 14.9% — gaps remain public by design.
Security fixes
- M-1 (behavior change): unsigned policy bundles now fail closed.
apply_bundlerejects unsigned bundles when no verifier is configured unless the caller explicitly passesallow_unsigned=True. Deployments relying on silent unsigned bundles must opt in. - Telemetry reporter requires an HTTPS endpoint unless
allow_insecure_endpoint=True(or a custom transport); queue-overflow and delivery-failure warnings added. - Sanitizer merges overlapping/adjacent redaction spans (categories reported as
a|b). - Fixed a request-body replay hang in the shared HTTP middleware that stalled
StreamingResponsedisconnect listeners with fabricated empty bodies.
Verification
433 tests passing (2 opt-in model tests skipped), 88% coverage, ruff + strict mypy clean (67 source files). Container image digest and SBOM are attached to this release by the container-release workflow.
ShadowShield 0.6.3
ShadowShield 0.6.3 is a post-launch production-hardening release.
Highlights:
- Records blocked session turns exactly once and surfaces bounded detector failures through scan metadata, audit events, control-plane metrics, and Prometheus. Strict mode now fails closed on detector execution errors.
- Hardens HTTP intake with authentication before body admission, a 1 MiB aggregate body limit, a fragmentation ceiling, one total read deadline, and authenticated protected OPTIONS requests while preserving valid CORS preflights.
- Adds trustworthy benchmark warmup/readiness/error reporting, confusion matrices, per-category recall/FPR/balanced accuracy, and 95% Wilson confidence intervals.
- Reduces common scan-path overhead while preserving detector behavior; focused measurements showed roughly 5–12% improvements on affected paths.
- Pins and hashes build/runtime dependencies, verifies byte-identical double builds, pins workflow actions, and makes container tags, release evidence, provenance, and SBOM handling immutable and verifiable.
Validation:
- 320 tests passed across Python 3.10–3.14; real-model integration passed.
- Ruff, strict mypy, dependency audit, CodeQL, reproducible package build, and hardened container security smoke passed for the release commit.
- Candidate image had zero fixable HIGH/CRITICAL findings with the current vulnerability database.
Upgrade notes:
- Configure four independent high-entropy API, admin, policy-signing, and policy-state keys before exposing the control plane.
- Balanced mode reports detector failures; strict mode blocks on them.
- Existing 0.6.0 durable policy-state volumes still require the documented offline migration before startup.
See the changelog and production-readiness roadmap for details.
Container evidence
- Immutable image:
ghcr.io/0xsl1m/shadowshield@sha256:ddc369cd94ee8b982fd8976f2a3641bb75546a4da805ab556e97c3a80df69d9f - Both
0.6.3andsha-cd852fe6f2b8a3e766fc21ae9f6360755ae50e97resolve to that digest. - SLSA provenance is bound to release source
cd852fe6f2b8a3e766fc21ae9f6360755ae50e97. - The signed CycloneDX SBOM was recovered without rebuilding or retagging from protected
maincommit9b3d7ac0cb095a9b7f179eecf2693cdf9b23d17e; see the successful evidence run. container-digest.txtandshadowshield-sbom.cdx.jsonare attached below.
ShadowShield v0.6.2
Production hardening for failure recovery, durable policy state, supply-chain provenance, repository governance, and honest blind evaluation.
Highlights
- Hardened durable state against symlink, non-regular-file, and swap races with bounded I/O and atomic replacement.
- Made Transformer and vector initialization failures single-flight, traceback-bounded, and safely retryable.
- Added signed SLSA provenance and a signed CycloneDX SBOM for the exact GHCR image, with registry-backed verification before release completion.
- Added the v3 blind generalization snapshot and aggregate reporting; a candidate that missed the frozen acceptance gates was discarded.
- Enforced a hash-only CSP, stronger browser security headers, a permanent www-to-apex redirect, and production CI/security gates.
Verified on the exact release source
- 295 tests passed with 2 optional real-model skips.
- Python 3.10 through 3.14 CI, real-model ML integration, package build, workflow lint, CodeQL, and container security smoke all passed.
- Linux/Python 3.10, strict mypy, Ruff, Actionlint, package isolation, and Trivy with zero fixable high/critical findings passed.
- Exact-SHA GitHub Pages and Vercel production deployments are live.
See CHANGELOG.md for the complete release record.
ShadowShield 0.6.1
What's Changed
Full Changelog: v0.6.0...v0.6.1