Releases: DataScience-EngineeringExperts/mcp-warden
Release list
v1.1.0
Added
- Injection-phrase FP-instrumentation (Refs #12). Shippable, non-default-changing
groundwork for eventually promotingWRD-RES-INJECT-PHRASEto default-block once field
false-positive (FP) data justifies it. No default posture changed — the fuzzy tier
stays monitor-only, andWRD-RES-INJECT-PHRASEkeeps its tier, its default action, and its
place in the error-replacement set. Added: (1) a discretematched_phrasesarray on the
finding record (JSONL) +matchedPhrasesSARIF property, so per-phrase aggregation reads
a structured field instead of parsingmessage; (2) arun-summaryJSONL record + SARIF
run property carryingframes_inspected— the base-rate denominator for a per-phrase FP
rate — plusinject_phrase_findings; (3)--block-inject-phrase-only <file>, a
default-off, per-phrase opt-in that blocks ONLY the named exact phrases while every other
curated phrase stays monitor (narrower than--block-inject-phrase; the future
deterministic-subset promotion mechanism); (4) an operator record → inspect → label
FP-collection workflow indocs/RESULT_INSPECTION.md§10. Security: the telemetry
surface emits only the curated denylist phrase, rule id, metadata, action, and counts —
never raw result content (which can carry secrets/PII); all aggregation is local-only,
no phone-home. Issue #12 stays open (the default-block flip remains gated on the FP data
this instrumentation collects). - CI coverage / lint / CVE gates. The
CIworkflow now enforces three new
standing gates: (1) a coverage floor —pytest --cov=mcp_warden --cov-fail-under=80(whole-project coverage is ~86%; the floor is pinned below
actual so it can only rise). Subprocess coverage ofguard_list_gate.py(which
only executes inside the guard child spawned by the strict-abort tests) is now
captured via[tool.coverage.run] parallel = true+COVERAGE_PROCESS_START,
taking it from a 0% visibility artifact to ~89%. (2) A ruff lint gate
(ruff check .) with config in[tool.ruff](pyflakes/pycodestyle/isort/
bugbear;line-length = 100). (3) A pip-audit CVE gate indeps-locked
that audits the resolved dependency closure and fails closed on any advisory. - Trust-root unit tests (
tests/test_signing_unit.py). 25 new tests drive
the internalsigning.pysign/verify code paths directly (mocking the sigstore
boundary — no network, OIDC, or Fulcio/Rekor traffic), liftingsigning.py
line coverage from 61% to 99%. Covers the sign path (ambient + explicit token),
the verify path (identity/issuer plumbing), and every fail-closed branch.
Changed
-
Dependency refresh (security). Bumped the hash-locked dev/CI closure:
pydantic-settings2.14.1 → 2.14.2 (clears advisory GHSA-4xgf-cpjx-pc3j),
plus current minors ofmcp(1.27.2 → 1.28.1),cryptography(→ 49.0.0),
anyio(4.13.0 → 4.14.2), and others.pytest-covadded to thedevextra. -
Runtime DNS resolution SSRF bypass detection (
WRD-RES-EXFIL-DNS-SSRF) (#11):
theguardproxy now resolves URL hostnames fromtools/callresults at runtime
and blocks (error-replace) when any resolved IP falls in a deny range
(SSRF_NETWORKS— link-local, loopback, RFC1918, IPv6 ULA/loopback/link-local).
This closes the bypass whereWRD-RES-EXFIL-IP-LITERALcould not fire because the
result contained a DNS hostname (e.g.169.254.169.254.nip.io) rather than a raw
IP literal. Resolution is bounded by 1 s across all hostnames per result frame,
fail-open (any DNS error = no hit), and opt-out via--no-block-exfil-dns-ssrf
(or--no-block-deterministic). Raw IP literals and the offlineinspectcommand
are unchanged. New moduleres_dns.py; 23 new tests.
v1.0.1
Packaging-metadata point release. No code or behavior changes.
Added
- Added
[project.urls]packaging metadata (Homepage / Repository / Documentation /
Changelog / Issues) so the PyPI page links back to the canonical repo and docs.
The published 1.0.0 page carried no project URLs; for a supply-chain tool that must
be distinguishable from the unrelatedmcp-wardenPyPI package, the back-links to
the canonical GitHub repo and docs site are part of the trust surface.
v1.0.0
First stable release. No new core features over 0.3.0 — v1 is the
distribution-hygiene, self-credentialing, and documentation hardening of an already
v1-strong foundation. Highlights of the 0.3.0 → 1.0.0 arc:
Added
- Sigstore keyless signing + verification of
warden.lockviapin --signand
check --verify(opt-inmcp-warden-cli[sigstore]extra). The tool now signs its own
release artifacts, not just others' locks. (#16) - Deterministic structural JSON-Schema diffing for tool
inputSchemachanges:
each security-relevant mutation (required dropped, enum widened/removed, type
broadened, constraint relaxed,additionalPropertiesopened) is classified
per-fact asWRD-DRIFT-SCHEMA-*instead of one opaque change. (#15) - In-document
$refresolution in the schema differ, so$reftargets are diffed
structurally instead of reported as an opaque leaf. (#29) - Official composite GitHub Action wrapping
mcp-warden checkwith SARIF upload to
code scanning; all runtime deps hash-locked inaction/requirements.lock. (#18) - pre-commit hook (
mcp-warden-check) running the identical drift verdict locally,
with a--strictfail-closed mode and a pre-push variant. (#22) --strictfail-closed mode for theguardproxy: an internal inspection error
terminates the session (exit 3,-32003) instead of failing open. (#21)warden diff: offline, redacted, human-readable comparison of two locks over the
drift engine — never re-captures, never prints rawserver.command/args. (#20)- Structured provenance metadata +
warden lock rotate: re-attest a baseline's
provenance without re-capturing the surface (overall_digeststays byte-identical).
(#19) - Property-based fuzzing (Hypothesis) of the guard stdio framer, ANSI stripper,
exfil-domain matcher, and secret redactor undertests/fuzz/. (#17) --strict-frame-cap: fail-closed on over-cap server→client result frames. (#37)- Raw-IP-literal exfil/SSRF matching (D6): deterministic matching of exfil-domain
rules against raw IPv4/IPv6 literal hosts, closing the IP-literal bypass of the
domain matcher. (#54) guardstartup posture banner reporting the active enforcement stance
(active / monitor / inactive, derived from the liveBLOCK_RULES), plus a
fail-closed refusal (exit 2) on non-POSIX / degraded platforms unless explicitly
overridden. (#57)- Vendor-neutral MCP Lock Format v1 spec (
docs/SPEC.md) and an education-first
docs site with an honest comparison page. (#46, #47, #48, #50) - MCP Lock Format v1 compatibility & versioning policy (
docs/SPEC.md §14) plus a
THREAT_MODEL.md §5.3self-bypass section (signed-lock replay, SARIF suppression,
JCS canonicalization edge cases). (#56) - Hash-pinned dev/CI lockfile (
requirements-dev.lock) and a documented
dependency-update policy inSECURITY.md, so the toolchain that builds a
supply-chain gate is itself pinned. (#59, closes #14) - Release-on-publish GitHub workflow with OIDC trusted publishing to PyPI and
self Sigstore signing of the release artifacts, plus aRELEASING.mdrunbook. (#58)
Changed
- Distribution name
mcp-warden-cli. The PyPI distribution name ismcp-warden-cli
becausemcp-wardenis taken on PyPI by an unrelated package, and PyPI rejects
mcpwardenas "too similar" to it (separator-stripping collapses both to the same
string).mcp-warden-clinormalizes to letters-onlymcpwardencli, which is
distinct. The CLI command (mcp-warden) and repo are unchanged. (#55) - README repositioned around the lockfile / CI-gate category claim, with the
stdio-transport scope surfaced in the opening paragraph and a "Who it's for"
use-cases section (author-flagship first). (#45, #49, #55)
Fixed
redact_secretnever discloses more than half of a detected secret. (#38)- Removed the install hazard: every
pip install mcp-wardensnippet (README, docs
site, example workflows) now installsmcp-warden-cli. The README carries a prominent
impostor-warning banner. (#55) - Corrected the
SPEC.mdworked-exampleschema_versionfrom1to3to match the
liveSCHEMA_VERSION. (#56)