stopgate 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 (37) hide show
  1. stopgate-0.1.0/LICENSE +21 -0
  2. stopgate-0.1.0/PKG-INFO +181 -0
  3. stopgate-0.1.0/README.md +163 -0
  4. stopgate-0.1.0/pyproject.toml +35 -0
  5. stopgate-0.1.0/setup.cfg +4 -0
  6. stopgate-0.1.0/src/stopgate/__init__.py +12 -0
  7. stopgate-0.1.0/src/stopgate/cli.py +711 -0
  8. stopgate-0.1.0/src/stopgate/core/__init__.py +2 -0
  9. stopgate-0.1.0/src/stopgate/core/action.py +196 -0
  10. stopgate-0.1.0/src/stopgate/core/detectors.py +117 -0
  11. stopgate-0.1.0/src/stopgate/core/patterns.py +164 -0
  12. stopgate-0.1.0/src/stopgate/core/taint.py +513 -0
  13. stopgate-0.1.0/src/stopgate/data/sample_session.jsonl +8 -0
  14. stopgate-0.1.0/src/stopgate/digest.py +210 -0
  15. stopgate-0.1.0/src/stopgate/engine.py +118 -0
  16. stopgate-0.1.0/src/stopgate/evalsuite.py +443 -0
  17. stopgate-0.1.0/src/stopgate/logparse.py +286 -0
  18. stopgate-0.1.0/src/stopgate/policy.py +482 -0
  19. stopgate-0.1.0/src/stopgate/session.py +260 -0
  20. stopgate-0.1.0/src/stopgate/supervisor.py +113 -0
  21. stopgate-0.1.0/src/stopgate.egg-info/PKG-INFO +181 -0
  22. stopgate-0.1.0/src/stopgate.egg-info/SOURCES.txt +35 -0
  23. stopgate-0.1.0/src/stopgate.egg-info/dependency_links.txt +1 -0
  24. stopgate-0.1.0/src/stopgate.egg-info/entry_points.txt +2 -0
  25. stopgate-0.1.0/src/stopgate.egg-info/top_level.txt +1 -0
  26. stopgate-0.1.0/tests/test_action.py +322 -0
  27. stopgate-0.1.0/tests/test_claude_code_transcript.py +78 -0
  28. stopgate-0.1.0/tests/test_cli.py +351 -0
  29. stopgate-0.1.0/tests/test_detectors.py +189 -0
  30. stopgate-0.1.0/tests/test_digest.py +183 -0
  31. stopgate-0.1.0/tests/test_engine.py +200 -0
  32. stopgate-0.1.0/tests/test_eval.py +60 -0
  33. stopgate-0.1.0/tests/test_live_gate.py +174 -0
  34. stopgate-0.1.0/tests/test_logparse.py +292 -0
  35. stopgate-0.1.0/tests/test_policy.py +356 -0
  36. stopgate-0.1.0/tests/test_supervisor.py +121 -0
  37. stopgate-0.1.0/tests/test_taint.py +309 -0
stopgate-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Rohan Kaila
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,181 @@
1
+ Metadata-Version: 2.4
2
+ Name: stopgate
3
+ Version: 0.1.0
4
+ Summary: Stop watching your agent. A local-first safety envelope that lets you run coding agents unattended.
5
+ Author: Rohan Kaila
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Robomba/stopgate
8
+ Project-URL: Source, https://github.com/Robomba/stopgate
9
+ Keywords: ai,agent,security,guardrail,claude,prompt-injection,taint,dataflow
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Security
13
+ Classifier: Environment :: Console
14
+ Requires-Python: >=3.9
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE
17
+ Dynamic: license-file
18
+
19
+ # Stopgate
20
+
21
+ [![CI](https://github.com/Robomba/stopgate/actions/workflows/ci.yml/badge.svg)](https://github.com/Robomba/stopgate/actions/workflows/ci.yml)
22
+  ·  MIT  ·  zero runtime deps  ·  runs entirely on your machine
23
+
24
+ ### Stop watching your agent.
25
+
26
+ You don't babysit your coding agent because it's dangerous. You babysit it because you can't tell the difference between it *reading a file* and it *reading your `.env` and POSTing it to an IP it found in a README.*
27
+
28
+ Stopgate can. So you can go do something else.
29
+
30
+ ```bash
31
+ pip install stopgate
32
+ stopgate report
33
+ ```
34
+
35
+ > The PyPI package is **`stopgate`** (plain `stopgate` is an unrelated project); the
36
+ > command is just `stopgate`. For the bleeding edge:
37
+ > `pip install "git+https://github.com/Robomba/stopgate.git"`.
38
+
39
+ No config. It reads the logs your agent already wrote and tells you what it's been doing.
40
+
41
+ ```
42
+ This session — 8 agent actions:
43
+
44
+ 1 file reads touched credentials (/home/dev/app/.env)
45
+ 3 network calls to 3 domains (docs.example.com, collect.evil.example, api.github.com)
46
+ 1 destructive commands (no confirmation asked)
47
+ 1 outbound payload carried a secret read earlier <- this is the one
48
+ 2 action(s) taken shortly after reading untrusted content
49
+ ```
50
+
51
+ **Free. MIT. Runs entirely on your machine. Makes zero network calls of its own.**
52
+
53
+ ---
54
+
55
+ ## Why it's different
56
+
57
+ Most guardrails you can `pip install` today match **keywords**. We published the benchmark showing that doesn't work: a bag-of-words classifier with no model at all scores **0.967** on the standard harm benchmark — and **0.493 (chance)** the moment the attacker stops using the obvious words. Keyword guardrails aren't detecting intent. They're detecting vocabulary. ([AICES paper](https://github.com/Robomba/ai-control-eval-suite) · [dataset](https://huggingface.co/datasets/Robomb/aices-minpair-control))
58
+
59
+ Stopgate watches **where data came from and where it's going.** It tracks which tool results are untrusted (web/email/file/MCP), taints the session when the agent reads them, and fingerprints every secret it sees so it can spot that secret leaving the machine — **even base64-encoded.** *"The agent read `evil.com`, then tried to POST your `.env`"* is not a wording problem. You can't rephrase your way past a hash comparison.
60
+
61
+ **This isn't a new idea, and I won't pretend it is.** Provenance/dataflow defenses for
62
+ agents already exist in research: DeepMind's [CaMeL](https://arxiv.org/abs/2503.18813),
63
+ [Invariant Labs](https://invariantlabs.ai/) (acquired into Snyk), Meta's
64
+ [LlamaFirewall](https://arxiv.org/abs/2505.03574). Stopgate's contribution is **not** the
65
+ concept — it's (1) a zero-config build you can install and run against your own Claude Code
66
+ sessions today, and (2) an **open, minimal-pair controlled benchmark for agent actions** that
67
+ measures the thing everyone hand-waves: how often a guardrail cries wolf. The benchmark is the
68
+ new part; the gate is an honest implementation of a known idea. And to be precise about *how* it
69
+ works: it's a **lexical** action layer (regex for `rm -rf`, `DROP TABLE`, `curl | bash`) **plus**
70
+ a **non-lexical** provenance layer — not "dataflow instead of keywords," but both.
71
+
72
+ ---
73
+
74
+ ## Turn it on (live gating)
75
+
76
+ Stopgate plugs into Claude Code as two hooks. **You need both.**
77
+
78
+ ```jsonc
79
+ // ~/.claude/settings.json
80
+ {
81
+ "hooks": {
82
+ "PreToolUse": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "stopgate hook" }] }],
83
+ "PostToolUse": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "stopgate watch" }] }]
84
+ }
85
+ }
86
+ ```
87
+
88
+ Why two? `PreToolUse` fires *before* a tool runs, so it never sees a **result** —
89
+ no result, no secret bytes, nothing to fingerprint. `stopgate watch` (PostToolUse)
90
+ is the only place a secret can actually be captured. **Without `watch`, Stopgate
91
+ can only judge one action at a time and cross-call exfiltration is not detected.**
92
+ With it, "read the `.env` at step 3, POST it to an unknown host at step 19" is
93
+ caught — the payload at step 19 looks innocent on its own.
94
+
95
+ ### Modes
96
+
97
+ | Mode | Behaviour | Use it when |
98
+ |---|---|---|
99
+ | `observe` | Scores and logs everything, **always allows**. Cannot stall an agent. | You're building trust, or the agent runs unattended and must never block. |
100
+ | `enforce` *(default)* | A hard-stop surfaces to you as an **ask**. Everything else auto-approves. | You're at the keyboard. |
101
+ | `enforce --headless` | A hard-stop **denies** instead of asking. | Nobody is there — an "ask" nobody answers is a hang, not a guardrail. |
102
+
103
+ Set with `--mode`, or `$STOPGATE_MODE`, or a `~/.stopgate-mode` file.
104
+
105
+ **Kill switch:** `echo observe > ~/.stopgate-mode` — instantly back to logging-only,
106
+ no restart, no config edit.
107
+
108
+ ### What it never does
109
+
110
+ Stopgate **never writes your secrets to disk.** Session state holds only rolling-hash
111
+ fingerprints and salted hashes — enough to recognise those bytes trying to leave,
112
+ not enough to reconstruct them. A stolen state file yields nothing. (State lives in
113
+ `~/.cache/stopgate/sessions`, mode `0600`, expires after 7 days.)
114
+
115
+ It also **fails open, on purpose**: if Stopgate itself errors, the tool call is
116
+ allowed and the error is logged. A broken guardrail must never brick the agent it
117
+ is watching. That is a deliberate trade-off, and it is the honest one to state:
118
+ **Stopgate is a safety net, not a guarantee.** It can miss things. Do not use it as
119
+ the only thing standing between an agent and something you cannot undo.
120
+
121
+ ## Our promises
122
+
123
+ These are commitments, not features. They're the reason you can trust a security tool you didn't write.
124
+
125
+ **1. We will never phone home.** Zero telemetry, zero analytics, no network calls of Stopgate's own — ever. A security tool that exfiltrates your data to prove nothing is exfiltrating your data is a joke. The code is MIT; verify it.
126
+
127
+ **2. We publish our false-alarm rate every release.** Not our catch rate — anyone can catch everything by blocking everything. The number that matters is **how often we interrupt you for nothing**, and we print it whether it's good or bad. I haven't found another installable agent guardrail that publishes its false-alarm rate on a controlled set — if you know one, tell me and I'll link it.
128
+
129
+ **3. Sixty seconds or we failed.** Install to first insight with no config file, no policy language, no account. If you have to *learn* Stopgate before it helps you, we built it wrong.
130
+
131
+ **4. Some things always stop for a human.** Money moving, production, anything irreversible — those wake you up no matter what your policy says. No "trust level" will ever override that. If a tool offers to fully automate spending your money, close the tab.
132
+
133
+ **5. We tell you what we can't do.** (See below — it stays in the README, permanently.)
134
+
135
+ **6. We'll never ship an attack to sell the defense.** Our demos use dummy canaries and local sinks. We don't publish weapons.
136
+
137
+ **7. Free, MIT, forever.** And the benchmark we grade ourselves with is public — run it against us, and against everyone else.
138
+
139
+ ---
140
+
141
+
142
+ ## ⚠ Disclaimer
143
+
144
+ **Stopgate is best-effort and will make mistakes.** It can miss real attacks and flag safe
145
+ actions. It is **not a guarantee of safety**, not a substitute for code review or OS
146
+ sandboxing, and is provided **AS IS with no warranty** (MIT). Benchmark numbers come from a
147
+ small, non-human-audited seed set and are indicative, not definitive. **You are responsible
148
+ for what your agent does.** Full text: [DISCLAIMER.md](DISCLAIMER.md).
149
+
150
+ ## What Stopgate does NOT catch
151
+
152
+ A security tool that overclaims is worse than none. Stopgate sees **actions, not thoughts.**
153
+
154
+ - **A genuinely malicious model with a covert channel.** If the model is the adversary and hides intent in benign-looking actions, Stopgate can't read its mind.
155
+ - **Anything outside the tool-call boundary.** If it doesn't go through a tool call Stopgate can see, Stopgate can't see it.
156
+ - **The "acted after untrusted content" signal is a temporal-proximity heuristic, not true taint.** We can't see which datum actually influenced the model, so we flag high-risk actions within N steps of an untrusted read — with confidence that **decays** with distance and is **evadable** by simply spacing the action out past the window.
157
+ - **Injection-provenance without secret egress.** A benign-*looking* action an agent runs because untrusted content told it to (no secret leaving) scores at **chance** in our own benchmark — Stopgate ties the keyword baseline there. Stopgate's real dataflow edge is secret-**egress**, not injection-provenance. We publish this miss (see `stopgate eval`).
158
+ - **Transformed exfil.** Byte-matching catches naive/base64/hex copies of a secret; gzip, encryption, or having the model paraphrase the secret defeat it. A competent adversary can get data out. It raises the cost; it is not a wall.
159
+ - **Anything not routed through the adapter** — a subprocess the agent spawns, network made from inside a tool's own code, or an MCP server talked to out-of-band — is invisible.
160
+ - **Closed chat UIs** (ChatGPT / Claude web). There's no interception point.
161
+ - **It is not a substitute for OS-level sandboxing.** Run untrusted agents in a container/VM. Stopgate is a layer on top, not a replacement.
162
+
163
+ Stopgate **reduces babysitting; it does not eliminate risk.**
164
+
165
+ ---
166
+
167
+ ## Status
168
+
169
+ **Shipped (local, verified):**
170
+ - `stopgate report` — read-only, zero-config: what your agent has been doing.
171
+ - `stopgate digest` — the session receipt: what was let through and *why it was safe*.
172
+ - `stopgate learn` — writes an editable allow-policy from your own sessions (opt-in tuning).
173
+ - `stopgate run` — unattended supervision: **auto-approve in-policy, hard-stop the irreversible.** Money, production, destructive, sign-in, install, and any secret leaving the machine always stop for a human — no policy can override that.
174
+ - `stopgate hook` — the live Claude Code PreToolUse gate (returns allow / ask per tool call).
175
+
176
+ **Next:** `stopgate eval` — the public precision benchmark (false alarms per 1,000 actions).
177
+
178
+
179
+ ## License
180
+
181
+ MIT. Local-first. No network calls of its own.
@@ -0,0 +1,163 @@
1
+ # Stopgate
2
+
3
+ [![CI](https://github.com/Robomba/stopgate/actions/workflows/ci.yml/badge.svg)](https://github.com/Robomba/stopgate/actions/workflows/ci.yml)
4
+ &nbsp;·&nbsp; MIT &nbsp;·&nbsp; zero runtime deps &nbsp;·&nbsp; runs entirely on your machine
5
+
6
+ ### Stop watching your agent.
7
+
8
+ You don't babysit your coding agent because it's dangerous. You babysit it because you can't tell the difference between it *reading a file* and it *reading your `.env` and POSTing it to an IP it found in a README.*
9
+
10
+ Stopgate can. So you can go do something else.
11
+
12
+ ```bash
13
+ pip install stopgate
14
+ stopgate report
15
+ ```
16
+
17
+ > The PyPI package is **`stopgate`** (plain `stopgate` is an unrelated project); the
18
+ > command is just `stopgate`. For the bleeding edge:
19
+ > `pip install "git+https://github.com/Robomba/stopgate.git"`.
20
+
21
+ No config. It reads the logs your agent already wrote and tells you what it's been doing.
22
+
23
+ ```
24
+ This session — 8 agent actions:
25
+
26
+ 1 file reads touched credentials (/home/dev/app/.env)
27
+ 3 network calls to 3 domains (docs.example.com, collect.evil.example, api.github.com)
28
+ 1 destructive commands (no confirmation asked)
29
+ 1 outbound payload carried a secret read earlier <- this is the one
30
+ 2 action(s) taken shortly after reading untrusted content
31
+ ```
32
+
33
+ **Free. MIT. Runs entirely on your machine. Makes zero network calls of its own.**
34
+
35
+ ---
36
+
37
+ ## Why it's different
38
+
39
+ Most guardrails you can `pip install` today match **keywords**. We published the benchmark showing that doesn't work: a bag-of-words classifier with no model at all scores **0.967** on the standard harm benchmark — and **0.493 (chance)** the moment the attacker stops using the obvious words. Keyword guardrails aren't detecting intent. They're detecting vocabulary. ([AICES paper](https://github.com/Robomba/ai-control-eval-suite) · [dataset](https://huggingface.co/datasets/Robomb/aices-minpair-control))
40
+
41
+ Stopgate watches **where data came from and where it's going.** It tracks which tool results are untrusted (web/email/file/MCP), taints the session when the agent reads them, and fingerprints every secret it sees so it can spot that secret leaving the machine — **even base64-encoded.** *"The agent read `evil.com`, then tried to POST your `.env`"* is not a wording problem. You can't rephrase your way past a hash comparison.
42
+
43
+ **This isn't a new idea, and I won't pretend it is.** Provenance/dataflow defenses for
44
+ agents already exist in research: DeepMind's [CaMeL](https://arxiv.org/abs/2503.18813),
45
+ [Invariant Labs](https://invariantlabs.ai/) (acquired into Snyk), Meta's
46
+ [LlamaFirewall](https://arxiv.org/abs/2505.03574). Stopgate's contribution is **not** the
47
+ concept — it's (1) a zero-config build you can install and run against your own Claude Code
48
+ sessions today, and (2) an **open, minimal-pair controlled benchmark for agent actions** that
49
+ measures the thing everyone hand-waves: how often a guardrail cries wolf. The benchmark is the
50
+ new part; the gate is an honest implementation of a known idea. And to be precise about *how* it
51
+ works: it's a **lexical** action layer (regex for `rm -rf`, `DROP TABLE`, `curl | bash`) **plus**
52
+ a **non-lexical** provenance layer — not "dataflow instead of keywords," but both.
53
+
54
+ ---
55
+
56
+ ## Turn it on (live gating)
57
+
58
+ Stopgate plugs into Claude Code as two hooks. **You need both.**
59
+
60
+ ```jsonc
61
+ // ~/.claude/settings.json
62
+ {
63
+ "hooks": {
64
+ "PreToolUse": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "stopgate hook" }] }],
65
+ "PostToolUse": [{ "matcher": "*", "hooks": [{ "type": "command", "command": "stopgate watch" }] }]
66
+ }
67
+ }
68
+ ```
69
+
70
+ Why two? `PreToolUse` fires *before* a tool runs, so it never sees a **result** —
71
+ no result, no secret bytes, nothing to fingerprint. `stopgate watch` (PostToolUse)
72
+ is the only place a secret can actually be captured. **Without `watch`, Stopgate
73
+ can only judge one action at a time and cross-call exfiltration is not detected.**
74
+ With it, "read the `.env` at step 3, POST it to an unknown host at step 19" is
75
+ caught — the payload at step 19 looks innocent on its own.
76
+
77
+ ### Modes
78
+
79
+ | Mode | Behaviour | Use it when |
80
+ |---|---|---|
81
+ | `observe` | Scores and logs everything, **always allows**. Cannot stall an agent. | You're building trust, or the agent runs unattended and must never block. |
82
+ | `enforce` *(default)* | A hard-stop surfaces to you as an **ask**. Everything else auto-approves. | You're at the keyboard. |
83
+ | `enforce --headless` | A hard-stop **denies** instead of asking. | Nobody is there — an "ask" nobody answers is a hang, not a guardrail. |
84
+
85
+ Set with `--mode`, or `$STOPGATE_MODE`, or a `~/.stopgate-mode` file.
86
+
87
+ **Kill switch:** `echo observe > ~/.stopgate-mode` — instantly back to logging-only,
88
+ no restart, no config edit.
89
+
90
+ ### What it never does
91
+
92
+ Stopgate **never writes your secrets to disk.** Session state holds only rolling-hash
93
+ fingerprints and salted hashes — enough to recognise those bytes trying to leave,
94
+ not enough to reconstruct them. A stolen state file yields nothing. (State lives in
95
+ `~/.cache/stopgate/sessions`, mode `0600`, expires after 7 days.)
96
+
97
+ It also **fails open, on purpose**: if Stopgate itself errors, the tool call is
98
+ allowed and the error is logged. A broken guardrail must never brick the agent it
99
+ is watching. That is a deliberate trade-off, and it is the honest one to state:
100
+ **Stopgate is a safety net, not a guarantee.** It can miss things. Do not use it as
101
+ the only thing standing between an agent and something you cannot undo.
102
+
103
+ ## Our promises
104
+
105
+ These are commitments, not features. They're the reason you can trust a security tool you didn't write.
106
+
107
+ **1. We will never phone home.** Zero telemetry, zero analytics, no network calls of Stopgate's own — ever. A security tool that exfiltrates your data to prove nothing is exfiltrating your data is a joke. The code is MIT; verify it.
108
+
109
+ **2. We publish our false-alarm rate every release.** Not our catch rate — anyone can catch everything by blocking everything. The number that matters is **how often we interrupt you for nothing**, and we print it whether it's good or bad. I haven't found another installable agent guardrail that publishes its false-alarm rate on a controlled set — if you know one, tell me and I'll link it.
110
+
111
+ **3. Sixty seconds or we failed.** Install to first insight with no config file, no policy language, no account. If you have to *learn* Stopgate before it helps you, we built it wrong.
112
+
113
+ **4. Some things always stop for a human.** Money moving, production, anything irreversible — those wake you up no matter what your policy says. No "trust level" will ever override that. If a tool offers to fully automate spending your money, close the tab.
114
+
115
+ **5. We tell you what we can't do.** (See below — it stays in the README, permanently.)
116
+
117
+ **6. We'll never ship an attack to sell the defense.** Our demos use dummy canaries and local sinks. We don't publish weapons.
118
+
119
+ **7. Free, MIT, forever.** And the benchmark we grade ourselves with is public — run it against us, and against everyone else.
120
+
121
+ ---
122
+
123
+
124
+ ## ⚠ Disclaimer
125
+
126
+ **Stopgate is best-effort and will make mistakes.** It can miss real attacks and flag safe
127
+ actions. It is **not a guarantee of safety**, not a substitute for code review or OS
128
+ sandboxing, and is provided **AS IS with no warranty** (MIT). Benchmark numbers come from a
129
+ small, non-human-audited seed set and are indicative, not definitive. **You are responsible
130
+ for what your agent does.** Full text: [DISCLAIMER.md](DISCLAIMER.md).
131
+
132
+ ## What Stopgate does NOT catch
133
+
134
+ A security tool that overclaims is worse than none. Stopgate sees **actions, not thoughts.**
135
+
136
+ - **A genuinely malicious model with a covert channel.** If the model is the adversary and hides intent in benign-looking actions, Stopgate can't read its mind.
137
+ - **Anything outside the tool-call boundary.** If it doesn't go through a tool call Stopgate can see, Stopgate can't see it.
138
+ - **The "acted after untrusted content" signal is a temporal-proximity heuristic, not true taint.** We can't see which datum actually influenced the model, so we flag high-risk actions within N steps of an untrusted read — with confidence that **decays** with distance and is **evadable** by simply spacing the action out past the window.
139
+ - **Injection-provenance without secret egress.** A benign-*looking* action an agent runs because untrusted content told it to (no secret leaving) scores at **chance** in our own benchmark — Stopgate ties the keyword baseline there. Stopgate's real dataflow edge is secret-**egress**, not injection-provenance. We publish this miss (see `stopgate eval`).
140
+ - **Transformed exfil.** Byte-matching catches naive/base64/hex copies of a secret; gzip, encryption, or having the model paraphrase the secret defeat it. A competent adversary can get data out. It raises the cost; it is not a wall.
141
+ - **Anything not routed through the adapter** — a subprocess the agent spawns, network made from inside a tool's own code, or an MCP server talked to out-of-band — is invisible.
142
+ - **Closed chat UIs** (ChatGPT / Claude web). There's no interception point.
143
+ - **It is not a substitute for OS-level sandboxing.** Run untrusted agents in a container/VM. Stopgate is a layer on top, not a replacement.
144
+
145
+ Stopgate **reduces babysitting; it does not eliminate risk.**
146
+
147
+ ---
148
+
149
+ ## Status
150
+
151
+ **Shipped (local, verified):**
152
+ - `stopgate report` — read-only, zero-config: what your agent has been doing.
153
+ - `stopgate digest` — the session receipt: what was let through and *why it was safe*.
154
+ - `stopgate learn` — writes an editable allow-policy from your own sessions (opt-in tuning).
155
+ - `stopgate run` — unattended supervision: **auto-approve in-policy, hard-stop the irreversible.** Money, production, destructive, sign-in, install, and any secret leaving the machine always stop for a human — no policy can override that.
156
+ - `stopgate hook` — the live Claude Code PreToolUse gate (returns allow / ask per tool call).
157
+
158
+ **Next:** `stopgate eval` — the public precision benchmark (false alarms per 1,000 actions).
159
+
160
+
161
+ ## License
162
+
163
+ MIT. Local-first. No network calls of its own.
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "stopgate"
7
+ version = "0.1.0"
8
+ description = "Stop watching your agent. A local-first safety envelope that lets you run coding agents unattended."
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Rohan Kaila" }]
13
+ keywords = ["ai", "agent", "security", "guardrail", "claude", "prompt-injection", "taint", "dataflow"]
14
+ classifiers = [
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Topic :: Security",
18
+ "Environment :: Console",
19
+ ]
20
+ # Deliberately ZERO runtime dependencies. Stopgate makes no network calls of its own
21
+ # and pulls in nothing that could. Standard library only. (Promise #1.)
22
+ dependencies = []
23
+
24
+ [project.urls]
25
+ Homepage = "https://github.com/Robomba/stopgate"
26
+ Source = "https://github.com/Robomba/stopgate"
27
+
28
+ [project.scripts]
29
+ stopgate = "stopgate.cli:main"
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
33
+
34
+ [tool.setuptools.package-data]
35
+ stopgate = ["data/*.jsonl"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,12 @@
1
+ """Stopgate — stop watching your agent.
2
+
3
+ A local-first safety envelope for coding agents. Detection is by PROVENANCE and
4
+ DATAFLOW, never keywords: every tool result is tagged trusted/untrusted, an
5
+ untrusted read taints the session, high-risk actions near untrusted content
6
+ escalate, and outbound bytes are matched (by rolling hash) against secrets read
7
+ earlier in the session.
8
+
9
+ Stopgate makes zero network calls of its own. Standard library only.
10
+ """
11
+
12
+ __version__ = "0.1.0"