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.
- gaslight-0.1.0/.claude/scheduled_tasks.lock +1 -0
- gaslight-0.1.0/.gitignore +17 -0
- gaslight-0.1.0/.superpowers/sdd/.gitignore +1 -0
- gaslight-0.1.0/AGENTS.md +134 -0
- gaslight-0.1.0/BRAIN_BRIDGE.md +30 -0
- gaslight-0.1.0/LICENSE +190 -0
- gaslight-0.1.0/PKG-INFO +215 -0
- gaslight-0.1.0/README.md +197 -0
- gaslight-0.1.0/council/2026-08-16-harness-security-pivot.md +69 -0
- gaslight-0.1.0/docs/TESTING_STRATEGY.md +264 -0
- gaslight-0.1.0/docs/brain/AGENT_SECURITY_LANDSCAPE.md +59 -0
- gaslight-0.1.0/docs/brain/ATTACK_COVERAGE_MAP.md +100 -0
- gaslight-0.1.0/docs/brain/BRIDGE_BRIEF.md +31 -0
- gaslight-0.1.0/docs/brain/BUILD_PLAN.md +187 -0
- gaslight-0.1.0/docs/brain/CASE_STUDY_the01dev.md +31 -0
- gaslight-0.1.0/docs/brain/IAGO_HANDOFF.md +117 -0
- gaslight-0.1.0/docs/brain/LLM_BOUNDARY.md +28 -0
- gaslight-0.1.0/docs/brain/M2_DESIGN.md +59 -0
- gaslight-0.1.0/docs/brain/THREAT_MODEL.md +28 -0
- gaslight-0.1.0/docs/brain/TICKET_denial_of_wallet.md +93 -0
- gaslight-0.1.0/docs/brain/WHY_IAGO_EXISTS.md +16 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m2-tool-authz-probe.md +904 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m3-attack-suite.md +1372 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m4-baseline-disclosure.md +1332 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m5a-instruction-override.md +1233 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-17-m6-path-traversal.md +656 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-18-m7-ssrf-probe.md +657 -0
- gaslight-0.1.0/docs/superpowers/plans/2026-08-18-m8-code-execution.md +761 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-16-m2-harness-attribution-design.md +7 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m3-attack-suite-design.md +79 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m4-baseline-disclosure-design.md +81 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m5a-instruction-override-design.md +77 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-17-m6-path-traversal-design.md +71 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-18-m7-ssrf-probe-design.md +78 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-18-m8-code-execution-design.md +92 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-19-claim-integrity-design.md +87 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-19-description-aware-targeting-design.md +188 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-20-v1-attack-net-widening.md +104 -0
- gaslight-0.1.0/docs/superpowers/specs/2026-08-20-v1-static-surface-pass.md +204 -0
- gaslight-0.1.0/harness/.gitignore +2 -0
- gaslight-0.1.0/harness/README.md +46 -0
- gaslight-0.1.0/harness/hunt.Dockerfile +29 -0
- gaslight-0.1.0/harness/hunt.py +200 -0
- gaslight-0.1.0/harness/proxy.Dockerfile +18 -0
- gaslight-0.1.0/harness/runner.Dockerfile +28 -0
- gaslight-0.1.0/harness/targets.txt +55 -0
- gaslight-0.1.0/harness/validate.txt +3 -0
- gaslight-0.1.0/harness/validate1.txt +1 -0
- gaslight-0.1.0/harness/verify_pairs.py +35 -0
- gaslight-0.1.0/pyproject.toml +36 -0
- gaslight-0.1.0/src/gaslight/__init__.py +0 -0
- gaslight-0.1.0/src/gaslight/cli.py +551 -0
- gaslight-0.1.0/src/gaslight/core/__init__.py +0 -0
- gaslight-0.1.0/src/gaslight/core/attacks/__init__.py +0 -0
- gaslight-0.1.0/src/gaslight/core/attacks/argument_smuggling.py +150 -0
- gaslight-0.1.0/src/gaslight/core/attacks/base.py +100 -0
- gaslight-0.1.0/src/gaslight/core/attacks/baseline_disclosure.py +67 -0
- gaslight-0.1.0/src/gaslight/core/attacks/claim_integrity.py +306 -0
- gaslight-0.1.0/src/gaslight/core/attacks/code_execution.py +184 -0
- gaslight-0.1.0/src/gaslight/core/attacks/confused_deputy.py +159 -0
- gaslight-0.1.0/src/gaslight/core/attacks/denial_of_wallet.py +102 -0
- gaslight-0.1.0/src/gaslight/core/attacks/destructive_authz_probe.py +188 -0
- gaslight-0.1.0/src/gaslight/core/attacks/error_disclosure.py +236 -0
- gaslight-0.1.0/src/gaslight/core/attacks/injection_exfil.py +121 -0
- gaslight-0.1.0/src/gaslight/core/attacks/instruction_override.py +198 -0
- gaslight-0.1.0/src/gaslight/core/attacks/memory_poisoning.py +140 -0
- gaslight-0.1.0/src/gaslight/core/attacks/output_leakage.py +86 -0
- gaslight-0.1.0/src/gaslight/core/attacks/path_traversal.py +237 -0
- gaslight-0.1.0/src/gaslight/core/attacks/resource_exposure.py +75 -0
- gaslight-0.1.0/src/gaslight/core/attacks/ssrf_probe.py +121 -0
- gaslight-0.1.0/src/gaslight/core/attacks/tool_authz_probe.py +90 -0
- gaslight-0.1.0/src/gaslight/core/attacks/tool_metadata_poisoning.py +100 -0
- gaslight-0.1.0/src/gaslight/core/baseline.py +112 -0
- gaslight-0.1.0/src/gaslight/core/blast.py +203 -0
- gaslight-0.1.0/src/gaslight/core/canary.py +37 -0
- gaslight-0.1.0/src/gaslight/core/claims.py +161 -0
- gaslight-0.1.0/src/gaslight/core/doctor.py +121 -0
- gaslight-0.1.0/src/gaslight/core/education.py +91 -0
- gaslight-0.1.0/src/gaslight/core/harness.py +92 -0
- gaslight-0.1.0/src/gaslight/core/llm.py +472 -0
- gaslight-0.1.0/src/gaslight/core/llm_secret_hints.py +34 -0
- gaslight-0.1.0/src/gaslight/core/metrics.py +198 -0
- gaslight-0.1.0/src/gaslight/core/reporter.py +642 -0
- gaslight-0.1.0/src/gaslight/core/schema.py +614 -0
- gaslight-0.1.0/src/gaslight/core/scorer.py +110 -0
- gaslight-0.1.0/src/gaslight/core/secrets_scan.py +140 -0
- gaslight-0.1.0/src/gaslight/core/sink.py +154 -0
- gaslight-0.1.0/src/gaslight/core/surface.py +298 -0
- gaslight-0.1.0/src/gaslight/core/target.py +354 -0
- gaslight-0.1.0/src/gaslight/core/verdict.py +152 -0
- gaslight-0.1.0/tests/__init__.py +0 -0
- gaslight-0.1.0/tests/fixtures/.hardened-memory-agent-default.json +1 -0
- gaslight-0.1.0/tests/fixtures/.memory-agent-default.json +1 -0
- gaslight-0.1.0/tests/fixtures/address_only_server.py +36 -0
- gaslight-0.1.0/tests/fixtures/capped_list_server.py +24 -0
- gaslight-0.1.0/tests/fixtures/clean_resource_server.py +19 -0
- gaslight-0.1.0/tests/fixtures/confidential_data_server.py +32 -0
- gaslight-0.1.0/tests/fixtures/decoy_hint_destructive_server.py +29 -0
- gaslight-0.1.0/tests/fixtures/denylisted_code_exec_server.py +51 -0
- gaslight-0.1.0/tests/fixtures/description_only_destructive_server.py +25 -0
- gaslight-0.1.0/tests/fixtures/document_sharing_server.py +52 -0
- gaslight-0.1.0/tests/fixtures/exfil_only_server.py +42 -0
- gaslight-0.1.0/tests/fixtures/exposed_resource_server.py +27 -0
- gaslight-0.1.0/tests/fixtures/external_effect_claim_server.py +32 -0
- gaslight-0.1.0/tests/fixtures/gated_resource_server.py +22 -0
- gaslight-0.1.0/tests/fixtures/generic_error_server.py +25 -0
- gaslight-0.1.0/tests/fixtures/guarded_code_exec_server.py +26 -0
- gaslight-0.1.0/tests/fixtures/guarded_destructive_server.py +48 -0
- gaslight-0.1.0/tests/fixtures/guarded_fetch_server.py +38 -0
- gaslight-0.1.0/tests/fixtures/guarded_file_read_sandbox/hello.txt +1 -0
- gaslight-0.1.0/tests/fixtures/guarded_file_read_server.py +33 -0
- gaslight-0.1.0/tests/fixtures/hardened_memory_agent_server.py +59 -0
- gaslight-0.1.0/tests/fixtures/hardened_server.py +43 -0
- gaslight-0.1.0/tests/fixtures/honest_readonly_server.py +30 -0
- gaslight-0.1.0/tests/fixtures/honest_staging_server.py +33 -0
- gaslight-0.1.0/tests/fixtures/inert_field_server.py +23 -0
- gaslight-0.1.0/tests/fixtures/leaky_status_server.py +22 -0
- gaslight-0.1.0/tests/fixtures/lying_readonly_server.py +33 -0
- gaslight-0.1.0/tests/fixtures/lying_staging_server.py +35 -0
- gaslight-0.1.0/tests/fixtures/lying_staging_with_other_pending_server.py +34 -0
- gaslight-0.1.0/tests/fixtures/memory_agent_server.py +68 -0
- gaslight-0.1.0/tests/fixtures/metadata_leak_fetch_server.py +33 -0
- gaslight-0.1.0/tests/fixtures/multi_destructive_server.py +49 -0
- gaslight-0.1.0/tests/fixtures/naively_guarded_file_read_server.py +38 -0
- gaslight-0.1.0/tests/fixtures/named_only_resource_server.py +20 -0
- gaslight-0.1.0/tests/fixtures/negation_false_candidate_server.py +25 -0
- gaslight-0.1.0/tests/fixtures/noisy_channel_readonly_server.py +39 -0
- gaslight-0.1.0/tests/fixtures/not_found_text_file_read_server.py +24 -0
- gaslight-0.1.0/tests/fixtures/only_destructive_server.py +21 -0
- gaslight-0.1.0/tests/fixtures/path_guarded_destructive_server.py +32 -0
- gaslight-0.1.0/tests/fixtures/rag_server.py +56 -0
- gaslight-0.1.0/tests/fixtures/redacted_status_server.py +19 -0
- gaslight-0.1.0/tests/fixtures/redacting_confidential_data_server.py +30 -0
- gaslight-0.1.0/tests/fixtures/secret.txt +1 -0
- gaslight-0.1.0/tests/fixtures/secret_leak_code_exec_server.py +44 -0
- gaslight-0.1.0/tests/fixtures/secret_leak_error_server.py +28 -0
- gaslight-0.1.0/tests/fixtures/smuggled_network_server.py +29 -0
- gaslight-0.1.0/tests/fixtures/smuggled_path_server.py +32 -0
- gaslight-0.1.0/tests/fixtures/sql_code_execution_server.py +35 -0
- gaslight-0.1.0/tests/fixtures/tool_metadata_poisoned_server.py +52 -0
- gaslight-0.1.0/tests/fixtures/unbounded_list_server.py +25 -0
- gaslight-0.1.0/tests/fixtures/unguarded_code_exec_server.py +38 -0
- gaslight-0.1.0/tests/fixtures/unguarded_destructive_server.py +43 -0
- gaslight-0.1.0/tests/fixtures/unguarded_fetch_server.py +23 -0
- gaslight-0.1.0/tests/fixtures/unguarded_file_read_extra_required_field_server.py +34 -0
- gaslight-0.1.0/tests/fixtures/unguarded_file_read_sandbox/hello.txt +1 -0
- gaslight-0.1.0/tests/fixtures/unguarded_file_read_server.py +29 -0
- gaslight-0.1.0/tests/fixtures/unnamed_leaky_resource_server.py +20 -0
- gaslight-0.1.0/tests/fixtures/unverifiable_claim_server.py +28 -0
- gaslight-0.1.0/tests/fixtures/verbose_error_server.py +31 -0
- gaslight-0.1.0/tests/fixtures/vulnerable_server.py +58 -0
- gaslight-0.1.0/tests/fixtures/write_destructive_collision_server.py +35 -0
- gaslight-0.1.0/tests/fixtures/write_is_exfil_server.py +33 -0
- gaslight-0.1.0/tests/test_argument_smuggling.py +72 -0
- gaslight-0.1.0/tests/test_attack_isolation.py +72 -0
- gaslight-0.1.0/tests/test_baseline.py +81 -0
- gaslight-0.1.0/tests/test_baseline_disclosure.py +46 -0
- gaslight-0.1.0/tests/test_blast.py +92 -0
- gaslight-0.1.0/tests/test_canary.py +19 -0
- gaslight-0.1.0/tests/test_claim_integrity.py +161 -0
- gaslight-0.1.0/tests/test_claims.py +100 -0
- gaslight-0.1.0/tests/test_cli.py +244 -0
- gaslight-0.1.0/tests/test_code_execution.py +110 -0
- gaslight-0.1.0/tests/test_confused_deputy.py +68 -0
- gaslight-0.1.0/tests/test_denial_of_wallet.py +113 -0
- gaslight-0.1.0/tests/test_destructive_authz_probe.py +171 -0
- gaslight-0.1.0/tests/test_doctor.py +79 -0
- gaslight-0.1.0/tests/test_education.py +40 -0
- gaslight-0.1.0/tests/test_end_to_end.py +39 -0
- gaslight-0.1.0/tests/test_error_disclosure.py +119 -0
- gaslight-0.1.0/tests/test_injection_exfil_attempted.py +35 -0
- gaslight-0.1.0/tests/test_instruction_override.py +149 -0
- gaslight-0.1.0/tests/test_llm_provider.py +67 -0
- gaslight-0.1.0/tests/test_llm_scripted.py +168 -0
- gaslight-0.1.0/tests/test_llm_secret_hints.py +46 -0
- gaslight-0.1.0/tests/test_memory_poisoning.py +50 -0
- gaslight-0.1.0/tests/test_metrics.py +148 -0
- gaslight-0.1.0/tests/test_output_leakage.py +35 -0
- gaslight-0.1.0/tests/test_path_traversal.py +128 -0
- gaslight-0.1.0/tests/test_rag_poisoning.py +29 -0
- gaslight-0.1.0/tests/test_reporter.py +211 -0
- gaslight-0.1.0/tests/test_resource_exposure.py +88 -0
- gaslight-0.1.0/tests/test_schema.py +606 -0
- gaslight-0.1.0/tests/test_scorer.py +142 -0
- gaslight-0.1.0/tests/test_secrets_scan.py +125 -0
- gaslight-0.1.0/tests/test_sink.py +47 -0
- gaslight-0.1.0/tests/test_ssrf_probe.py +85 -0
- gaslight-0.1.0/tests/test_surface.py +346 -0
- gaslight-0.1.0/tests/test_target.py +162 -0
- gaslight-0.1.0/tests/test_target_resources.py +35 -0
- gaslight-0.1.0/tests/test_tool_authz_probe.py +60 -0
- gaslight-0.1.0/tests/test_tool_metadata_poisoning.py +37 -0
- gaslight-0.1.0/tests/test_verdict.py +123 -0
- gaslight-0.1.0/tests/test_widened_exfil_detection.py +32 -0
- 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
|
+
*
|
gaslight-0.1.0/AGENTS.md
ADDED
|
@@ -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.
|
gaslight-0.1.0/PKG-INFO
ADDED
|
@@ -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`.
|