mcp-warden-cli 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. mcp_warden_cli-1.0.0/.github/ISSUE_TEMPLATE/bug_report.yml +75 -0
  2. mcp_warden_cli-1.0.0/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. mcp_warden_cli-1.0.0/.github/ISSUE_TEMPLATE/feature_request.yml +52 -0
  4. mcp_warden_cli-1.0.0/.github/PULL_REQUEST_TEMPLATE.md +39 -0
  5. mcp_warden_cli-1.0.0/.github/dependabot.yml +24 -0
  6. mcp_warden_cli-1.0.0/.github/workflows/action-test.yml +147 -0
  7. mcp_warden_cli-1.0.0/.github/workflows/deps-locked.yml +88 -0
  8. mcp_warden_cli-1.0.0/.github/workflows/docs.yml +81 -0
  9. mcp_warden_cli-1.0.0/.github/workflows/examples.yml +95 -0
  10. mcp_warden_cli-1.0.0/.github/workflows/integrity-gate.yml +230 -0
  11. mcp_warden_cli-1.0.0/.github/workflows/release.yml +188 -0
  12. mcp_warden_cli-1.0.0/.github/workflows/sigstore-fixture.yml +76 -0
  13. mcp_warden_cli-1.0.0/.gitignore +25 -0
  14. mcp_warden_cli-1.0.0/.gitleaks.toml +20 -0
  15. mcp_warden_cli-1.0.0/.hypothesis/.gitignore +9 -0
  16. mcp_warden_cli-1.0.0/.hypothesis/constants/0ac87047b2101d00 +4 -0
  17. mcp_warden_cli-1.0.0/.hypothesis/constants/0f78f4c5dfc3ec68 +4 -0
  18. mcp_warden_cli-1.0.0/.hypothesis/constants/1123ff8c7df61a75 +4 -0
  19. mcp_warden_cli-1.0.0/.hypothesis/constants/166123028c09ce5a +4 -0
  20. mcp_warden_cli-1.0.0/.hypothesis/constants/19963d50c188fc89 +4 -0
  21. mcp_warden_cli-1.0.0/.hypothesis/constants/1bc4420e557a4a6c +4 -0
  22. mcp_warden_cli-1.0.0/.hypothesis/constants/1d320fe167a83e7e +4 -0
  23. mcp_warden_cli-1.0.0/.hypothesis/constants/1d37c2b81416c9cc +4 -0
  24. mcp_warden_cli-1.0.0/.hypothesis/constants/1d92178d356cd006 +4 -0
  25. mcp_warden_cli-1.0.0/.hypothesis/constants/1eb1d2091c42d146 +4 -0
  26. mcp_warden_cli-1.0.0/.hypothesis/constants/22c9161fb29ccd1d +4 -0
  27. mcp_warden_cli-1.0.0/.hypothesis/constants/2861c475f8f6640d +4 -0
  28. mcp_warden_cli-1.0.0/.hypothesis/constants/2c648f5ece25bf1b +4 -0
  29. mcp_warden_cli-1.0.0/.hypothesis/constants/2fb82bfa0bdf25f4 +4 -0
  30. mcp_warden_cli-1.0.0/.hypothesis/constants/31b7090f6083b3de +4 -0
  31. mcp_warden_cli-1.0.0/.hypothesis/constants/38879f4735819604 +4 -0
  32. mcp_warden_cli-1.0.0/.hypothesis/constants/3a5c232418138d5e +4 -0
  33. mcp_warden_cli-1.0.0/.hypothesis/constants/4c60a6d5813c6026 +4 -0
  34. mcp_warden_cli-1.0.0/.hypothesis/constants/54fa25d1048e526f +4 -0
  35. mcp_warden_cli-1.0.0/.hypothesis/constants/56c2321fd144ff81 +4 -0
  36. mcp_warden_cli-1.0.0/.hypothesis/constants/5abdd8a8fa0f26a8 +4 -0
  37. mcp_warden_cli-1.0.0/.hypothesis/constants/5d68adf45561bab8 +4 -0
  38. mcp_warden_cli-1.0.0/.hypothesis/constants/5e6c439c06f8166c +4 -0
  39. mcp_warden_cli-1.0.0/.hypothesis/constants/63088e1987514d1f +4 -0
  40. mcp_warden_cli-1.0.0/.hypothesis/constants/67da63c67def28cd +4 -0
  41. mcp_warden_cli-1.0.0/.hypothesis/constants/6985dbd48e79fe50 +4 -0
  42. mcp_warden_cli-1.0.0/.hypothesis/constants/6e92e55af0b43dac +4 -0
  43. mcp_warden_cli-1.0.0/.hypothesis/constants/6f8e50d9bba46424 +4 -0
  44. mcp_warden_cli-1.0.0/.hypothesis/constants/752d20f4d08bbab8 +4 -0
  45. mcp_warden_cli-1.0.0/.hypothesis/constants/77188865a8b89606 +4 -0
  46. mcp_warden_cli-1.0.0/.hypothesis/constants/7c0227c1543cf1a7 +4 -0
  47. mcp_warden_cli-1.0.0/.hypothesis/constants/7c609014e505cdb7 +4 -0
  48. mcp_warden_cli-1.0.0/.hypothesis/constants/7dae633ad6beb312 +4 -0
  49. mcp_warden_cli-1.0.0/.hypothesis/constants/818b5634372ffcc0 +4 -0
  50. mcp_warden_cli-1.0.0/.hypothesis/constants/822d60e72b73ac67 +4 -0
  51. mcp_warden_cli-1.0.0/.hypothesis/constants/86dc3a317f141aa1 +4 -0
  52. mcp_warden_cli-1.0.0/.hypothesis/constants/88a6443235d3c4c3 +4 -0
  53. mcp_warden_cli-1.0.0/.hypothesis/constants/8c3092a523c48b3d +4 -0
  54. mcp_warden_cli-1.0.0/.hypothesis/constants/8dbbda4799fecb3b +4 -0
  55. mcp_warden_cli-1.0.0/.hypothesis/constants/9504269672cd5922 +4 -0
  56. mcp_warden_cli-1.0.0/.hypothesis/constants/96702b7d6cc0aac4 +4 -0
  57. mcp_warden_cli-1.0.0/.hypothesis/constants/9c31cd3a5545e4b8 +4 -0
  58. mcp_warden_cli-1.0.0/.hypothesis/constants/9e3dbdc584aee45b +4 -0
  59. mcp_warden_cli-1.0.0/.hypothesis/constants/a1b74dede9492584 +4 -0
  60. mcp_warden_cli-1.0.0/.hypothesis/constants/a2d7b9dcf7c963e8 +4 -0
  61. mcp_warden_cli-1.0.0/.hypothesis/constants/a46cdf2d81318187 +4 -0
  62. mcp_warden_cli-1.0.0/.hypothesis/constants/ab70b0843c8efda8 +4 -0
  63. mcp_warden_cli-1.0.0/.hypothesis/constants/ac3a6c5416518fdc +4 -0
  64. mcp_warden_cli-1.0.0/.hypothesis/constants/ae9bcc4de55ea6df +4 -0
  65. mcp_warden_cli-1.0.0/.hypothesis/constants/b2b4900e07439276 +4 -0
  66. mcp_warden_cli-1.0.0/.hypothesis/constants/b63b352e6de46daa +4 -0
  67. mcp_warden_cli-1.0.0/.hypothesis/constants/bfd5fd085ec158e1 +4 -0
  68. mcp_warden_cli-1.0.0/.hypothesis/constants/c348f06ef4dc9bbf +4 -0
  69. mcp_warden_cli-1.0.0/.hypothesis/constants/c7eb1b39a3fecbe8 +4 -0
  70. mcp_warden_cli-1.0.0/.hypothesis/constants/c7ff6b7c362ffdaa +4 -0
  71. mcp_warden_cli-1.0.0/.hypothesis/constants/c8c7f4b8a3ba3756 +4 -0
  72. mcp_warden_cli-1.0.0/.hypothesis/constants/cba21f149513281d +4 -0
  73. mcp_warden_cli-1.0.0/.hypothesis/constants/ce757813990c427f +4 -0
  74. mcp_warden_cli-1.0.0/.hypothesis/constants/cf4860dbd577fa02 +4 -0
  75. mcp_warden_cli-1.0.0/.hypothesis/constants/d2d2e0b391659f5e +4 -0
  76. mcp_warden_cli-1.0.0/.hypothesis/constants/d7dd46e3ab67e9f2 +4 -0
  77. mcp_warden_cli-1.0.0/.hypothesis/constants/d8a6e73ca1695f6c +4 -0
  78. mcp_warden_cli-1.0.0/.hypothesis/constants/e4dc134db43a698a +4 -0
  79. mcp_warden_cli-1.0.0/.hypothesis/constants/e91e67a53a5aa4c6 +4 -0
  80. mcp_warden_cli-1.0.0/.hypothesis/constants/ea25419afd56349e +4 -0
  81. mcp_warden_cli-1.0.0/.hypothesis/constants/f6adf5c5dc4d4d5f +4 -0
  82. mcp_warden_cli-1.0.0/.hypothesis/constants/fce0200863b3c581 +4 -0
  83. mcp_warden_cli-1.0.0/.hypothesis/constants/ffa00c565d1a3509 +4 -0
  84. mcp_warden_cli-1.0.0/.hypothesis/unicode_data/15.1.0/charmap.json.gz +0 -0
  85. mcp_warden_cli-1.0.0/.hypothesis/unicode_data/15.1.0/codec-utf-8.json.gz +0 -0
  86. mcp_warden_cli-1.0.0/.pre-commit-hooks.yaml +27 -0
  87. mcp_warden_cli-1.0.0/CHANGELOG.md +128 -0
  88. mcp_warden_cli-1.0.0/CODEOWNERS +12 -0
  89. mcp_warden_cli-1.0.0/CODE_OF_CONDUCT.md +133 -0
  90. mcp_warden_cli-1.0.0/CONTRIBUTING.md +222 -0
  91. mcp_warden_cli-1.0.0/DOCUMENTATION_INDEX.md +184 -0
  92. mcp_warden_cli-1.0.0/LICENSE +21 -0
  93. mcp_warden_cli-1.0.0/Makefile +23 -0
  94. mcp_warden_cli-1.0.0/PKG-INFO +517 -0
  95. mcp_warden_cli-1.0.0/README.md +493 -0
  96. mcp_warden_cli-1.0.0/RELEASING.md +178 -0
  97. mcp_warden_cli-1.0.0/SECURITY.md +139 -0
  98. mcp_warden_cli-1.0.0/SYSTEM_CONTEXT_DIAGRAM.md +195 -0
  99. mcp_warden_cli-1.0.0/action/build-requirements.lock +22 -0
  100. mcp_warden_cli-1.0.0/action/requirements.lock +664 -0
  101. mcp_warden_cli-1.0.0/action.yml +263 -0
  102. mcp_warden_cli-1.0.0/docs/CHECKS.md +294 -0
  103. mcp_warden_cli-1.0.0/docs/GUARD_PROXY.md +499 -0
  104. mcp_warden_cli-1.0.0/docs/GUARD_PROXY_V3.md +499 -0
  105. mcp_warden_cli-1.0.0/docs/POLICY_MODEL.md +262 -0
  106. mcp_warden_cli-1.0.0/docs/RESULT_INSPECTION.md +404 -0
  107. mcp_warden_cli-1.0.0/docs/SIGNING.md +272 -0
  108. mcp_warden_cli-1.0.0/docs/SPEC.md +499 -0
  109. mcp_warden_cli-1.0.0/docs/THREAT_MODEL.md +321 -0
  110. mcp_warden_cli-1.0.0/docs/THREAT_MODEL_V2.md +257 -0
  111. mcp_warden_cli-1.0.0/docs/WARDEN_LOCK_EXAMPLE.md +58 -0
  112. mcp_warden_cli-1.0.0/docs/WARDEN_LOCK_SCHEMA.md +501 -0
  113. mcp_warden_cli-1.0.0/docs-site/checklist.md +91 -0
  114. mcp_warden_cli-1.0.0/docs-site/comparison.md +101 -0
  115. mcp_warden_cli-1.0.0/docs-site/index.md +34 -0
  116. mcp_warden_cli-1.0.0/docs-site/lock-format.md +63 -0
  117. mcp_warden_cli-1.0.0/docs-site/pin-in-ci.md +137 -0
  118. mcp_warden_cli-1.0.0/docs-site/quickstart.md +98 -0
  119. mcp_warden_cli-1.0.0/docs-site/rug-pull.md +67 -0
  120. mcp_warden_cli-1.0.0/docs-site/tool-poisoning.md +74 -0
  121. mcp_warden_cli-1.0.0/examples/README.md +55 -0
  122. mcp_warden_cli-1.0.0/examples/github-actions/matrix-multiple-servers.yml +45 -0
  123. mcp_warden_cli-1.0.0/examples/github-actions/pin-on-merge-check-on-pr.yml +57 -0
  124. mcp_warden_cli-1.0.0/examples/github-actions/private-repo-no-sarif.yml +38 -0
  125. mcp_warden_cli-1.0.0/examples/github-actions/sarif-upload.yml +38 -0
  126. mcp_warden_cli-1.0.0/examples/gitlab-ci/.gitlab-ci.yml +33 -0
  127. mcp_warden_cli-1.0.0/examples/pinned-servers/server-everything/README.md +43 -0
  128. mcp_warden_cli-1.0.0/examples/pinned-servers/server-everything/warden.lock +581 -0
  129. mcp_warden_cli-1.0.0/examples/pinned-servers/server-memory/README.md +47 -0
  130. mcp_warden_cli-1.0.0/examples/pinned-servers/server-memory/warden.lock +555 -0
  131. mcp_warden_cli-1.0.0/examples/pinned-servers/server-sequential-thinking/README.md +39 -0
  132. mcp_warden_cli-1.0.0/examples/pinned-servers/server-sequential-thinking/warden.lock +173 -0
  133. mcp_warden_cli-1.0.0/examples/pre-commit/.pre-commit-config.yaml +29 -0
  134. mcp_warden_cli-1.0.0/mkdocs.yml +73 -0
  135. mcp_warden_cli-1.0.0/pyproject.toml +54 -0
  136. mcp_warden_cli-1.0.0/requirements-dev.lock +694 -0
  137. mcp_warden_cli-1.0.0/src/mcp_warden/__init__.py +25 -0
  138. mcp_warden_cli-1.0.0/src/mcp_warden/capture.py +197 -0
  139. mcp_warden_cli-1.0.0/src/mcp_warden/check_core.py +98 -0
  140. mcp_warden_cli-1.0.0/src/mcp_warden/checks.py +163 -0
  141. mcp_warden_cli-1.0.0/src/mcp_warden/checks_secret.py +129 -0
  142. mcp_warden_cli-1.0.0/src/mcp_warden/checks_supply.py +146 -0
  143. mcp_warden_cli-1.0.0/src/mcp_warden/cli.py +367 -0
  144. mcp_warden_cli-1.0.0/src/mcp_warden/cli_diff.py +245 -0
  145. mcp_warden_cli-1.0.0/src/mcp_warden/cli_guard.py +301 -0
  146. mcp_warden_cli-1.0.0/src/mcp_warden/cli_lock.py +124 -0
  147. mcp_warden_cli-1.0.0/src/mcp_warden/cli_sign.py +304 -0
  148. mcp_warden_cli-1.0.0/src/mcp_warden/drift.py +272 -0
  149. mcp_warden_cli-1.0.0/src/mcp_warden/emit_res.py +102 -0
  150. mcp_warden_cli-1.0.0/src/mcp_warden/emitters.py +169 -0
  151. mcp_warden_cli-1.0.0/src/mcp_warden/framing.py +338 -0
  152. mcp_warden_cli-1.0.0/src/mcp_warden/guard.py +397 -0
  153. mcp_warden_cli-1.0.0/src/mcp_warden/guard_banner.py +211 -0
  154. mcp_warden_cli-1.0.0/src/mcp_warden/guard_io.py +70 -0
  155. mcp_warden_cli-1.0.0/src/mcp_warden/guard_lifecycle.py +320 -0
  156. mcp_warden_cli-1.0.0/src/mcp_warden/guard_list_gate.py +95 -0
  157. mcp_warden_cli-1.0.0/src/mcp_warden/guard_loop.py +332 -0
  158. mcp_warden_cli-1.0.0/src/mcp_warden/guard_result.py +249 -0
  159. mcp_warden_cli-1.0.0/src/mcp_warden/guard_strict.py +159 -0
  160. mcp_warden_cli-1.0.0/src/mcp_warden/hashing.py +102 -0
  161. mcp_warden_cli-1.0.0/src/mcp_warden/inspector.py +169 -0
  162. mcp_warden_cli-1.0.0/src/mcp_warden/lockfile.py +299 -0
  163. mcp_warden_cli-1.0.0/src/mcp_warden/models.py +300 -0
  164. mcp_warden_cli-1.0.0/src/mcp_warden/net_rules.py +80 -0
  165. mcp_warden_cli-1.0.0/src/mcp_warden/policy_eval.py +264 -0
  166. mcp_warden_cli-1.0.0/src/mcp_warden/policy_model.py +261 -0
  167. mcp_warden_cli-1.0.0/src/mcp_warden/precommit.py +259 -0
  168. mcp_warden_cli-1.0.0/src/mcp_warden/provenance.py +199 -0
  169. mcp_warden_cli-1.0.0/src/mcp_warden/redact.py +52 -0
  170. mcp_warden_cli-1.0.0/src/mcp_warden/res_catalog.py +198 -0
  171. mcp_warden_cli-1.0.0/src/mcp_warden/res_net.py +227 -0
  172. mcp_warden_cli-1.0.0/src/mcp_warden/res_rules.py +176 -0
  173. mcp_warden_cli-1.0.0/src/mcp_warden/result_inspection.py +201 -0
  174. mcp_warden_cli-1.0.0/src/mcp_warden/schema_diff.py +548 -0
  175. mcp_warden_cli-1.0.0/src/mcp_warden/signing.py +291 -0
  176. mcp_warden_cli-1.0.0/src/mcp_warden/tokenizer.py +199 -0
  177. mcp_warden_cli-1.0.0/src/mcp_warden/wire_block.py +258 -0
  178. mcp_warden_cli-1.0.0/tests/__init__.py +0 -0
  179. mcp_warden_cli-1.0.0/tests/fixtures/clean.warden.lock +141 -0
  180. mcp_warden_cli-1.0.0/tests/fixtures/clean_listchange.warden.lock +35 -0
  181. mcp_warden_cli-1.0.0/tests/fixtures/clean_server.py +76 -0
  182. mcp_warden_cli-1.0.0/tests/fixtures/crash_server.py +66 -0
  183. mcp_warden_cli-1.0.0/tests/fixtures/fault_guard_launcher.py +91 -0
  184. mcp_warden_cli-1.0.0/tests/fixtures/listchange_server.py +111 -0
  185. mcp_warden_cli-1.0.0/tests/fixtures/mutated_server.py +96 -0
  186. mcp_warden_cli-1.0.0/tests/fixtures/overcap_server.py +178 -0
  187. mcp_warden_cli-1.0.0/tests/fixtures/poison_server.py +70 -0
  188. mcp_warden_cli-1.0.0/tests/fuzz/__init__.py +8 -0
  189. mcp_warden_cli-1.0.0/tests/fuzz/conftest.py +74 -0
  190. mcp_warden_cli-1.0.0/tests/fuzz/test_fuzz_ansi.py +188 -0
  191. mcp_warden_cli-1.0.0/tests/fuzz/test_fuzz_domain.py +186 -0
  192. mcp_warden_cli-1.0.0/tests/fuzz/test_fuzz_framing.py +393 -0
  193. mcp_warden_cli-1.0.0/tests/fuzz/test_fuzz_redact.py +153 -0
  194. mcp_warden_cli-1.0.0/tests/test_action_yml.py +138 -0
  195. mcp_warden_cli-1.0.0/tests/test_checks.py +180 -0
  196. mcp_warden_cli-1.0.0/tests/test_cli_version.py +61 -0
  197. mcp_warden_cli-1.0.0/tests/test_diff.py +249 -0
  198. mcp_warden_cli-1.0.0/tests/test_drift.py +254 -0
  199. mcp_warden_cli-1.0.0/tests/test_e2e_pin_check.py +121 -0
  200. mcp_warden_cli-1.0.0/tests/test_emitters.py +144 -0
  201. mcp_warden_cli-1.0.0/tests/test_framing.py +152 -0
  202. mcp_warden_cli-1.0.0/tests/test_guard_banner.py +337 -0
  203. mcp_warden_cli-1.0.0/tests/test_guard_platform.py +203 -0
  204. mcp_warden_cli-1.0.0/tests/test_guard_posture.py +155 -0
  205. mcp_warden_cli-1.0.0/tests/test_guard_proxy.py +228 -0
  206. mcp_warden_cli-1.0.0/tests/test_guard_strict.py +976 -0
  207. mcp_warden_cli-1.0.0/tests/test_guard_v3.py +430 -0
  208. mcp_warden_cli-1.0.0/tests/test_hashing.py +82 -0
  209. mcp_warden_cli-1.0.0/tests/test_inspect_parity.py +105 -0
  210. mcp_warden_cli-1.0.0/tests/test_inspection_policy.py +154 -0
  211. mcp_warden_cli-1.0.0/tests/test_lockfile.py +173 -0
  212. mcp_warden_cli-1.0.0/tests/test_policy.py +299 -0
  213. mcp_warden_cli-1.0.0/tests/test_precommit.py +386 -0
  214. mcp_warden_cli-1.0.0/tests/test_provenance.py +250 -0
  215. mcp_warden_cli-1.0.0/tests/test_result_inspection.py +243 -0
  216. mcp_warden_cli-1.0.0/tests/test_schema_diff.py +262 -0
  217. mcp_warden_cli-1.0.0/tests/test_schema_diff_refs.py +428 -0
  218. mcp_warden_cli-1.0.0/tests/test_signing.py +613 -0
  219. mcp_warden_cli-1.0.0/tests/test_spec_consistency.py +142 -0
  220. mcp_warden_cli-1.0.0/tests/test_tokenizer.py +61 -0
  221. mcp_warden_cli-1.0.0/tests/test_wire_block.py +61 -0
  222. mcp_warden_cli-1.0.0/tests/test_workflow_pins.py +111 -0
@@ -0,0 +1,75 @@
1
+ name: 🐛 Bug report
2
+ description: Report a defect in mcp-warden (NOT a security vulnerability)
3
+ labels: ["bug", "triage"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ ⚠️ **Do not report security vulnerabilities here.** If this is a way to
9
+ bypass a control mcp-warden claims to enforce (drift slips through, a real
10
+ secret is emitted unredacted, a poisoned result evades the block tier),
11
+ report it privately per [SECURITY.md](https://github.com/ernestprovo23/mcp-warden/blob/main/SECURITY.md).
12
+ - type: checkboxes
13
+ id: prechecks
14
+ attributes:
15
+ label: Pre-flight
16
+ options:
17
+ - label: This is a functional bug, not a security vulnerability.
18
+ required: true
19
+ - label: I searched existing issues and this is not a duplicate.
20
+ required: true
21
+ - label: I can reproduce this on the latest release or `main`.
22
+ required: true
23
+ - type: input
24
+ id: version
25
+ attributes:
26
+ label: mcp-warden version
27
+ description: Output of `mcp-warden --version`, or the commit SHA.
28
+ placeholder: "1.0.0"
29
+ validations:
30
+ required: true
31
+ - type: dropdown
32
+ id: command
33
+ attributes:
34
+ label: Which command?
35
+ options:
36
+ - pin
37
+ - check
38
+ - policy
39
+ - guard
40
+ - inspect
41
+ - other / not sure
42
+ validations:
43
+ required: true
44
+ - type: textarea
45
+ id: repro
46
+ attributes:
47
+ label: Reproduction
48
+ description: >
49
+ Exact command(s) and flags, plus a minimal MCP server fixture, `warden.lock`,
50
+ policy file, or `trace.jsonl` that reproduces it. **Strip or fake any real
51
+ secrets first.**
52
+ render: shell
53
+ validations:
54
+ required: true
55
+ - type: textarea
56
+ id: expected
57
+ attributes:
58
+ label: Expected behavior
59
+ validations:
60
+ required: true
61
+ - type: textarea
62
+ id: actual
63
+ attributes:
64
+ label: Actual behavior
65
+ description: Include the full output / exit code. Redact anything sensitive.
66
+ validations:
67
+ required: true
68
+ - type: textarea
69
+ id: env
70
+ attributes:
71
+ label: Environment
72
+ description: OS, Python version, how you installed (uv / pip), and how you run tests.
73
+ placeholder: "macOS 14 / Python 3.11.8 / uv / .venv"
74
+ validations:
75
+ required: false
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: false
2
+ contact_links:
3
+ - name: 🔒 Report a security vulnerability
4
+ url: https://github.com/ernestprovo23/mcp-warden/security/advisories/new
5
+ about: "Security issues must be reported privately — do NOT open a public issue. See SECURITY.md."
6
+ - name: 📖 Documentation & threat model
7
+ url: https://github.com/ernestprovo23/mcp-warden/tree/main/docs
8
+ about: "Read the design specs and threat model before filing — some behaviors are explicitly out of scope."
@@ -0,0 +1,52 @@
1
+ name: 💡 Feature / new check request
2
+ description: Propose a feature, or a new WRD-* / WRD-RES-* detection rule
3
+ labels: ["enhancement", "triage"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ New checks are very welcome. mcp-warden blocks **only on deterministic
9
+ signals** (~0 false positives); heuristic/fuzzy detectors are accepted only
10
+ in the monitor (log-only) tier. Frame your proposal around a concrete threat.
11
+ - type: textarea
12
+ id: threat
13
+ attributes:
14
+ label: Threat / problem
15
+ description: What attack or failure does this address? Where does it appear (MCP surface, tool-result shape, CLI workflow)?
16
+ validations:
17
+ required: true
18
+ - type: dropdown
19
+ id: kind
20
+ attributes:
21
+ label: What are you proposing?
22
+ options:
23
+ - New static check (WRD-* — pin/check time)
24
+ - New result-inspection rule (WRD-RES-* — guard/inspect time)
25
+ - CLI / workflow feature
26
+ - Other
27
+ validations:
28
+ required: true
29
+ - type: dropdown
30
+ id: tier
31
+ attributes:
32
+ label: For a new check — deterministic or fuzzy?
33
+ description: Deterministic = can block (near-zero false positives). Fuzzy = monitor/log-only.
34
+ options:
35
+ - Deterministic (block-capable)
36
+ - Fuzzy (monitor / log-only)
37
+ - N/A — not a check
38
+ validations:
39
+ required: false
40
+ - type: textarea
41
+ id: detection
42
+ attributes:
43
+ label: Proposed detection / behavior
44
+ description: How would it match deterministically? What severity? Any false-positive risk and how you'd anchor against it?
45
+ validations:
46
+ required: true
47
+ - type: textarea
48
+ id: alternatives
49
+ attributes:
50
+ label: Alternatives considered
51
+ validations:
52
+ required: false
@@ -0,0 +1,39 @@
1
+ <!--
2
+ Thanks for contributing to mcp-warden. mcp-warden is a security tool, so PRs are
3
+ held to a determinism + specs-in-sync bar. See CONTRIBUTING.md.
4
+ Do NOT use a PR to report a security vulnerability — follow SECURITY.md.
5
+ -->
6
+
7
+ ## What & why
8
+
9
+ <!-- What does this change do, and what problem does it solve? Link any issue. -->
10
+
11
+ Closes #
12
+
13
+ ## Type of change
14
+
15
+ - [ ] Bug fix (non-breaking)
16
+ - [ ] New feature / check (non-breaking)
17
+ - [ ] Breaking change (alters a hash, canonical form, rule verdict, or CLI contract)
18
+ - [ ] Docs / specs only
19
+ - [ ] CI / tooling
20
+
21
+ ## Checklist
22
+
23
+ - [ ] **Tests pass** via the repo venv: `.venv/bin/python -m pytest -q` is green.
24
+ - [ ] **Specs updated.** Any behavior change (hashing, canonicalization, the
25
+ `WRD-*` / `WRD-RES-*` catalogs, drift semantics, block posture, policy,
26
+ reserved error codes) updates the matching `docs/` spec in this same PR.
27
+ - [ ] **Determinism preserved.** No unintended change to a digest, canonical form,
28
+ or rule verdict on an unchanged surface. If a hash change is intentional, it
29
+ is documented and the version is bumped.
30
+ - [ ] **`guard` / `inspect` parity** holds for any result-rule change
31
+ (`tests/test_inspect_parity.py`).
32
+ - [ ] **No secrets.** No real credentials anywhere; test fixtures use obviously-fake
33
+ placeholders (already allowlisted in `.gitleaks.toml`).
34
+ - [ ] **Docs in sync.** README / CLI reference / `DOCUMENTATION_INDEX.md` updated if
35
+ user-facing behavior or flags changed.
36
+
37
+ ## Notes for reviewers
38
+
39
+ <!-- Anything you want a reviewer to look at first; fixture/spec diffs welcome. -->
@@ -0,0 +1,24 @@
1
+ version: 2
2
+ updates:
3
+ # Python dependencies declared in pyproject.toml.
4
+ - package-ecosystem: "pip"
5
+ directory: "/"
6
+ schedule:
7
+ interval: "weekly"
8
+ open-pull-requests-limit: 5
9
+ labels:
10
+ - "dependencies"
11
+ commit-message:
12
+ prefix: "deps"
13
+
14
+ # GitHub Actions used by the CI workflows.
15
+ - package-ecosystem: "github-actions"
16
+ directory: "/"
17
+ schedule:
18
+ interval: "weekly"
19
+ open-pull-requests-limit: 5
20
+ labels:
21
+ - "dependencies"
22
+ - "ci"
23
+ commit-message:
24
+ prefix: "ci"
@@ -0,0 +1,147 @@
1
+ name: Action self-test
2
+
3
+ # Validates the composite mcp-warden-action against the fixture MCP servers
4
+ # on all three supported runner OSes. Also runs a dedicated ubuntu job that
5
+ # exercises the real SARIF upload path (requires security-events: write).
6
+ #
7
+ # Runs on every push/PR that touches the action itself or its fixtures.
8
+
9
+ on:
10
+ push:
11
+ branches: [main]
12
+ paths:
13
+ - "action.yml"
14
+ - "action/**"
15
+ - "tests/fixtures/**"
16
+ - ".github/workflows/action-test.yml"
17
+ pull_request:
18
+ branches: [main]
19
+ paths:
20
+ - "action.yml"
21
+ - "action/**"
22
+ - "tests/fixtures/**"
23
+ - ".github/workflows/action-test.yml"
24
+
25
+ jobs:
26
+ # --------------------------------------------------------------------------
27
+ # Matrix job: pass path + blocking proof on ubuntu / macos / windows.
28
+ # upload-sarif: false — the matrix legs do not have security-events: write.
29
+ # --------------------------------------------------------------------------
30
+ action-matrix:
31
+ name: "Action test (${{ matrix.os }})"
32
+ runs-on: ${{ matrix.os }}
33
+ strategy:
34
+ fail-fast: false
35
+ matrix:
36
+ os: [ubuntu-latest, macos-latest, windows-latest]
37
+
38
+ steps:
39
+ - name: Checkout
40
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
41
+
42
+ # -----------------------------------------------------------------------
43
+ # Pass path: clean server vs committed lock — gate must exit 0.
44
+ # -----------------------------------------------------------------------
45
+ - name: "Pass path — clean server must exit 0"
46
+ id: pass-path
47
+ uses: ./
48
+ with:
49
+ server-cmd: "python tests/fixtures/clean_server.py"
50
+ lock: "tests/fixtures/clean.warden.lock"
51
+ sarif: "clean-check.sarif"
52
+ upload-sarif: "false"
53
+
54
+ - name: "Assert pass-path exit code is 0"
55
+ shell: bash
56
+ run: |
57
+ code="${{ steps.pass-path.outputs.exit-code }}"
58
+ if [ "$code" != "0" ]; then
59
+ echo "ERROR: pass path exit code was $code (expected 0)" >&2
60
+ exit 1
61
+ fi
62
+ echo "Pass path exited 0 — OK"
63
+
64
+ # -----------------------------------------------------------------------
65
+ # Blocking proof: mutated server vs same lock — gate must exit 1.
66
+ # continue-on-error: true so the job does not fail on the expected non-0.
67
+ # We then assert that the step outcome was 'failure' and exit-code == '1'.
68
+ # -----------------------------------------------------------------------
69
+ - name: "Blocking proof — mutated server must exit 1"
70
+ id: blocking-proof
71
+ uses: ./
72
+ continue-on-error: true
73
+ with:
74
+ server-cmd: "python tests/fixtures/mutated_server.py"
75
+ lock: "tests/fixtures/clean.warden.lock"
76
+ sarif: "mutated-check.sarif"
77
+ upload-sarif: "false"
78
+
79
+ - name: "Assert blocking-proof step failed with exit-code 1"
80
+ shell: bash
81
+ run: |
82
+ outcome="${{ steps.blocking-proof.outcome }}"
83
+ code="${{ steps.blocking-proof.outputs.exit-code }}"
84
+ if [ "$outcome" != "failure" ]; then
85
+ echo "ERROR: blocking-proof step outcome was '$outcome' (expected 'failure')" >&2
86
+ exit 1
87
+ fi
88
+ if [ "$code" != "1" ]; then
89
+ echo "ERROR: blocking-proof exit-code was '$code' (expected '1')" >&2
90
+ exit 1
91
+ fi
92
+ echo "Blocking proof step outcome=failure, exit-code=1 — gate is working correctly"
93
+
94
+ # --------------------------------------------------------------------------
95
+ # Dedicated upload job: ubuntu only, with security-events: write.
96
+ # Exercises the real SARIF upload path end-to-end against the clean fixture.
97
+ # --------------------------------------------------------------------------
98
+ action-upload-sarif:
99
+ name: "Action test (SARIF upload, ubuntu)"
100
+ runs-on: ubuntu-latest
101
+ permissions:
102
+ contents: read
103
+ security-events: write
104
+
105
+ steps:
106
+ - name: Checkout
107
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
108
+
109
+ - name: "Clean server — upload-sarif true (real upload path)"
110
+ id: upload-test
111
+ uses: ./
112
+ with:
113
+ server-cmd: "python tests/fixtures/clean_server.py"
114
+ lock: "tests/fixtures/clean.warden.lock"
115
+ sarif: "upload-test.sarif"
116
+ upload-sarif: "true"
117
+ category: "mcp-warden-action-test"
118
+
119
+ - name: "Assert upload-test exit code is 0"
120
+ shell: bash
121
+ run: |
122
+ code="${{ steps.upload-test.outputs.exit-code }}"
123
+ if [ "$code" != "0" ]; then
124
+ echo "ERROR: upload-test exit code was $code (expected 0)" >&2
125
+ exit 1
126
+ fi
127
+ echo "SARIF upload path exited 0 — OK"
128
+
129
+ - name: "Assert SARIF upload step succeeded"
130
+ shell: bash
131
+ env:
132
+ UPLOAD_OUTCOME: ${{ steps.upload-test.outputs['sarif-upload'] }}
133
+ run: |
134
+ # The composite action's sarif-upload step id is internal; we verify
135
+ # upload success by confirming the overall action step exited 0 (already
136
+ # asserted above) and that the SARIF file was produced and is non-empty.
137
+ sarif_path="${{ steps.upload-test.outputs.sarif }}"
138
+ if [ -z "$sarif_path" ] || [ ! -f "$sarif_path" ]; then
139
+ echo "ERROR: SARIF file not found at path '$sarif_path' — upload cannot have succeeded" >&2
140
+ exit 1
141
+ fi
142
+ sarif_size=$(wc -c < "$sarif_path")
143
+ if [ "$sarif_size" -eq 0 ]; then
144
+ echo "ERROR: SARIF file is empty — upload would have been rejected" >&2
145
+ exit 1
146
+ fi
147
+ echo "SARIF file present at $sarif_path (${sarif_size} bytes) and action exited 0 — upload confirmed OK"
@@ -0,0 +1,88 @@
1
+ name: deps-locked
2
+
3
+ # Proves mcp-warden "heals itself": its OWN dev/CI dependency closure installs
4
+ # reproducibly from a fully hash-pinned lockfile (requirements-dev.lock). A
5
+ # supply-chain integrity gate that ships unpinned transitive deps is
6
+ # indefensible — this job is the standing evidence that we don't (issue #14,
7
+ # conclave v1 must-do #4).
8
+ #
9
+ # What it asserts, in a CLEAN environment, on every push/PR:
10
+ # 1. `pip install --require-hashes` accepts the committed lockfile end-to-end.
11
+ # --require-hashes makes pip REFUSE any artifact whose sha256 is not pinned,
12
+ # so a drifted or tampered transitive dep fails the job here.
13
+ # 2. The lockfile is still in sync with pyproject.toml — we regenerate it with
14
+ # the documented `uv pip compile` command and fail if the committed file
15
+ # differs (catches "bumped pyproject, forgot to regenerate the lock").
16
+ # 3. The package + its runtime/dev closure import from the locked set.
17
+
18
+ on:
19
+ push:
20
+ branches: [main]
21
+ pull_request:
22
+ branches: [main]
23
+
24
+ permissions:
25
+ contents: read
26
+
27
+ jobs:
28
+ deps-locked:
29
+ name: Hash-locked dev/CI install
30
+ runs-on: ubuntu-latest
31
+
32
+ steps:
33
+ # Pinned to the same full-SHA actions the rest of CI uses (test_workflow_pins.py
34
+ # enforces 40-char SHA + version comment on every `uses:`). Bump majors
35
+ # deliberately, never float tags — this is the supply-chain tool's own CI.
36
+ - name: Checkout
37
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
38
+
39
+ - name: Set up Python 3.11
40
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
41
+ with:
42
+ python-version: "3.11"
43
+
44
+ # --------------------------------------------------------------------
45
+ # 1. Hash-verified install in a clean venv.
46
+ # --require-hashes makes pip reject ANY package whose artifact hash is
47
+ # not pinned in requirements-dev.lock, so transitive drift fails closed.
48
+ # --------------------------------------------------------------------
49
+ - name: Install dev/CI closure with --require-hashes
50
+ run: |
51
+ python -m venv /tmp/locked
52
+ /tmp/locked/bin/python -m pip install --upgrade pip
53
+ /tmp/locked/bin/python -m pip install --require-hashes -r requirements-dev.lock
54
+
55
+ # --------------------------------------------------------------------
56
+ # 2. Lockfile-in-sync check.
57
+ # Regenerate with the SAME documented command and fail if the committed
58
+ # lock drifted from pyproject.toml. Keeps the lock from silently rotting.
59
+ # --------------------------------------------------------------------
60
+ - name: Install uv (pinned)
61
+ run: python -m pip install "uv==0.6.16"
62
+
63
+ - name: Verify lockfile is in sync with pyproject.toml
64
+ run: |
65
+ uv pip compile --universal --generate-hashes --python-version 3.11 \
66
+ --extra dev pyproject.toml -o /tmp/requirements-dev.regenerated.lock
67
+ # Compare only the dependency body. The autogenerated header comment
68
+ # embeds the `-o` output path, which differs by construction (the CI
69
+ # run writes to /tmp), so we strip leading `#` comment lines before
70
+ # diffing. Pins, markers, and hashes are all in the body and are
71
+ # compared exactly.
72
+ if ! diff -u \
73
+ <(grep -v '^#' requirements-dev.lock) \
74
+ <(grep -v '^#' /tmp/requirements-dev.regenerated.lock); then
75
+ echo "::error::requirements-dev.lock is out of sync with pyproject.toml."
76
+ echo "Regenerate it (see SECURITY.md / CONTRIBUTING.md) and commit the result:"
77
+ echo " uv pip compile --universal --generate-hashes --python-version 3.11 --extra dev pyproject.toml -o requirements-dev.lock"
78
+ exit 1
79
+ fi
80
+ echo "requirements-dev.lock is in sync with pyproject.toml."
81
+
82
+ # --------------------------------------------------------------------
83
+ # 3. The locked closure actually works — import the package + key deps.
84
+ # --------------------------------------------------------------------
85
+ - name: Import package + locked closure
86
+ run: |
87
+ /tmp/locked/bin/python -m pip install --no-deps -e .
88
+ /tmp/locked/bin/python -c "import mcp_warden; from mcp_warden import cli; import mcp, rfc8785, pydantic, typer, rich, yaml, anyio, pytest, hypothesis; print('OK: mcp_warden + hash-locked dev/CI closure import clean')"
@@ -0,0 +1,81 @@
1
+ name: Docs
2
+
3
+ # Builds the mkdocs-material documentation site.
4
+ # - On every PR: `mkdocs build --strict` is the gate (no broken internal
5
+ # links, no warnings). It does NOT deploy.
6
+ # - On push to main: build, then deploy to GitHub Pages.
7
+ #
8
+ # All third-party actions are pinned to a full 40-char commit SHA with a version
9
+ # comment (enforced by tests/test_workflow_pins.py).
10
+
11
+ on:
12
+ push:
13
+ branches: [main]
14
+ pull_request:
15
+ branches: [main]
16
+
17
+ # Least-privilege by default; the deploy job widens scope locally.
18
+ permissions:
19
+ contents: read
20
+
21
+ concurrency:
22
+ group: docs-${{ github.ref }}
23
+ cancel-in-progress: false
24
+
25
+ jobs:
26
+ # --------------------------------------------------------------------------
27
+ # Job 1: strict build — the PR gate. Runs on PRs and on main.
28
+ # Fails the build on any broken internal link or mkdocs warning.
29
+ # --------------------------------------------------------------------------
30
+ build:
31
+ name: mkdocs build --strict
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - name: Checkout
35
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
36
+
37
+ - name: Set up Python 3.11
38
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
39
+ with:
40
+ python-version: "3.11"
41
+
42
+ - name: Install mkdocs-material
43
+ run: pip install "mkdocs-material==9.7.6"
44
+
45
+ - name: Build site (strict)
46
+ run: mkdocs build --strict --site-dir site
47
+
48
+ - name: Upload Pages artifact
49
+ # Only needed on main, where the deploy job consumes it. Harmless on PRs
50
+ # (artifact is just not deployed), and keeps the build job self-contained.
51
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
52
+ uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5
53
+ with:
54
+ path: site
55
+
56
+ # --------------------------------------------------------------------------
57
+ # Job 2: deploy to GitHub Pages — only on push to main.
58
+ #
59
+ # NOTE: this requires GitHub Pages to be enabled for the repo with the
60
+ # "GitHub Actions" source (Settings -> Pages). Until that one-time enable is
61
+ # done, this job will fail on main but the PR gate (job 1) is unaffected.
62
+ # --------------------------------------------------------------------------
63
+ deploy:
64
+ name: Deploy to GitHub Pages
65
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
66
+ needs: build
67
+ runs-on: ubuntu-latest
68
+ permissions:
69
+ contents: read
70
+ pages: write
71
+ id-token: write
72
+ environment:
73
+ name: github-pages
74
+ url: ${{ steps.deployment.outputs.page_url }}
75
+ steps:
76
+ - name: Configure Pages
77
+ uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6
78
+
79
+ - name: Deploy
80
+ id: deployment
81
+ uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5
@@ -0,0 +1,95 @@
1
+ name: Examples
2
+
3
+ # Keeps examples/ honest:
4
+ # 1. lint — YAML-lint every example workflow so a broken copy-paste template
5
+ # can never merge.
6
+ # 2. check — re-run `mcp-warden check` against each committed lock under
7
+ # examples/pinned-servers/ so the example locks stay green (a drifted
8
+ # upstream server or a stale lock fails this job).
9
+ #
10
+ # All third-party actions are pinned to a full 40-char commit SHA with a version
11
+ # comment (enforced by tests/test_workflow_pins.py).
12
+
13
+ on:
14
+ push:
15
+ branches: [main]
16
+ pull_request:
17
+ branches: [main]
18
+
19
+ jobs:
20
+ # --------------------------------------------------------------------------
21
+ # Job 1: YAML-lint the example workflows.
22
+ # --------------------------------------------------------------------------
23
+ lint:
24
+ name: YAML lint example workflows
25
+ runs-on: ubuntu-latest
26
+ steps:
27
+ - name: Checkout
28
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
29
+
30
+ - name: Set up Python 3.11
31
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
32
+ with:
33
+ python-version: "3.11"
34
+
35
+ - name: Install yamllint
36
+ run: pip install "yamllint==1.35.1"
37
+
38
+ # Lint the example workflow / CI / config YAML. The relaxed ruleset focuses
39
+ # on syntactic validity and basic hygiene rather than strict formatting,
40
+ # since these are copy-paste templates authored for readability.
41
+ - name: Lint example YAML
42
+ run: |
43
+ yamllint -d relaxed \
44
+ examples/github-actions \
45
+ examples/gitlab-ci \
46
+ examples/pre-commit
47
+
48
+ # --------------------------------------------------------------------------
49
+ # Job 2: re-check the committed example locks.
50
+ #
51
+ # Launches each real, openly-available server via its PINNED ref and verifies
52
+ # the committed warden.lock still matches the live surface. No paid creds, no
53
+ # secrets — every server is public.
54
+ # --------------------------------------------------------------------------
55
+ check-locks:
56
+ name: Re-check committed example locks
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - name: Checkout
60
+ uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
61
+
62
+ - name: Set up Python 3.11
63
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
64
+ with:
65
+ python-version: "3.11"
66
+
67
+ # Node provides npx for the @modelcontextprotocol/* servers.
68
+ - name: Set up Node 22
69
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
70
+ with:
71
+ node-version: "22"
72
+
73
+ - name: Install mcp-warden
74
+ run: pip install -e .
75
+
76
+ - name: "check: server-everything (npx, pinned @2026.1.26)"
77
+ run: |
78
+ mcp-warden check \
79
+ --lock examples/pinned-servers/server-everything/warden.lock \
80
+ --timeout 120 \
81
+ -- npx -y @modelcontextprotocol/server-everything@2026.1.26
82
+
83
+ - name: "check: server-memory (npx, pinned @2026.1.26)"
84
+ run: |
85
+ mcp-warden check \
86
+ --lock examples/pinned-servers/server-memory/warden.lock \
87
+ --timeout 120 \
88
+ -- npx -y @modelcontextprotocol/server-memory@2026.1.26
89
+
90
+ - name: "check: server-sequential-thinking (npx, pinned @2025.12.18)"
91
+ run: |
92
+ mcp-warden check \
93
+ --lock examples/pinned-servers/server-sequential-thinking/warden.lock \
94
+ --timeout 120 \
95
+ -- npx -y @modelcontextprotocol/server-sequential-thinking@2025.12.18