gaslight 0.1.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 (195) hide show
  1. gaslight-0.1.0/.claude/scheduled_tasks.lock +1 -0
  2. gaslight-0.1.0/.gitignore +17 -0
  3. gaslight-0.1.0/.superpowers/sdd/.gitignore +1 -0
  4. gaslight-0.1.0/AGENTS.md +134 -0
  5. gaslight-0.1.0/BRAIN_BRIDGE.md +30 -0
  6. gaslight-0.1.0/LICENSE +190 -0
  7. gaslight-0.1.0/PKG-INFO +215 -0
  8. gaslight-0.1.0/README.md +197 -0
  9. gaslight-0.1.0/council/2026-08-16-harness-security-pivot.md +69 -0
  10. gaslight-0.1.0/docs/TESTING_STRATEGY.md +264 -0
  11. gaslight-0.1.0/docs/brain/AGENT_SECURITY_LANDSCAPE.md +59 -0
  12. gaslight-0.1.0/docs/brain/ATTACK_COVERAGE_MAP.md +100 -0
  13. gaslight-0.1.0/docs/brain/BRIDGE_BRIEF.md +31 -0
  14. gaslight-0.1.0/docs/brain/BUILD_PLAN.md +187 -0
  15. gaslight-0.1.0/docs/brain/CASE_STUDY_the01dev.md +31 -0
  16. gaslight-0.1.0/docs/brain/IAGO_HANDOFF.md +117 -0
  17. gaslight-0.1.0/docs/brain/LLM_BOUNDARY.md +28 -0
  18. gaslight-0.1.0/docs/brain/M2_DESIGN.md +59 -0
  19. gaslight-0.1.0/docs/brain/THREAT_MODEL.md +28 -0
  20. gaslight-0.1.0/docs/brain/TICKET_denial_of_wallet.md +93 -0
  21. gaslight-0.1.0/docs/brain/WHY_IAGO_EXISTS.md +16 -0
  22. gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m2-tool-authz-probe.md +904 -0
  23. gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m3-attack-suite.md +1372 -0
  24. gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m4-baseline-disclosure.md +1332 -0
  25. gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m5a-instruction-override.md +1233 -0
  26. gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m6-path-traversal.md +656 -0
  27. gaslight-0.1.0/docs/superpowers/plans/2026-08-18-m7-ssrf-probe.md +657 -0
  28. gaslight-0.1.0/docs/superpowers/plans/2026-08-18-m8-code-execution.md +761 -0
  29. gaslight-0.1.0/docs/superpowers/specs/2026-08-16-m2-harness-attribution-design.md +7 -0
  30. gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m3-attack-suite-design.md +79 -0
  31. gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m4-baseline-disclosure-design.md +81 -0
  32. gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m5a-instruction-override-design.md +77 -0
  33. gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m6-path-traversal-design.md +71 -0
  34. gaslight-0.1.0/docs/superpowers/specs/2026-08-18-m7-ssrf-probe-design.md +78 -0
  35. gaslight-0.1.0/docs/superpowers/specs/2026-08-18-m8-code-execution-design.md +92 -0
  36. gaslight-0.1.0/docs/superpowers/specs/2026-08-19-claim-integrity-design.md +87 -0
  37. gaslight-0.1.0/docs/superpowers/specs/2026-08-19-description-aware-targeting-design.md +188 -0
  38. gaslight-0.1.0/docs/superpowers/specs/2026-08-20-v1-attack-net-widening.md +104 -0
  39. gaslight-0.1.0/docs/superpowers/specs/2026-08-20-v1-static-surface-pass.md +204 -0
  40. gaslight-0.1.0/harness/.gitignore +2 -0
  41. gaslight-0.1.0/harness/README.md +46 -0
  42. gaslight-0.1.0/harness/hunt.Dockerfile +29 -0
  43. gaslight-0.1.0/harness/hunt.py +200 -0
  44. gaslight-0.1.0/harness/proxy.Dockerfile +18 -0
  45. gaslight-0.1.0/harness/runner.Dockerfile +28 -0
  46. gaslight-0.1.0/harness/targets.txt +55 -0
  47. gaslight-0.1.0/harness/validate.txt +3 -0
  48. gaslight-0.1.0/harness/validate1.txt +1 -0
  49. gaslight-0.1.0/harness/verify_pairs.py +35 -0
  50. gaslight-0.1.0/pyproject.toml +36 -0
  51. gaslight-0.1.0/src/gaslight/__init__.py +0 -0
  52. gaslight-0.1.0/src/gaslight/cli.py +551 -0
  53. gaslight-0.1.0/src/gaslight/core/__init__.py +0 -0
  54. gaslight-0.1.0/src/gaslight/core/attacks/__init__.py +0 -0
  55. gaslight-0.1.0/src/gaslight/core/attacks/argument_smuggling.py +150 -0
  56. gaslight-0.1.0/src/gaslight/core/attacks/base.py +100 -0
  57. gaslight-0.1.0/src/gaslight/core/attacks/baseline_disclosure.py +67 -0
  58. gaslight-0.1.0/src/gaslight/core/attacks/claim_integrity.py +306 -0
  59. gaslight-0.1.0/src/gaslight/core/attacks/code_execution.py +184 -0
  60. gaslight-0.1.0/src/gaslight/core/attacks/confused_deputy.py +159 -0
  61. gaslight-0.1.0/src/gaslight/core/attacks/denial_of_wallet.py +102 -0
  62. gaslight-0.1.0/src/gaslight/core/attacks/destructive_authz_probe.py +188 -0
  63. gaslight-0.1.0/src/gaslight/core/attacks/error_disclosure.py +236 -0
  64. gaslight-0.1.0/src/gaslight/core/attacks/injection_exfil.py +121 -0
  65. gaslight-0.1.0/src/gaslight/core/attacks/instruction_override.py +198 -0
  66. gaslight-0.1.0/src/gaslight/core/attacks/memory_poisoning.py +140 -0
  67. gaslight-0.1.0/src/gaslight/core/attacks/output_leakage.py +86 -0
  68. gaslight-0.1.0/src/gaslight/core/attacks/path_traversal.py +237 -0
  69. gaslight-0.1.0/src/gaslight/core/attacks/resource_exposure.py +75 -0
  70. gaslight-0.1.0/src/gaslight/core/attacks/ssrf_probe.py +121 -0
  71. gaslight-0.1.0/src/gaslight/core/attacks/tool_authz_probe.py +90 -0
  72. gaslight-0.1.0/src/gaslight/core/attacks/tool_metadata_poisoning.py +100 -0
  73. gaslight-0.1.0/src/gaslight/core/baseline.py +112 -0
  74. gaslight-0.1.0/src/gaslight/core/blast.py +203 -0
  75. gaslight-0.1.0/src/gaslight/core/canary.py +37 -0
  76. gaslight-0.1.0/src/gaslight/core/claims.py +161 -0
  77. gaslight-0.1.0/src/gaslight/core/doctor.py +121 -0
  78. gaslight-0.1.0/src/gaslight/core/education.py +91 -0
  79. gaslight-0.1.0/src/gaslight/core/harness.py +92 -0
  80. gaslight-0.1.0/src/gaslight/core/llm.py +472 -0
  81. gaslight-0.1.0/src/gaslight/core/llm_secret_hints.py +34 -0
  82. gaslight-0.1.0/src/gaslight/core/metrics.py +198 -0
  83. gaslight-0.1.0/src/gaslight/core/reporter.py +642 -0
  84. gaslight-0.1.0/src/gaslight/core/schema.py +614 -0
  85. gaslight-0.1.0/src/gaslight/core/scorer.py +110 -0
  86. gaslight-0.1.0/src/gaslight/core/secrets_scan.py +140 -0
  87. gaslight-0.1.0/src/gaslight/core/sink.py +154 -0
  88. gaslight-0.1.0/src/gaslight/core/surface.py +298 -0
  89. gaslight-0.1.0/src/gaslight/core/target.py +354 -0
  90. gaslight-0.1.0/src/gaslight/core/verdict.py +152 -0
  91. gaslight-0.1.0/tests/__init__.py +0 -0
  92. gaslight-0.1.0/tests/fixtures/.hardened-memory-agent-default.json +1 -0
  93. gaslight-0.1.0/tests/fixtures/.memory-agent-default.json +1 -0
  94. gaslight-0.1.0/tests/fixtures/address_only_server.py +36 -0
  95. gaslight-0.1.0/tests/fixtures/capped_list_server.py +24 -0
  96. gaslight-0.1.0/tests/fixtures/clean_resource_server.py +19 -0
  97. gaslight-0.1.0/tests/fixtures/confidential_data_server.py +32 -0
  98. gaslight-0.1.0/tests/fixtures/decoy_hint_destructive_server.py +29 -0
  99. gaslight-0.1.0/tests/fixtures/denylisted_code_exec_server.py +51 -0
  100. gaslight-0.1.0/tests/fixtures/description_only_destructive_server.py +25 -0
  101. gaslight-0.1.0/tests/fixtures/document_sharing_server.py +52 -0
  102. gaslight-0.1.0/tests/fixtures/exfil_only_server.py +42 -0
  103. gaslight-0.1.0/tests/fixtures/exposed_resource_server.py +27 -0
  104. gaslight-0.1.0/tests/fixtures/external_effect_claim_server.py +32 -0
  105. gaslight-0.1.0/tests/fixtures/gated_resource_server.py +22 -0
  106. gaslight-0.1.0/tests/fixtures/generic_error_server.py +25 -0
  107. gaslight-0.1.0/tests/fixtures/guarded_code_exec_server.py +26 -0
  108. gaslight-0.1.0/tests/fixtures/guarded_destructive_server.py +48 -0
  109. gaslight-0.1.0/tests/fixtures/guarded_fetch_server.py +38 -0
  110. gaslight-0.1.0/tests/fixtures/guarded_file_read_sandbox/hello.txt +1 -0
  111. gaslight-0.1.0/tests/fixtures/guarded_file_read_server.py +33 -0
  112. gaslight-0.1.0/tests/fixtures/hardened_memory_agent_server.py +59 -0
  113. gaslight-0.1.0/tests/fixtures/hardened_server.py +43 -0
  114. gaslight-0.1.0/tests/fixtures/honest_readonly_server.py +30 -0
  115. gaslight-0.1.0/tests/fixtures/honest_staging_server.py +33 -0
  116. gaslight-0.1.0/tests/fixtures/inert_field_server.py +23 -0
  117. gaslight-0.1.0/tests/fixtures/leaky_status_server.py +22 -0
  118. gaslight-0.1.0/tests/fixtures/lying_readonly_server.py +33 -0
  119. gaslight-0.1.0/tests/fixtures/lying_staging_server.py +35 -0
  120. gaslight-0.1.0/tests/fixtures/lying_staging_with_other_pending_server.py +34 -0
  121. gaslight-0.1.0/tests/fixtures/memory_agent_server.py +68 -0
  122. gaslight-0.1.0/tests/fixtures/metadata_leak_fetch_server.py +33 -0
  123. gaslight-0.1.0/tests/fixtures/multi_destructive_server.py +49 -0
  124. gaslight-0.1.0/tests/fixtures/naively_guarded_file_read_server.py +38 -0
  125. gaslight-0.1.0/tests/fixtures/named_only_resource_server.py +20 -0
  126. gaslight-0.1.0/tests/fixtures/negation_false_candidate_server.py +25 -0
  127. gaslight-0.1.0/tests/fixtures/noisy_channel_readonly_server.py +39 -0
  128. gaslight-0.1.0/tests/fixtures/not_found_text_file_read_server.py +24 -0
  129. gaslight-0.1.0/tests/fixtures/only_destructive_server.py +21 -0
  130. gaslight-0.1.0/tests/fixtures/path_guarded_destructive_server.py +32 -0
  131. gaslight-0.1.0/tests/fixtures/rag_server.py +56 -0
  132. gaslight-0.1.0/tests/fixtures/redacted_status_server.py +19 -0
  133. gaslight-0.1.0/tests/fixtures/redacting_confidential_data_server.py +30 -0
  134. gaslight-0.1.0/tests/fixtures/secret.txt +1 -0
  135. gaslight-0.1.0/tests/fixtures/secret_leak_code_exec_server.py +44 -0
  136. gaslight-0.1.0/tests/fixtures/secret_leak_error_server.py +28 -0
  137. gaslight-0.1.0/tests/fixtures/smuggled_network_server.py +29 -0
  138. gaslight-0.1.0/tests/fixtures/smuggled_path_server.py +32 -0
  139. gaslight-0.1.0/tests/fixtures/sql_code_execution_server.py +35 -0
  140. gaslight-0.1.0/tests/fixtures/tool_metadata_poisoned_server.py +52 -0
  141. gaslight-0.1.0/tests/fixtures/unbounded_list_server.py +25 -0
  142. gaslight-0.1.0/tests/fixtures/unguarded_code_exec_server.py +38 -0
  143. gaslight-0.1.0/tests/fixtures/unguarded_destructive_server.py +43 -0
  144. gaslight-0.1.0/tests/fixtures/unguarded_fetch_server.py +23 -0
  145. gaslight-0.1.0/tests/fixtures/unguarded_file_read_extra_required_field_server.py +34 -0
  146. gaslight-0.1.0/tests/fixtures/unguarded_file_read_sandbox/hello.txt +1 -0
  147. gaslight-0.1.0/tests/fixtures/unguarded_file_read_server.py +29 -0
  148. gaslight-0.1.0/tests/fixtures/unnamed_leaky_resource_server.py +20 -0
  149. gaslight-0.1.0/tests/fixtures/unverifiable_claim_server.py +28 -0
  150. gaslight-0.1.0/tests/fixtures/verbose_error_server.py +31 -0
  151. gaslight-0.1.0/tests/fixtures/vulnerable_server.py +58 -0
  152. gaslight-0.1.0/tests/fixtures/write_destructive_collision_server.py +35 -0
  153. gaslight-0.1.0/tests/fixtures/write_is_exfil_server.py +33 -0
  154. gaslight-0.1.0/tests/test_argument_smuggling.py +72 -0
  155. gaslight-0.1.0/tests/test_attack_isolation.py +72 -0
  156. gaslight-0.1.0/tests/test_baseline.py +81 -0
  157. gaslight-0.1.0/tests/test_baseline_disclosure.py +46 -0
  158. gaslight-0.1.0/tests/test_blast.py +92 -0
  159. gaslight-0.1.0/tests/test_canary.py +19 -0
  160. gaslight-0.1.0/tests/test_claim_integrity.py +161 -0
  161. gaslight-0.1.0/tests/test_claims.py +100 -0
  162. gaslight-0.1.0/tests/test_cli.py +244 -0
  163. gaslight-0.1.0/tests/test_code_execution.py +110 -0
  164. gaslight-0.1.0/tests/test_confused_deputy.py +68 -0
  165. gaslight-0.1.0/tests/test_denial_of_wallet.py +113 -0
  166. gaslight-0.1.0/tests/test_destructive_authz_probe.py +171 -0
  167. gaslight-0.1.0/tests/test_doctor.py +79 -0
  168. gaslight-0.1.0/tests/test_education.py +40 -0
  169. gaslight-0.1.0/tests/test_end_to_end.py +39 -0
  170. gaslight-0.1.0/tests/test_error_disclosure.py +119 -0
  171. gaslight-0.1.0/tests/test_injection_exfil_attempted.py +35 -0
  172. gaslight-0.1.0/tests/test_instruction_override.py +149 -0
  173. gaslight-0.1.0/tests/test_llm_provider.py +67 -0
  174. gaslight-0.1.0/tests/test_llm_scripted.py +168 -0
  175. gaslight-0.1.0/tests/test_llm_secret_hints.py +46 -0
  176. gaslight-0.1.0/tests/test_memory_poisoning.py +50 -0
  177. gaslight-0.1.0/tests/test_metrics.py +148 -0
  178. gaslight-0.1.0/tests/test_output_leakage.py +35 -0
  179. gaslight-0.1.0/tests/test_path_traversal.py +128 -0
  180. gaslight-0.1.0/tests/test_rag_poisoning.py +29 -0
  181. gaslight-0.1.0/tests/test_reporter.py +211 -0
  182. gaslight-0.1.0/tests/test_resource_exposure.py +88 -0
  183. gaslight-0.1.0/tests/test_schema.py +606 -0
  184. gaslight-0.1.0/tests/test_scorer.py +142 -0
  185. gaslight-0.1.0/tests/test_secrets_scan.py +125 -0
  186. gaslight-0.1.0/tests/test_sink.py +47 -0
  187. gaslight-0.1.0/tests/test_ssrf_probe.py +85 -0
  188. gaslight-0.1.0/tests/test_surface.py +346 -0
  189. gaslight-0.1.0/tests/test_target.py +162 -0
  190. gaslight-0.1.0/tests/test_target_resources.py +35 -0
  191. gaslight-0.1.0/tests/test_tool_authz_probe.py +60 -0
  192. gaslight-0.1.0/tests/test_tool_metadata_poisoning.py +37 -0
  193. gaslight-0.1.0/tests/test_verdict.py +123 -0
  194. gaslight-0.1.0/tests/test_widened_exfil_detection.py +32 -0
  195. gaslight-0.1.0/uv.lock +1352 -0
@@ -0,0 +1 @@
1
+ {"sessionId":"8d47fa29-5d99-44cb-a402-17ae8bf20f62","pid":4392,"procStart":"Thu Aug 20 01:01:16 2026","acquiredAt":1787197490766}
@@ -0,0 +1,17 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ dist/
8
+ build/
9
+ *.html
10
+ !tests/**/*.html
11
+ # Secrets and local env — never commit
12
+ .env
13
+ .env.*
14
+ logs/
15
+ # Local hunt-result artifacts — contain real local paths and leaked findings
16
+ # from real third-party servers. Never commit.
17
+ harness/hunt_results*.json
@@ -0,0 +1 @@
1
+ *
@@ -0,0 +1,134 @@
1
+ # Using gaslight from an AI agent
2
+
3
+ This file is written for an **AI coding assistant** (Claude Code, Cursor, etc.).
4
+ It tells you how to run `gaslight` correctly, how to read its output, and — most
5
+ importantly — why it is safe to run without worrying about breaking the user's
6
+ code. If a user says *"use gaslight to check my agent,"* follow this.
7
+
8
+ `gaslight` is a black-box security scanner for MCP-based AI agents. You point it
9
+ at a running MCP server; it attacks the tools it finds and returns a graded
10
+ report. Every finding it marks CONFIRMED is physically proven — never a guess.
11
+
12
+ ## TL;DR
13
+
14
+ ```
15
+ pip install gaslight
16
+ gaslight --json -- <command that launches the MCP server>
17
+ ```
18
+
19
+ Parse the JSON on stdout. `grade` is A–F. `findings[]` with `fired: true` are
20
+ real. Exit code `1` means at least one CONFIRMED issue, `0` means clean.
21
+
22
+ ## When to use it
23
+
24
+ - Before the user ships or publishes an MCP server or agent.
25
+ - In CI, to catch a tool that changed since it was approved (see `--baseline`).
26
+ - Whenever the user asks *"is my agent / MCP server secure?"*
27
+
28
+ ## How to run it
29
+
30
+ **Install:** `pip install gaslight` (or run without installing: `uvx gaslight`).
31
+
32
+ **Point it at a target:**
33
+ ```
34
+ gaslight -- npx -y some-mcp-server # a stdio MCP server
35
+ gaslight --url https://host/mcp # a remote HTTP+SSE server
36
+ gaslight --json -- python server.py # machine-readable — USE THIS to parse
37
+ ```
38
+
39
+ **Flags worth knowing:**
40
+ | Flag | Use |
41
+ |---|---|
42
+ | `--json` | Machine-readable report on **stdout** (all human text goes to stderr, so stdout is clean JSON). |
43
+ | `--safe` / `--no-safe` | `--safe` is the default. Keep it. |
44
+ | `--env KEY=VALUE` | Pass a **throwaway/test** credential if the server needs one to boot. Never a production secret. |
45
+ | `--baseline FILE` | CI rug-pull guard: records the tool set on first run, flags any tool that changed on later runs. |
46
+ | `--llm ollama` | Optional free local model for richer output. Never required; never decides a verdict. |
47
+ | `--skip k1,k2` | Skip named attacks (e.g. a raw-SQL tool wired to a real warehouse). |
48
+
49
+ ## What gaslight will NEVER do — the safety contract
50
+
51
+ You can run it without worrying about the user's system. On the default `--safe`
52
+ setting, gaslight:
53
+
54
+ - **Never reads the user's source code.** It is black-box — it only sees the
55
+ tools the server exposes over MCP, exactly like any other client.
56
+ - **Never performs a destructive or irreversible action.** Delete/reset-style
57
+ tools are probed for *authorization*, but the destructive call is not actually
58
+ made.
59
+ - **Aims its network probes at a dead local address it controls** (its own
60
+ listener), not at the internet or the user's infrastructure.
61
+ - **Needs no API key**, and with no model (or a local one) **sends nothing off
62
+ the machine**.
63
+ - **Only tests the one target you point it at.**
64
+
65
+ ## The ONE thing to be careful about
66
+
67
+ gaslight sends **real (but benign) attack payloads** to whatever target it is
68
+ pointed at. So:
69
+
70
+ - Point it at a **local / test / throwaway** instance — **never a production
71
+ backend**.
72
+ - If the server needs a credential, pass a **throwaway** one via `--env` — never
73
+ a production secret.
74
+ - Do not aim `--url` at a production endpoint.
75
+
76
+ If you are unsure whether a target is production, ask the user before running.
77
+
78
+ ## How to read the result
79
+
80
+ **Exit code:**
81
+ - `0` — clean: no CONFIRMED findings.
82
+ - `1` — at least one CONFIRMED finding. The agent has a proven security issue.
83
+ - `2` — the target could not be started or reached. gaslight prints a
84
+ plain-language reason (old SDK, needs a credential, wrong Node/Python, bad
85
+ command). This is not a security verdict — the target never ran.
86
+
87
+ **JSON shape (`--json`):**
88
+ ```json
89
+ {
90
+ "target": "…",
91
+ "tool_count": 6,
92
+ "grade": { "grade": "F", "fired_count": 2, "total_count": 17, "summary": "…" },
93
+ "findings":[ { "attack_key": "ssrf-probe", "fired": true, "attempted": true, "reason": "…" } ],
94
+ "metrics": { "average": 60, "scores": [ { "name": "Network", "score": 0, "band": "red", "breached": true } ] },
95
+ "surface": [ { "severity": "warn", "category": "unconstrained-field", "tool_name": "run_sql", "message": "…" } ],
96
+ "llm": { "active": false, "provider": "scripted", "role": "off", "decides_verdict": false }
97
+ }
98
+ ```
99
+
100
+ **What the fields mean:**
101
+ - `fired: true` → **CONFIRMED**. Physically proven — a token gaslight planted
102
+ reached its listener, or a protected file came back. Real. Report it and help
103
+ the user fix it.
104
+ - `attempted: false` → **NOT TESTED**. No tool of the shape this attack needs,
105
+ or nothing verifiable black-box. This is an honest gap, **not** a pass — don't
106
+ report it as "secure."
107
+ - `metrics.scores[].score` is 0–100 (or `null` when every check for that metric
108
+ was N/A). `breached: true` means a confirmed exploit capped that metric.
109
+ - `surface[]` are **static warnings** (schema hygiene) — `info`/`warn` only.
110
+ They never change the grade and are not CONFIRMED exploits. Surface them as
111
+ "worth reviewing," not as proven vulnerabilities.
112
+
113
+ ## The confidence model — why you can trust it
114
+
115
+ gaslight **never** marks something CONFIRMED on a guess or a model's opinion.
116
+ Every CONFIRMED is backed by physical proof. So:
117
+ - Trust a CONFIRMED — it really happened.
118
+ - Trust a clean gauge — those vectors were tested and nothing fired.
119
+ - A clean overall run means *"these attack vectors, tested, found nothing"* — a
120
+ floor, not a certificate. It is the first security check to run, not the last.
121
+
122
+ The optional LLM layer only makes probes smarter and explains results. It can
123
+ **never** decide whether an attack succeeded.
124
+
125
+ ## What gaslight does NOT cover — don't overclaim
126
+
127
+ It is a black-box behavioral scanner of one MCP target's runtime. Out of scope
128
+ **by design** (it cannot see these, and says so rather than faking a pass):
129
+ - Supply-chain / dependency tampering (a source/SCA concern).
130
+ - Internal audit-logging quality.
131
+ - Multi-agent / agent-to-agent attacks (on the roadmap).
132
+
133
+ When you report results, describe them as *"gaslight tested the running tools
134
+ and found X"* — not as a complete security audit.
@@ -0,0 +1,30 @@
1
+ # 🧠🌉 Brain ↔ Code Bridge (gaslight ⇄ LLM WIKI)
2
+ *How this code repo connects to the strategy brain. Read this first if you're Claude Code (or any builder) working in `gaslight`.*
3
+
4
+ ## The two halves
5
+ - **This repo `gaslight`** (working name for **Iago**) = the **CODE / implementation**.
6
+ - **The strategy brain** = a separate knowledge base at **`~/Documents/LLM WIKI/`**, specifically the Iago project folder:
7
+ **`~/Documents/LLM WIKI/verticals/career/projects/iago/`**
8
+ (You are on the same Mac — you can read that path directly, and it's always the freshest version.)
9
+
10
+ ## The rule (who is canonical)
11
+ - **Strategy, product decisions, threat model, positioning, "why", scope, launch → the WIKI is canonical.** Read it before making any product/design decision. When a decision changes, update it *there* (append-only), then reflect it in code here.
12
+ - **Implementation — code, tests, packaging → this REPO is canonical.**
13
+ - The `docs/brain/` folder in this repo holds **synced snapshots** of the key wiki docs so you have them locally/offline. **If a snapshot and the live wiki disagree, the WIKI wins** — re-read the live path above.
14
+
15
+ ## How to read (start order)
16
+ 1. **`docs/brain/IAGO_HANDOFF.md`** — the complete standalone build brief. **START HERE.**
17
+ 2. **`docs/brain/M2_DESIGN.md`** — the hard-won design decisions: how Iago connects (the two mechanisms: direct tool probe + MCP proxy), why it's generic ("Burp for agents" — challenge behavior, don't read the harness), the model-vs-code verdict, the tiered **connection inputs**, and the scope guardrails (**"paste a URL" is NOT the product**; NOT an "MCP tester"; why-not-DIY).
18
+ 3. **`docs/brain/BUILD_PLAN.md`** — the locked V1 spec (Python + `uvx`, MCP-native, deterministic canary, cuts, launch).
19
+ 4. **`docs/brain/THREAT_MODEL.md`** — what it secures, the attack classes, V1 scope.
20
+ 5. **`docs/brain/AGENT_SECURITY_LANDSCAPE.md`** — the field: top problems now/future + what's black-box testable vs. out of reach.
21
+ 6. **`docs/brain/WHY_IAGO_EXISTS.md`** — objection handling (auto-discovery; why not just DIY with an LLM).
22
+ 7. **`docs/brain/CASE_STUDY_the01dev.md`** — the first real-world target (Swanand's own product) + test plan.
23
+
24
+ ## The Council (for new features / product decisions — NOT code review)
25
+ Any new **feature or product decision** (changes UX / could become a business decision) → convene **The Council** at `~/Documents/LLM WIKI/council/THE_COUNCIL.md` before building. Run it as a single structured pass (not a heavy multi-agent workflow). **Save the session** to `~/Documents/LLM WIKI/council/sessions/` (or the iago folder) so it isn't lost. Code-quality review is a normal code review, NOT the Council.
26
+
27
+ ## Keeping in sync
28
+ - Product/design decision changes in code → write it back into the wiki (source of truth).
29
+ - Re-sync these `docs/brain/` snapshots from the wiki when they go stale (or just read the live wiki path — it's local).
30
+ - Working name is **gaslight**; final product name (Iago) is not locked — needs a PyPI/GitHub/domain + malware/threat-intel sweep first (Gaslight was killed for being live NK malware).
gaslight-0.1.0/LICENSE ADDED
@@ -0,0 +1,190 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the
44
+ purposes of this License, Derivative Works shall not include works
45
+ that remain separable from, or merely link (or bind by name) to the
46
+ interfaces of, the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including the
49
+ original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing
141
+ the origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ Copyright 2026 Swanand Kadam
179
+
180
+ Licensed under the Apache License, Version 2.0 (the "License");
181
+ you may not use this file except in compliance with the License.
182
+ You may obtain a copy of the License at
183
+
184
+ http://www.apache.org/licenses/LICENSE-2.0
185
+
186
+ Unless required by applicable law or agreed to in writing, software
187
+ distributed under the License is distributed on an "AS IS" BASIS,
188
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
189
+ See the License for the specific language governing permissions and
190
+ limitations under the License.
@@ -0,0 +1,215 @@
1
+ Metadata-Version: 2.5
2
+ Name: gaslight
3
+ Version: 0.1.0
4
+ Summary: A Lighthouse score for MCP agents: point it at your agent, get a graded security report — and everything it confirms, it proves.
5
+ Author: Swanand Kadam
6
+ License-Expression: Apache-2.0
7
+ License-File: LICENSE
8
+ Classifier: License :: OSI Approved :: Apache Software License
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Topic :: Security
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: anthropic>=0.68.0
13
+ Requires-Dist: jinja2>=3.1.0
14
+ Requires-Dist: mcp>=1.9.0
15
+ Requires-Dist: openai>=1.50.0
16
+ Requires-Dist: rich>=13.7.0
17
+ Description-Content-Type: text/markdown
18
+
19
+ # gaslight
20
+
21
+ > A Lighthouse score for MCP agents. Point it at your agent, get a graded security report — and everything it confirms, it proves.
22
+
23
+ gaslight is a black-box security tester for AI agents built on the
24
+ [Model Context Protocol](https://modelcontextprotocol.io). You point it at a
25
+ running MCP server; it connects like any other client, runs a suite of real
26
+ probes against the tools it finds, and hands you a graded, screenshot-ready
27
+ report. It never reads your source, your database, or an API key.
28
+
29
+ Think Lighthouse, but for agent security: five scores out of 100, a letter
30
+ grade, and a picture of how far a breach could travel — so you can see at a
31
+ glance whether your agent is solid or leaking, and exactly where.
32
+
33
+ The one thing that sets it apart from every "AI security" scanner that grades
34
+ one model's output with another model: **gaslight never trusts an opinion.**
35
+ A finding is only marked CONFIRMED when something physically happened — a unique
36
+ token you planted arrived at a listener gaslight controls, real out-of-bounds
37
+ data came back, or a call that should have been refused went through. If it says
38
+ confirmed, it's real. Go fix it.
39
+
40
+ ```
41
+ $ gaslight -- npx -y some-mcp-server
42
+
43
+ 🛡 These are safe probes, not real break-ins — testing your guards, not stealing your data.
44
+
45
+ 🧪 Network Egress Abuse (SSRF) — whether a URL tool can be aimed at addresses it should never reach
46
+ 🔥 CONFIRMED — fetch_url reached http://127.0.0.1:<sink> (your canary arrived). No destination check.
47
+ 🧪 Claim Integrity — whether a tool that promises to be read-only keeps that promise
48
+ 🔥 CONFIRMED — create_invoice says "stages for approval; does not issue",
49
+ but the record it created shows status "issued". Its own read tools contradict its own description.
50
+
51
+ Network 42 Filesystem 100 Leakage 88 Authorization 60 Integrity 55
52
+ Grade: F · blast radius: THIS MACHINE ▓ YOUR NETWORK ▓ DATA LEAVING ░
53
+ ```
54
+
55
+ ## Quick start
56
+
57
+ ```
58
+ pip install gaslight
59
+ gaslight -- npx -y your-mcp-server # point it at your agent
60
+ ```
61
+
62
+ That's it — no API key, no config. gaslight connects like any MCP client,
63
+ attacks the tools it finds, prints a graded report to your terminal, and writes
64
+ a shareable HTML report next to it. Add `--json` for machine-readable output, or
65
+ `--baseline tools.json` to catch a tool that changes on you in CI. What the
66
+ grades mean is under [How to read a report](#how-to-read-a-report); to drive it
67
+ from an AI assistant, see [AGENTS.md](AGENTS.md).
68
+
69
+ ## The score
70
+
71
+ Every finding rolls up into five gauges, each 0–100, plus one letter grade:
72
+
73
+ | Gauge | The question it answers |
74
+ |---|---|
75
+ | **Network** | Can the agent be steered into reaching out, or sending your data, over the wire? |
76
+ | **Filesystem** | Do file tools stay in their lane, or can they be walked out of scope? |
77
+ | **Leakage** | Do secrets, keys or tokens slip out during ordinary use? |
78
+ | **Authorization** | Are destructive, consequential or costly actions actually gated? |
79
+ | **Integrity** | Do the agent's instructions and its tools' own promises hold under pressure? |
80
+
81
+ A **breach never scores green** — a confirmed exploit caps the metric and drops
82
+ the grade. And the **blast radius** only lights up where an attack *physically*
83
+ succeeded: working guards keep the lit area small, so the picture rewards real
84
+ defense instead of just counting capabilities.
85
+
86
+ ## What it tests
87
+
88
+ Every agent, whatever its domain, is built on the same few primitives: tools
89
+ that move data out, read resources, take consequential actions, and make claims
90
+ about themselves. gaslight aims at the primitives, so the same tests apply to
91
+ a hospital agent and a bank agent alike.
92
+
93
+ **17 attack modules**, all deterministic, all proven physically — including
94
+ indirect prompt injection → exfiltration, SSRF, path traversal, code execution,
95
+ confused-deputy, tool-metadata poisoning, memory poisoning, destructive-action
96
+ authorization, verbose-error disclosure, **denial-of-wallet** (unbounded, costly
97
+ calls), and the headline: **claim integrity** — it takes the safety promise a
98
+ tool's description makes (the promise the driving model trusts) and checks
99
+ whether it's still true, using the target's own read tools as the verification
100
+ channel.
101
+
102
+ Plus a zero-call **static surface pass** (schema hygiene, hidden instructions in
103
+ descriptions, tool-shadowing / homoglyph names) that flags red flags without
104
+ firing a shot.
105
+
106
+ ### Coverage, mapped to a standard
107
+
108
+ gaslight is anchored to the **[OWASP MCP Top 10](https://owasp.org/www-project-mcp-top-10/)**,
109
+ not an ad-hoc list:
110
+
111
+ - **7 of 10 fully covered** — secret exposure, tool poisoning, command
112
+ injection, prompt injection, weak authorization, context over-sharing, and
113
+ shadow-servers/rug-pulls.
114
+ - **2 out of scope by design** — supply-chain/dependency tampering and internal
115
+ audit logging. A black-box behavioral tool can't see those, and says so rather
116
+ than faking a pass.
117
+ - **1 partial** — privilege scope-creep (stateful over time).
118
+
119
+ Stating what it *doesn't* test is the difference between an honest benchmark and
120
+ a scanner that over-credits itself.
121
+
122
+ ## The optional LLM layer
123
+
124
+ The whole deterministic core needs **no model and no key** — it works out of the
125
+ box. An LLM is an *optional lens* that makes probes smarter and the report
126
+ richer, and there is one hard rule:
127
+
128
+ > The LLM may aim an attack and explain a result. It may **never** decide whether
129
+ > the attack succeeded.
130
+
131
+ Every CONFIRMED still comes from a canary reaching our sink — never a model's
132
+ opinion. Turn it on with a key, or with `--llm ollama` for a **free local
133
+ model** (nothing leaves your machine — the right default for a security tool).
134
+ No model configured? You still get the full deterministic run. Every run states
135
+ plainly whether the LLM layer is on, off, and where its boundary is.
136
+
137
+ ## Extra modes
138
+
139
+ - **Doctor mode** — if the target won't start (built for an older SDK, needs a
140
+ credential, wrong Node/Python), gaslight reads its startup output and gives
141
+ you one plain sentence to fix it, instead of a wall of someone else's stack
142
+ trace.
143
+ - **Rug-pull guard** — `gaslight --baseline tools.json` records your tools on
144
+ first run and flags any that changed since (a description quietly rewritten
145
+ into a poisoned payload, a new dangerous parameter). Drop it in CI to catch a
146
+ tool that turns malicious *after* you approved it.
147
+
148
+ ## How to read a report
149
+
150
+ - **CONFIRMED** — physically proven. Real. Fix it.
151
+ - **not tested** — no tool of the shape this attack needs, or a claim with no
152
+ black-box way to verify it. Honest about what it couldn't reach, never
153
+ silently green.
154
+ - A clean run means *these attack vectors, tested, found nothing* — a floor, not
155
+ a certificate. It's the first security check to run on your agent, not the last.
156
+
157
+ ## Safety
158
+
159
+ Probes are harmless by construction: they only ever touch a sink gaslight
160
+ controls, an ordinary system file, or a synthetic canary record — never real
161
+ data. On the default `--safe`, an action with a real irreversible or external
162
+ effect is never triggered, and a soft, description-only signal never fires one.
163
+ When you point it at a target that needs a credential, use a **throwaway/test**
164
+ one via `--env KEY=VALUE` — never production.
165
+
166
+ ## Install
167
+
168
+ ```
169
+ pip install gaslight # (pre-launch)
170
+ gaslight --help
171
+ ```
172
+
173
+ Point it at any stdio MCP server:
174
+
175
+ ```
176
+ gaslight -- npx -y some-mcp-server
177
+ gaslight --url https://my-agent.example/mcp # remote (HTTP+SSE)
178
+ gaslight --json -- python my_server.py # machine-readable, for CI
179
+ ```
180
+
181
+ ## Use it from an AI agent (or CI)
182
+
183
+ gaslight is built to be driven by an AI assistant — just tell yours *"use
184
+ gaslight to check my agent."* It ships an **[AGENTS.md](AGENTS.md)** that tells
185
+ the AI how to run it, how to read the result, and — crucially — the safety
186
+ contract, so it can run without any worry about touching your code:
187
+
188
+ - `--json` emits a structured report on stdout (findings, grade, metrics); human
189
+ text goes to stderr, so stdout stays clean JSON to parse.
190
+ - **Exit codes:** `0` clean · `1` a CONFIRMED finding · `2` the target couldn't
191
+ start (with a plain-language reason).
192
+ - **The boundary:** black-box (never reads your source), `--safe` by default
193
+ (never fires a destructive action), probes aimed at a local sink it controls,
194
+ no API key, nothing leaves your machine. See `AGENTS.md` for the full contract.
195
+
196
+ ## Roadmap
197
+
198
+ v1 tests **MCP-based agents** — one target, through the MCP boundary. The next
199
+ frontier is the **agentic / multi-agent layer**: an adaptive red-team agent that
200
+ reasons about your agent and holds a real multi-turn conversation, plus
201
+ agent-to-agent (A2A) attacks between agents that talk to each other. The
202
+ physical-proof rule holds there too — the attacker gets smarter, the verdict
203
+ stays deterministic.
204
+
205
+ ## Status
206
+
207
+ Pre-launch. **17 attack modules**, validated against deliberately-vulnerable
208
+ benchmarks and 50+ real, independently-built community MCP servers, with matched
209
+ vulnerable/hardened fixtures and zero false positives on the controlled set. See
210
+ `docs/` for the design specs and `docs/TESTING_STRATEGY.md` for the validation
211
+ record.
212
+
213
+ ## License
214
+
215
+ Apache-2.0 — see `LICENSE`.