Last Updated: 2026-10-04
Master index of every document in this repository. The docs/ files are the
security contract and source of truth for all algorithms; the three core docs
describe and visualize the implementation that satisfies that contract.
| # | Doc | Purpose |
|---|---|---|
| 1 | README.md |
Project overview, install, the pin/check CI demo (full walkthrough archived to docs/PIN_CHECK_DEMO.md to hold the 500-line core-doc limit), CLI reference (incl. v0.3 lock rotate + redacted offline diff viewer), GitHub Action usage section (Issue #18), pre-commit hook section (Issue #22) |
| 2 | SYSTEM_CONTEXT_DIAGRAM.md |
System context + pin/check sequence (mermaid); trust boundary; conclave as dev-time reviewer only; composite GitHub Action + pre-commit hook as consumer delivery vehicles |
| 3 | DOCUMENTATION_INDEX.md |
This file |
Schema level 4 adds annotation/output commitments (DSE-1539). The upgrade plan and Warden checkpoint proposal separates implemented surface integrity from proposed protocol-neutral enforcement.
The format is a standard, not a tool: a language-neutral corpus defines conformance and two implementations (Python reference, zero-dependency TypeScript) prove it in CI.
| Artifact | Purpose |
|---|---|
vectors/README.md |
Consumer contract: manifest schema, the four vector kinds, the surface document shape, how a third implementation runs the corpus |
vectors/manifest.json + vectors/cases/ |
111 generated vectors — canonical (RFC 8785), digest, drift (every WRD-DRIFT-* class), malformed |
vectors/tools/generate.py |
Regenerates the corpus from the Python reference; a corpus diff = a hashed-derivation change = a schema_version bump (SPEC §14.2) |
tests/test_spec_vectors.py |
Python harness over the manifest (honours MCP_LOCK_VECTORS_DIR) |
packages/lock-ts/ |
@mcp-warden/lock — verify-only TypeScript: hand-written JCS, SHA-256, capability + skeleton derivation, drift classifier; npm test runs the same corpus |
.github/workflows/integrity-gate.yml conformance job |
Runs both harnesses; mutation proof flips one hex char and requires BOTH to fail |
Two fail-closed gates extending warden past MCP-surface integrity into the adjacent
CI controls agent deployments lack: did the deploy meet its declared safety bar, and
is the MCP auth posture sound. Both reuse the check exit-code contract (0 clean /
1 finding / 2 fail-closed) and the shared SARIF + JSONL emitters.
| Artifact | Purpose |
|---|---|
docs/AGENT_GATES.md |
Security contract for both gates — policy/evidence schemas, full rule tables, scope honesty, and the two load-bearing design decisions (evidence-adjudication, static-only) |
src/mcp_warden/deploy_gate.py |
WRD-GATE-* engine: eval thresholds, guardrail presence, budget, approval receipt |
src/mcp_warden/cli_deploy_gate.py |
deploy-gate command body (register idiom) |
src/mcp_warden/auth_audit.py |
WRD-AUTH-* static config audit; reuses checks_secret.scan_field for vendor patterns (vendor hits are never downgraded); template fill-me-ins are WRD-AUTH-PLACEHOLDER-SECRET (low), matched on whole tokens |
src/mcp_warden/cli_auth.py |
auth audit sub-app command body |
tests/test_deploy_gate.py |
Engine per-control pass/fail + CLI exit codes + fail-closed on malformed evidence |
tests/test_auth_audit.py |
Every rule, the deliberate non-flags (loopback, ${VAR} refs, stdio), redaction, CLI/JSON/SARIF |
tests/test_agent_gates_examples.py |
Pins the shipped examples to the per-server verdicts their README claims, so a rule change cannot silently make the docs wrong; also asserts the planted fake credentials never reach a finding field |
examples/agent-gates/ |
Runnable demos — a 6-server config (4 flagged / 2 deliberately clean, incl. the Bearer ${VAR} embedded-reference shape from #94) and pass/fail deploy evidence, with expected verdicts documented and verified |
The adoption funnel: one command, no arguments, static. Discovers every MCP client config
on the machine and composes the existing WRD-AUTH-* + WRD-SUP-* engines plus a
lock-coverage check per server, then prints the exact pin command for anything uncovered.
| Artifact | Purpose |
|---|---|
docs/DOCTOR.md |
Contract — the per-platform discovery table, the symlink-escape rule, what runs per server, lock-coverage matching, the static-by-default guarantee, the --pin opt-in contract, exit codes |
src/mcp_warden/doctor_paths.py |
Pure path enumeration for (platform, home, cwd, env): the per-platform well-known set, the .git/home-bounded project walk-up, the symlink-component guard |
src/mcp_warden/doctor_discovery.py |
Fail-closed loaders — union of mcpServers + VS Code servers (conflicts → WRD-DOCTOR-AMBIGUOUS-SERVER), ~/.claude.json per-project, Codex TOML, string-aware JSONC; per-candidate hard-error / skip accounting |
src/mcp_warden/doctor_jsonc.py |
strip_jsonc — one linear, string-aware pass over VS Code JSONC (comments + trailing commas); an unterminated string or /* leaves the remainder untouched so it fails closed (DSE-1529) |
src/mcp_warden/doctor_funnel.py |
safe_text (C0/C1/NEL/zero-width/bidi neutralisation), lock naming, the masking rules and byte-preserving URL redaction behind the printed pin command |
src/mcp_warden/doctor.py |
Bounded lock discovery, pin.approved-aware coverage, per-server composition of audit_server + check_launch_command + WRD-DOCTOR-*, resolved-path de-duplication of --config |
src/mcp_warden/cli_doctor.py |
doctor command body (register idiom): report rendering, JSONL/SARIF, the --pin/--yes TTY contract |
tests/test_doctor.py |
Discovery purity per platform, every loader shape, symlink file + directory escape, bounded lock search, coverage matching, composition, funnel redaction |
tests/test_doctor_security.py |
One test per security-review finding (two passes): terminal / bidi injection, --pin provenance, masking bypasses, decoy servers map, string-aware JSONC, unauthenticated coverage, discovery robustness, walk-up boundary, --config de-duplication |
tests/test_doctor_cli.py |
Exit codes, no-config path, redaction across stdout/JSONL/SARIF, the no-spawn/no-socket/no-DNS assertion, --pin refusal + real end-to-end pin, Windows shape via injected APPDATA |
Multi-attester surface consensus that closes the TOFU hole a single-party lock cannot see. Compares a launch-independent surface digest to Sigstore-signed attestations in a git corpus; every unverifiable condition is exit 2. Phase 2 (the public corpus repo + nightly attester) is pending.
| Artifact | Purpose |
|---|---|
docs/COMMUNITY_CORPUS.md |
Contract — the trust model (what the v2 signature binds: identity, digest and coordinate; the consumer pin is the trust root, the corpus list is discovery), the surface digest, corpus layout + size caps, attesters.json, coordinate grammar, verdict/exit table incl. UNPINNED-TRUST/INSUFFICIENT/SCHEMA-MISMATCH, git transport hardening, phase-2 sandbox contract |
src/mcp_warden/corpus.py |
Corpus fetch — local path, or https:///ssh:///git@ URL @ exact sha cloned with protocol.allow=never, hooks/symlinks/submodules off, -- separator, scrubbed env — and run orchestration |
src/mcp_warden/corpus_trust.py |
Consumer trust pin (--attester/--attesters-file, required), corpus discovery list, intersection rules (unpinned ignored, divergent/duplicate ids exit 2) |
src/mcp_warden/corpus_verify.py |
Per-entry verification — path confinement, size caps, schema-version check, v2 statement bound to the directory coordinate, self-consistency — and the WRD-CONSENSUS-* verdict incl. --min-attesters |
src/mcp_warden/corpus_coordinate.py |
npm:/pypi: coordinate grammar; inference from npx/uvx/pipx run argv; floating specs resolve to nothing (fail closed) |
src/mcp_warden/cli_corpus.py |
check glue: stray-option validation, trust-pin + coordinate preflight before spawn, consensus adjudication after drift (any unexpected error → exit 2, class name only) |
src/mcp_warden/lockfile.py |
surface_digest() (§6.1 payload minus server) and lock_is_self_consistent() |
tests/test_corpus.py / tests/test_corpus_cli.py |
Coordinate table incl. whitespace/control rejection, v1-bytes-unchanged + v2 statements, trust pin (required, duplicates, divergence, hostile corpus trust root), relocated sidecar, every verdict incl. INSUFFICIENT, every fail-closed path (unknown attester, missing/corrupt/wrong sidecar, tampered entries, size caps, symlink escape, schema mismatch, directory-as-lock, deep JSON, ext::/option/file:// sources never reach git, hardened argv, unreachable/wrong-ref corpus), SARIF/JSONL, stray options, default check unchanged |
tests/fixtures/corpus/ |
Local corpus with fake sidecars accepted only by the test boundary; regenerated by tests/fixtures/gen_corpus.py |
The composite reusable action is the primary delivery vehicle for the check gate.
Consumers pin DataScience-EngineeringExperts/mcp-warden@<tag> and get a zero-copy-paste integrity
gate with hash-locked supply-chain, SARIF upload, and cross-OS support.
| Artifact | Purpose |
|---|---|
action.yml |
Composite action definition — inputs, outputs, injection guard, hash-locked install, exit-code contract |
action/build-requirements.lock |
Hash-locked build backend (hatchling + deps) — regenerate with pip-compile --generate-hashes on each release |
action/requirements.lock |
Hash-locked mcp-warden runtime closure — regenerate with pip-compile --generate-hashes on each release |
.github/workflows/action-test.yml |
OS-matrix self-test (ubuntu/macos/windows) + dedicated SARIF-upload job |
tests/test_action_yml.py |
Structural pytest: composite kind, SHA-pinned uses:, version comments, exit-code propagation step, shell: bash on every run step |
The local pre-CI gate: runs the same check verdict path on every commit so drift
is caught before it reaches CI. A local hook and CI can never disagree on a drift
verdict because both call the shared check_core.run_check sequence.
| Artifact | Purpose |
|---|---|
.pre-commit-hooks.yaml |
Hook definition (id: mcp-warden-check, pass_filenames: false, always_run, require_serial) consumers reference from their .pre-commit-config.yaml |
src/mcp_warden/precommit.py |
Wrapper entry point (mcp-warden-precommit): -- server-argv contract, cwd-normalization to git root, non-strict-vs---strict server-unavailability handling; check-only (never writes the lock) |
tests/test_precommit.py |
arg parsing, empty-cmd guidance, clean/drift exit codes, server-unavailable (non-strict 0 / strict 2), cwd normalization, lock write-protection (runtime spy + static import check), .pre-commit-hooks.yaml invariants |
Copy-paste integration examples, kept green by the Examples CI workflow (YAML-lints
the example workflows + re-checks the committed pinned-server locks on every run).
| Artifact | Purpose |
|---|---|
examples/README.md |
Gallery index; links each example back to the core docs |
examples/github-actions/ |
Four GitHub Action workflows: (a) pin-on-merge + check-on-PR, (b) matrix over multiple servers, (c) SARIF upload, (d) upload-sarif: false for private repos |
examples/gitlab-ci/.gitlab-ci.yml |
Equivalent check gate on GitLab CI |
examples/pre-commit/.pre-commit-config.yaml |
Minimal + pre-push hook variants (mirror the README hook) |
examples/pinned-servers/ |
Three real, openly-available MCP servers (server-everything, server-memory, server-sequential-thinking) each pinned to a committed warden.lock via a pinned launcher ref, with a per-server README (exact pin argv + sample check) |
.github/workflows/examples.yml |
CI: yamllint the example workflows + re-run check against every committed example lock |
Education-first, task-focused guides (mkdocs-material) where mcp-warden is the
implementation detail. Built with mkdocs build --strict on every PR and deployed
to GitHub Pages on main. The security-contract specs under docs/ remain the
source of truth; these pages explain and link them. Every page carries a
scope-honesty box and makes no compliance/regulatory claim.
| Artifact | Purpose |
|---|---|
mkdocs.yml |
Site config (material theme, nav, no analytics/tracking) |
docs-site/index.md |
Home — mental model + where to start |
docs-site/quickstart.md |
Install → pin → check → Action in under 5 minutes |
docs-site/tool-poisoning.md |
What is MCP tool poisoning; what mcp-warden does / does-not do |
docs-site/rug-pull.md |
What is an MCP rug pull; how the drift gate catches it |
docs-site/pin-in-ci.md |
Pin MCP servers in CI (GitHub Actions + GitLab); links examples/ |
docs-site/checklist.md |
Vendor-neutral MCP security checklist; names the tool per layer |
docs-site/lock-format.md |
The MCP Lock Format; links docs/SPEC.md as source of truth |
docs-site/comparison.md |
Honest mcp-warden vs mcp-scan vs gateways — complementary layers (Issue #48) |
.github/workflows/docs.yml |
CI: mkdocs build --strict PR gate; deploy to Pages on main |
| Doc | Defines |
|---|---|
docs/ARTIFACT_TRUST.md |
Opt-in Ed25519 implementation of DSE-716's external artifact verifier: explicit key/kind roles, independently pinned canonical roots, exact version/kind/key-bound signing frame, unsigned review preparation and offline signature verification. No private signing capability, durable receipts, live guard wiring or whole-kernel claim |
docs/PIN_CHECK_DEMO.md |
Full end-to-end pin/check walkthrough, archived out of README.md on 2026-08-24 to hold the 500-line core-doc limit |
docs/SPEC.md |
MCP Lock Format v1 — the vendor-neutral, self-contained format specification any tool can implement: on-disk warden.lock schema, RFC 8785 (JCS) canonicalization, SHA-256 sha256:<hex> hashing, overall_digest construction, the normative drift class + severity table, the optional per-tool inspection block, and a Conformance section (§12.1: passing vectors/ is conformance) + worked example. WARDEN_LOCK_SCHEMA.md is the mcp-warden implementation of this format |
docs/THREAT_MODEL.md |
(v0.1) Positioning, trust model (TOFU + --approve), assets/actors, the four threat classes (MCP-DRIFT / MCP-CAPSURF / MCP-SECRET / MCP-SUPPLY), explicit out-of-scope limits, deliberate cuts |
docs/THREAT_MODEL_V2.md |
(v0.2) Addendum extending the v0.1 model: T-RESULT vectors, the defends (BLOCK) / monitors (fuzzy) / still-does-NOT-defend (T-BEHAVE) table, runtime trust-model notes, retained + added cuts, shadow-default positioning |
docs/AGENT_TRUST_KERNEL.md |
(DSE-714, design contract) Normative invariants for the future deterministic Agent Trust Kernel: trust boundaries, complete mediation, default deny, non-overridable critical classes, evidence-before-effect, offline operation, residual risks, and bindings for DSE-715 through DSE-717. MCP-Warden 2.0.0 is explicitly not yet ATK-conformant |
docs/CONTENT_ENVELOPE.md |
(DSE-715, implemented foundation) Strict immutable V1 content envelope, domain-separated exact-byte digests, canonical metadata boundary, bounded one-hop lineage, monotonic taint, stable code-only errors, and secret-safe public projection. Evidence only; no authority or whole-ATK conformance claim |
docs/POLICY_ENFORCEMENT.md |
(DSE-716, implemented foundation) Versioned signed policy/runtime/adapter/executable-bundle activation, exact adapter/bundle-bound leases, mechanically derived frozen handler identity, deterministic default-deny PDP, evidence-gated structural PEP, stable reason/recovery matrix, caps, and non-optional fixed-corpus adapter harness. Separate DSE-717 V2 evidence foundation; real protected-platform and live-guard gates remain pending |
docs/DECISION_RECEIPTS.md |
(DSE-717, development foundation) Independently authorized signed receipts, strict strengthening rules and finite noncritical overrides; separate primary/fallback logs, protected-state/latch ports, authenticated recovery, pure historical replay, current eligibility, safe projections and nonoptional reference conformance. Reference providers cannot establish platform rollback resistance; absent from PyPI 2.0.0 |
docs/WARDEN_LOCK_SCHEMA.md |
mcp-warden implementation of docs/SPEC.md (MCP Lock Format v1). warden.lock format, RFC 8785 canonicalization + SHA-256 hashing, field/entry/overall digests, the normative drift definition + severities; §5.1/§6.2 structural schema diff (normalized per-tool schema_skeleton, schema_version 4 — annotations/output added at v4, skeleton added at v2, in-document $ref resolution at v3 (#29), granular WRD-DRIFT-SCHEMA-* taxonomy + severities, v1 fallback); §8.1/§8.2 (v0.3, #19) structured out-of-digest provenance (pinner / attestations / rotation_count, PROVENANCE_VERSION, B4 bound_digest format) + lock rotate digest-invariant semantics + the #16 signing implication; §11 (v0.2) optional per-tool inspection policy (expected_output_charset / may_return_urls / secret_echo_applies, fail-safe defaults, digest impact) |
docs/WARDEN_LOCK_EXAMPLE.md |
Illustrative full warden.lock + a post-lock rotate pin block (archived from WARDEN_LOCK_SCHEMA §9 to keep that core doc under the line cap) |
docs/CHECKS.md |
The deterministic WRD-* static-check catalog (capability/secret/supply/robustness), the shared tokenizer, severity→SARIF mapping, redaction rule, CUT list. Reused by v0.2 WRD-RES-SECRET-ECHO (the WRD-SEC-* patterns + redaction) |
docs/POLICY_MODEL.md |
Policy schema, the four high-risk shapes, constraint vocabulary, fail-closed defaults, SSRF deny ranges, lint + single-sample eval semantics. Enforced at runtime by v0.2 guard on live tools/call requests |
docs/RESULT_INSPECTION.md |
(v0.2) The WRD-RES-* result-inspection catalog: deterministic/fuzzy tier partition, per-rule exact match definitions (ANSI allowlist, secret-echo via WRD-SEC-*, exfil seed denylist, injection seed phrase list), severities, SARIF mapping, redaction, fail-safe per-tool precision. Run identically by guard and inspect |
docs/GUARD_PROXY.md |
(v0.2 base, updated to v0.3 defaults) The guard transparent stdio proxy + inspect offline analyzer contract: frame-handling discipline, single-loop framing (Content-Length + newline), incremental scan, subprocess lifecycle, runtime arg-policy + tools/list_changed gate, the v0.3 default-block posture + --no-block-* opt-outs + --audit-only, reserved codes -32001/-32002, and the exact on-the-wire "block" behavior |
docs/GUARD_PROXY_V3.md |
(v0.3) The proxy-hardening contract: notifications/cancelled/progress untouched passthrough (§1), subprocess-lifecycle edge cases — server-crash -32002 synthesis, client-disconnect process-group teardown, truncated/oversized-frame fail-open (§2), Windows experimental degradation (§3), the full v0.3 block-flag scheme + precedence (§4), and (#21) --strict fail-CLOSED mode — terminate on an inspection-layer error, -32003 non-retriable, exit 3 (§5) |
docs/SIGNING.md |
(v0.3, #16) Sigstore keyless signing + verification of warden.lock: the optional [sigstore] extra, the deterministic mcp-warden-lock-digest/v1 statement that binds ONLY overall_digest (survives lock rotate), pin --sign / check --verify usage, the fixed-sidecar verify contract (pointer field never trusted), the full fail-closed matrix, the TUF-cache/offline caveat, and the two accepted trade-offs (rotate-replay + committed-fixture coverage gap + refresh steps) |
Runtime CLI examples retain the detailed guard commands moved from README.
| Plan | Purpose |
|---|---|
docs/plans/2026-10-04-dse717-reconciliation.md |
Recovered-branch provenance, integration ownership, failure-path validation and exact-head security/external-review gates |
docs/plans/2026-07-19-decision-receipts-design.md |
Original DSE-717 receipt, deterministic rule, evidence, recovery and replay design |
docs/plans/2026-07-19-decision-receipts-implementation.md |
Original strict-TDD execution plan and independently reviewed release gates |
docs/archive/2026-10-04-readme-community-consensus.md |
Preserved advanced README community-consensus walkthrough: pinned attesters/corpus revision, verdict exit codes and required-consensus withholding protection |
docs/plans/2026-10-04-dse717-council-fixes.md |
Council remediation: quarantine preservation, complete V2 floor presence, independently pinned historical signer/root rotation, regression evidence and bounded projection/conformance documentation |
docs/plans/2026-10-03-checkpoint-artifact-trust.md |
First human-checkpoint development wave: opt-in signature verification and unsigned review tooling, with unpublished DSE-717 work preserved and live DSE-1076 integration still dependent on it |
docs/plans/2026-07-18-agent-trust-kernel-design.md |
Non-normative execution record. Records the DSE-714 design decision and verification plan; binding requirements live in docs/AGENT_TRUST_KERNEL.md |
docs/plans/2026-07-18-content-envelope-design.md |
Non-normative DSE-715 execution record. Records the reviewed strict-TDD plan; verified behavior is documented in docs/CONTENT_ENVELOPE.md |
docs/plans/2026-07-19-pdp-pep-design.md |
Non-normative DSE-716 execution record. Records the activated-snapshot, structural-PEP, TDD, and review plan; verified behavior is documented in docs/POLICY_ENFORCEMENT.md |
| Doc | Purpose |
|---|---|
LICENSE |
MIT license |
SECURITY.md |
Private vulnerability-disclosure policy + supported versions (report via GitHub Security Advisories / email — never a public issue) |
CONTRIBUTING.md |
Dev setup, the .venv test workflow, the determinism / byte-compatibility contract, how to propose a new check |
CODE_OF_CONDUCT.md |
Contributor Covenant 2.1 |
.github/ISSUE_TEMPLATE/ |
Bug report + feature/new-check request forms (security issues routed to SECURITY.md) |
.github/PULL_REQUEST_TEMPLATE.md |
PR checklist (tests green, specs in sync, determinism preserved, no secrets) |
.gitleaks.toml |
Secret-scan config; CI runs gitleaks over full history on every push/PR |
| Doc | Purpose |
|---|---|
RELEASING.md |
Operator runbook: existing-project PyPI publisher settings, authentication-only verification, release delivery, post-release checks, failed-job recovery and rollback/yank. PyPI dist name is mcp-warden-cli; CLI/repo stay mcp-warden. |
CHANGELOG.md |
Keep-a-Changelog history through CLI 2.0.0 / schema level 4 with explicit in/out-of-scope. |
.github/workflows/release.yml |
Publish-on-Release: build Python + tested TypeScript tarball; upload only Python through OIDC (repo gate + skip-existing); Sigstore-sign artifacts/checksums. Manual verify-pypi exchanges credentials without build/upload/signing. The gate variable alone does not prove publisher alignment. |
scripts/verify_pypi_oidc.py |
Standard-library OIDC probe: reviewed-main binding, owner inspection acknowledgment, bounded HTTPS, no redirects/token logs/storage/uploads. PyPI minting can mutate pending records; exchange does not prove project upload permission. |
docs/plans/2026-10-02-pypi-automation-repair.md |
Bounded automation repair and session wrap plan, including the authenticated PyPI browser boundary. |
requirements-dev.lock · .github/workflows/deps-locked.yml |
(#59) Hash-pinned dev/CI dependency lock + the "Hash-locked dev/CI install" check (verifies --require-hashes install + that the lock stays in sync with pyproject.toml without floating to latest, #65). Dependency-update policy lives in SECURITY.md. |
src/mcp_warden/artifact_payload.py, artifact_trust.py, and cli_trust.py implement
the strict existing-artifact decoder, opt-in public-key verifier, and unsigned
review/signature CLI. Tests are tests/test_artifact_trust.py,
test_cli_trust.py, and test_artifact_trust_integration.py.
| Module | Responsibility | Spec anchor |
|---|---|---|
receipt_models.py · decision_receipts.py · signer_authorization.py · receipt_kernel.py |
(DSE-717) Closed canonical receipts and independently activated, role-bound governance signatures; no product private-key loader | DECISION_RECEIPTS.md authority/events |
rule_models.py · rule_engine.py · decision_governor.py · governed_decision.py |
(DSE-717) Strengthening-only rules, exact finite noncritical overrides and canonical effective decisions | DECISION_RECEIPTS.md rules |
evidence_state.py · evidence_latch.py · evidence_reference.py · receipt_log.py · evidence_models.py · evidence_coordinator.py · evidence_recovery.py |
(DSE-717) Independent primary/fallback evidence, compare-and-advance protected-state ports and latch-clear-last recovery; reference protection unsupported | DECISION_RECEIPTS.md evidence/recovery |
policy_enforcement_v2.py · enforcement_result_v2.py · receipt_conformance.py · receipt_conformance_models.py |
(DSE-717) Evidence on every path, failed-allow deny conversion, pre-sink revalidation and mandatory eleven-scenario/five-fixed-case reference corpus | DECISION_RECEIPTS.md evidence/conformance |
receipt_verification.py · receipt_replay.py · receipt_projection.py |
(DSE-717) Canonical signature/chain verification with retained root-activated historical authority/verifier pins, strict separate live-floor checks, effect-free historical replay, current eligibility and primary-only human explanations | DECISION_RECEIPTS.md verification/replay |
src/mcp_warden/hashing.py |
canon() (RFC 8785) + hash() + field hashes |
WARDEN_LOCK_SCHEMA §3 |
src/mcp_warden/content_models.py · content_envelope.py |
(DSE-715) Strict immutable evidence models; typed domain-separated byte hashing call surface; canonical constructors/parser; bounded derivation and one-hop lineage; explicit secret-safe projection | CONTENT_ENVELOPE.md / AGENT_TRUST_KERNEL ATK-01/02/05/06/09/12 |
src/mcp_warden/decision_models.py · policy_decision.py |
(DSE-716) Strict V1 decision models; signed policy/runtime activation; exact lease/request binding; deterministic default-deny PDP; canonical digest-only decisions and stable recovery codes | POLICY_ENFORCEMENT.md / AGENT_TRUST_KERNEL ATK-03/05/06/07/08/09 |
src/mcp_warden/policy_enforcement.py · handler_identity.py · executable_bundle.py · adapter_conformance.py |
(DSE-716) Signed adapter and executable-bundle closure; exact manifest-bound leases; closure-free mechanically code/dependency-derived frozen handlers; canonical effect binding; evidence-gated PEP; PEP-owned execution trace and multiple output-channel scans; mandatory versioned malformed-input corpus | POLICY_ENFORCEMENT.md / AGENT_TRUST_KERNEL ATK-03/04/06/08 |
src/mcp_warden/tokenizer.py |
Shared tokenizer + capability derivation (single source of truth) | CHECKS §3 / WARDEN_LOCK_SCHEMA §5.4 |
src/mcp_warden/capture.py |
Declared-surface capture over stdio (argv array, no shell) or Streamable HTTP (--url); shared list normalization, timeouts, and errors |
THREAT_MODEL §3.3 / WARDEN_LOCK_SCHEMA §4.1 |
src/mcp_warden/models.py |
Pydantic models for captured surface + lock (incl. Pinner/Attestation provenance) |
WARDEN_LOCK_SCHEMA §2–§8 |
src/mcp_warden/lockfile.py |
Lock builder + reader/writer + overall digest | WARDEN_LOCK_SCHEMA §5–§6, §9 |
src/mcp_warden/check_core.py |
(#22) Shared check verdict core (run_check / run_check_full): read_lock→capture→checks→build_lock(in-memory)→compute_drift. Single source of truth for cli.py:check AND the pre-commit wrapper |
WARDEN_LOCK_SCHEMA §6.2 |
src/mcp_warden/provenance.py |
Out-of-digest provenance construction + rotate_provenance (pure; note-cap fail-closed) + (#16) make_sigstore_pointer_attestation |
WARDEN_LOCK_SCHEMA §8.1–§8.2 |
src/mcp_warden/signing.py |
(#16) Sigstore keyless sign/verify primitives (guarded import; build_statement / sign_statement / verify_statement — verify raises on failure, returns None on success) |
SIGNING.md |
src/mcp_warden/cli_sign.py |
(#16) pin --sign / check --verify CLI control flow: fixed-sidecar verify, atomic bundle write, fail-closed exits |
SIGNING.md |
src/mcp_warden/drift.py |
Per-class drift/diff engine + severities | WARDEN_LOCK_SCHEMA §6.2 |
src/mcp_warden/drift_tool_metadata.py |
v4 annotation drift and structural output-schema classification without raw annotation disclosure | SPEC v4 extension |
src/mcp_warden/schema_diff.py |
Deterministic structural inputSchema skeleton extractor + per-fact diff classifier (WRD-DRIFT-SCHEMA-*; $ref/cyclic/malformed-safe) |
WARDEN_LOCK_SCHEMA §5.1, §6.2 |
src/mcp_warden/checks.py |
Static-check orchestrator (deterministic sort) | CHECKS §4–§5 |
src/mcp_warden/checks_secret.py |
WRD-SEC-* vendor + entropy + redaction |
CHECKS §4.2 |
src/mcp_warden/checks_supply.py |
WRD-SUP-* launch-command checks |
CHECKS §4.3 |
src/mcp_warden/redact.py |
first4 + "…" + (len=N) secret redaction |
CHECKS §8.2 |
src/mcp_warden/emitters.py |
SARIF 2.1.0 + JSONL emitters (ruleId verbatim) |
CHECKS §2 |
src/mcp_warden/policy_model.py |
Policy load + lint + fail-closed schema | POLICY_MODEL §3, §4.1 |
src/mcp_warden/policy_eval.py |
Single-sample eval + runtime arg eval (fs/shell/http-SSRF/sql) | POLICY_MODEL §2, §4.2, §5 |
src/mcp_warden/result_inspection.py |
(v0.2) WRD-RES-* catalog public entry (inspect_result, ResultFinding, InspectionPolicy) — single source run by guard + inspect |
RESULT_INSPECTION §1–§6, §8 |
src/mcp_warden/res_catalog.py |
(v0.2) per-rule evaluators + content-block text extraction | RESULT_INSPECTION §1, §3–§5 |
src/mcp_warden/res_rules.py · res_net.py |
(v0.2) deterministic primitives: ANSI codepoint scan + inject-phrase normalize (res_rules), exfil/URL host matching + seed denylists + (#54, D6) raw-IP-literal matching in result text vs SSRF/exfil ranges — WRD-RES-EXFIL-IP-LITERAL, no DNS (res_net) |
RESULT_INSPECTION §3.1, §3.3, §3.4, §4.1, §5.1 |
src/mcp_warden/net_rules.py |
SSRF deny CIDRs (loopback/RFC1918/link-local/IPv6) + host parse — used by policy_eval (http-request SSRF) and the #54 raw-IP-literal matcher |
POLICY_MODEL §2.3, §5 |
src/mcp_warden/guard.py |
(v0.2/v0.3) proxy runner: subprocess lifecycle, own pgrp, signal forwarding, single-loop byte pumps, teardown-path decision (client-EOF vs child-exit) | GUARD_PROXY §1, §2.3, §2.6 · V3 §2 |
src/mcp_warden/guard_loop.py · guard_result.py |
(v0.2/v0.3) frame discipline: v0.3 default-block GuardConfig + c2s arg-policy + cancel/progress passthrough (guard_loop), s2c result inspection + tools/list_changed gate + on-wire block decision (guard_result) |
GUARD_PROXY §2, §4, §7, §9 · V3 §1, §4 |
src/mcp_warden/guard_lifecycle.py |
(v0.3) lifecycle teardown: -32002 pending-id synthesis, 128+signum exit mapping, POSIX process-group TERM→grace→KILL teardown, Windows best-effort + WRD-RES-WIN-LIFECYCLE; (#21) -32003 synthesize_strict_abort |
GUARD_PROXY_V3 §2, §3, §5 |
src/mcp_warden/guard_io.py |
(v0.3) async stdio adapters (wrap_recv/wrap_send) bridging blocking stdio to the single-loop framer |
GUARD_PROXY §2.3 |
src/mcp_warden/guard_banner.py |
(#57) startup posture banner: renders the resolved BLOCKING / MONITOR-ONLY / INACTIVE enforcement state to stderr (derived from BLOCK_RULES + GuardConfig, no server identity), so a naive guard run can't be misread as fully protected. Paired with cli_guard's non-POSIX degraded-platform refusal (exit 2 unless --allow-degraded-platform) |
GUARD_PROXY_V3 §3 |
src/mcp_warden/guard_list_gate.py |
(v0.3) runtime tools/list drift gate: hashes the live list vs the lock (reuses hashing), fail-open on malformed payloads; (#21) strict= re-raises the nested hash error instead of swallowing it |
GUARD_PROXY §4.3, §7.3 · V3 §5 |
src/mcp_warden/framing.py |
(v0.2) single-reader stdio framer (Content-Length + newline), original-bytes pass-through, truncation-at-EOF capture | GUARD_PROXY §2.4, §2.5 · V3 §2.3 |
src/mcp_warden/wire_block.py |
(v0.2/v0.3) on-wire block synthesis: -32001 error-response + redacted-content (_meta.warden.modified); v0.3 -32002 transport_error; (#21) -32003 strict_abort_error (non-retriable) |
GUARD_PROXY §7 · V3 §2.6, §5 |
src/mcp_warden/inspector.py |
(v0.2) offline JSONL analyzer over recorded sessions (same catalog) | GUARD_PROXY §3 |
src/mcp_warden/emit_res.py |
(v0.2) SARIF 2.1.0 + JSONL emitters for ResultFinding (action/direction/tier) |
GUARD_PROXY §10 |
src/mcp_warden/cli.py · cli_guard.py · cli_lock.py · cli_diff.py |
typer CLI (pin/check/policy/guard/inspect/lock rotate/diff), exit codes; check delegates its verdict to check_core.run_check_full (#22); guard/inspect bodies in cli_guard, lock rotate + integrity gate in cli_lock, (v0.3) diff redacted offline lock viewer (SAFE_PROVENANCE_FIELDS allowlist, never reads server.command/args) in cli_diff |
all |
src/mcp_warden/precommit.py |
(#22) mcp-warden-precommit pre-commit entry point — wraps check_core.run_check; check-only (never imports pin/lock-writer, never opens the lock for write) |
README pre-commit section |
| File | Covers |
|---|---|
tests/test_dse717_council_fixes.py |
(DSE-717) Critical/rule quarantine preservation after rejected overrides, closed governor errors, every mandatory V2 floor omission, conditional override/legacy compatibility, retired live signer rejection and root/key rotation followed by append/reopen/chain verification |
tests/test_receipt_conformance.py · test_dse717_review_regressions.py · test_policy_enforcement_v2.py · test_handler_boundary.py |
(DSE-717) Mandatory failure/restart corpus, actual evidence/projection scans, negative sink absence, distinct failed-allow conversion, closed hostile inputs and supported interpreter/serialized-code boundaries |
tests/test_decision_receipts.py · test_receipt_hardening.py · test_rule_engine.py · test_evidence_coordinator.py · test_evidence_recovery.py · test_receipt_verification.py · test_receipt_replay.py · test_receipt_projection.py |
(DSE-717) Canonical signing/authority isolation, strict rules/finite overrides, independent log/state/latch failures, authenticated recovery, chain verification, effect-free replay and closed projections |
tests/test_hashing.py |
JCS+SHA-256 reproducibility, canonical-form pins, null handling |
tests/test_content_envelope.py |
(DSE-715) Strict/frozen models, typed digest domains, nine ingress kinds, canonical/cap boundary, deterministic lineage, parser rejection matrix, atomic digest verification, and planted-secret output/error/log scans |
tests/test_policy_decision.py · test_policy_enforcement.py · test_adapter_conformance.py |
(DSE-716) Exact policy/runtime/adapter/bundle activation, deterministic decisions, every subject/effect/lease/manifest binding, trusted-time/rollback/revocation matrix, critical floor, hostile nested construction, callable drift resistance, evidence/sink ordering, fixed-corpus enforcement, cap boundaries, and deterministic reports |
tests/test_tokenizer.py |
Segment-exact tokenization + capability derivation |
tests/test_checks.py |
Capability/secret/supply/robustness checks + redaction |
tests/test_drift.py |
Drift per class (added/removed/modified/server-identity/unapproved) |
tests/test_schema_diff.py |
Structural skeleton extraction (purity, $ref/cyclic/malformed safety) + per-fact diff taxonomy (required/enum/type/constraint/additionalProperties) + v1 fallback |
tests/test_lockfile.py |
Lock build/write/read, digest exclusions, hashes-not-raw |
tests/test_policy.py |
Lint (incl. unknown-key error) + eval (allow/deny/SSRF/fail-closed) |
tests/test_emitters.py |
SARIF shape + level mapping + JSONL records |
tests/test_e2e_pin_check.py |
Headline: real stdio pin→mutate→check round-trip |
tests/test_capture_http.py |
(#74, DSE-57) Async/sync Streamable HTTP capture, protocol/list normalization, timeout handling, and connection errors |
tests/test_diff.py |
(v0.3) warden diff renderer: identical→"no differences", tool add/remove + schema change rows, redaction-leak guard (secret in server.args absent from human/--json/--sarif incl. parsed-JSONL detail), provenance-only section vs empty integrity drift, --exit-code (1 on integrity drift / 0 on provenance-only), --no-provenance M6 message, fail-closed on missing/invalid lock |
tests/test_result_inspection.py |
(v0.2) WRD-RES-*: ANSI codepoint match (incl. extended/binary-ok), secret-echo reuse + redaction, exfil host/subdomain boundary + path-qualified, injection exact-phrase (no broad-regex FP), URL/uninspectable notes |
tests/test_inspection_policy.py |
(v0.2) §11 per-tool policy fail-safe defaults, inspection omission/None digest parity in the current format, inspection-policy drift, pin-time validation, reader fallback + LOCK-INVALID |
tests/test_wire_block.py |
(v0.2) -32001 error-response shape, block-mode mapping, ANSI strip-in-place _meta.warden.modified, secret redact-in-place |
tests/test_framing.py |
(v0.2) newline + Content-Length framing, chunk-split reads, original-bytes pass-through, malformed-frame parse capture |
tests/test_guard_posture.py |
(v0.2/v0.3) fail-open (inspector exception/malformed → pass-through) vs fail-closed (policy deny → block under armed_policy), audit-only precedence over default-on |
tests/test_guard_proxy.py |
(v0.2/v0.3) Headline: real tools/call through guard: v0.3 default-block + --audit-only shadow restore, deprecated --block-* no-op + stderr note, inject stays monitor, forced framing error survives |
tests/test_guard_v3.py |
(v0.3) opt-out demotes to shadow (--no-block-*/--allow-exfil-domain/--no-block-deterministic), tools/list_changed gate block+shadow, policy deny block+shadow, audit-only override, cancel/progress passthrough, server-crash → -32002 for every pending id, client-disconnect child reap (no orphan), truncated + oversized frame fail-open |
tests/test_guard_strict.py |
(#21) --strict fail-CLOSED: 4 terminate sites (request-policy / result-inspect / list-gate / nested-hash re-raise) → exit 3 + one strict_abort stderr line + -32003 client frame + child reaped; negatives (truncated/over-cap/unparseable/clean) do NOT abort; default --no-strict byte-identical fail-open regression; secret-leak redaction; CLI threading; double-emission single line; StrictInspectionAbort is BaseException-not-Exception + anyio ExceptionGroup unwrap |
tests/test_inspect_parity.py |
(v0.2) guard↔inspect finding parity on the same recorded frames + inspect exit codes |
tests/fuzz/ (test_fuzz_framing.py · test_fuzz_ansi.py · test_fuzz_domain.py · test_fuzz_redact.py · test_fuzz_content_envelope.py · test_fuzz_policy_decision.py · test_fuzz_receipts.py) |
(#17 / DSE-715 / DSE-716) hypothesis property-fuzzing of the live runtime attack surface, content envelopes, identity substitution, arbitrary effect bytes, explicit trusted-time boundaries, deterministic decisions, and planted-secret absence. ci/fuzz profiles in tests/fuzz/conftest.py; deep soak via make fuzz |
tests/fixtures/clean_server.py · mutated_server.py |
Real MCP SDK stdio fixtures |
tests/fixtures/poison_server.py |
(v0.2) result-poisoning fixture server (ANSI/secret-echo/exfil/inject/clean tools) |
tests/fixtures/crash_server.py · listchange_server.py · clean_listchange.warden.lock |
(v0.3) raw-stdio lifecycle fixtures: crash-mid-call (-32002) and tools/list_changed rug-pull + its pinned clean lock |
tests/fixtures/fault_guard_launcher.py |
(#21) test-only launcher that monkeypatches ONE inspection function (inspect_result / evaluate_call / diverges_from_lock / _hash_live_tools) to raise inside the spawned guard child, then runs the real CLI — drives the --strict terminate-site tests without any test branch in production code; FAULT_SECRET plants a secret for the redaction test |