@sponsio/sdk 0.1.0-alpha.3 → 0.1.0
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.
- package/bin/sponsio.cjs +11 -0
- package/contracts/capability/credentials.yaml +8 -8
- package/contracts/capability/database.yaml +6 -6
- package/contracts/capability/filesystem-strict.yaml +4 -4
- package/contracts/capability/filesystem.yaml +9 -9
- package/contracts/capability/host-config-integrity.yaml +285 -0
- package/contracts/capability/self-modify.yaml +214 -9
- package/contracts/capability/shell.yaml +25 -32
- package/contracts/capability/subagent.yaml +5 -5
- package/contracts/core/llm_safety.yaml +23 -13
- package/contracts/incident/claude-code-secret-bypass.yaml +10 -11
- package/contracts/incident/cursor-railway-wipe.yaml +3 -3
- package/contracts/incident/mcp-composition.yaml +12 -12
- package/contracts/incident/openclaw.yaml +53 -45
- package/contracts/incident/subagent-escape.yaml +4 -4
- package/dist/cli/check.d.ts +2 -0
- package/dist/cli/check.d.ts.map +1 -0
- package/dist/cli/check.js +283 -0
- package/dist/cli/check.js.map +1 -0
- package/dist/cli/cli.d.ts +25 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +459 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/config.d.ts +88 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +243 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/demo.d.ts +12 -0
- package/dist/cli/demo.d.ts.map +1 -0
- package/dist/cli/demo.js +350 -0
- package/dist/cli/demo.js.map +1 -0
- package/dist/cli/doctor.d.ts +11 -0
- package/dist/cli/doctor.d.ts.map +1 -0
- package/dist/cli/doctor.js +201 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/eval.d.ts +2 -0
- package/dist/cli/eval.d.ts.map +1 -0
- package/dist/cli/eval.js +361 -0
- package/dist/cli/eval.js.map +1 -0
- package/dist/cli/explain.d.ts +2 -0
- package/dist/cli/explain.d.ts.map +1 -0
- package/dist/cli/explain.js +266 -0
- package/dist/cli/explain.js.map +1 -0
- package/dist/cli/export-sessions.d.ts +2 -0
- package/dist/cli/export-sessions.d.ts.map +1 -0
- package/dist/cli/export-sessions.js +182 -0
- package/dist/cli/export-sessions.js.map +1 -0
- package/dist/cli/export.d.ts +2 -0
- package/dist/cli/export.d.ts.map +1 -0
- package/dist/cli/export.js +222 -0
- package/dist/cli/export.js.map +1 -0
- package/dist/cli/extractors/common.d.ts +27 -0
- package/dist/cli/extractors/common.d.ts.map +1 -0
- package/dist/cli/extractors/common.js +107 -0
- package/dist/cli/extractors/common.js.map +1 -0
- package/dist/cli/extractors/generic.d.ts +37 -0
- package/dist/cli/extractors/generic.d.ts.map +1 -0
- package/dist/cli/extractors/generic.js +185 -0
- package/dist/cli/extractors/generic.js.map +1 -0
- package/dist/cli/extractors/langchain.d.ts +18 -0
- package/dist/cli/extractors/langchain.d.ts.map +1 -0
- package/dist/cli/extractors/langchain.js +86 -0
- package/dist/cli/extractors/langchain.js.map +1 -0
- package/dist/cli/extractors/vercel.d.ts +17 -0
- package/dist/cli/extractors/vercel.d.ts.map +1 -0
- package/dist/cli/extractors/vercel.js +46 -0
- package/dist/cli/extractors/vercel.js.map +1 -0
- package/dist/cli/index.d.ts +38 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +146 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +2 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +177 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/mode.d.ts +2 -0
- package/dist/cli/mode.d.ts.map +1 -0
- package/dist/cli/mode.js +71 -0
- package/dist/cli/mode.js.map +1 -0
- package/dist/cli/onboard.d.ts +88 -0
- package/dist/cli/onboard.d.ts.map +1 -0
- package/dist/cli/onboard.js +758 -0
- package/dist/cli/onboard.js.map +1 -0
- package/dist/cli/otlp.d.ts +27 -0
- package/dist/cli/otlp.d.ts.map +1 -0
- package/dist/cli/otlp.js +79 -0
- package/dist/cli/otlp.js.map +1 -0
- package/dist/cli/package.json +1 -0
- package/dist/cli/packs.d.ts +16 -0
- package/dist/cli/packs.d.ts.map +1 -0
- package/dist/cli/packs.js +184 -0
- package/dist/cli/packs.js.map +1 -0
- package/dist/cli/patterns.d.ts +15 -0
- package/dist/cli/patterns.d.ts.map +1 -0
- package/dist/cli/patterns.js +135 -0
- package/dist/cli/patterns.js.map +1 -0
- package/dist/cli/prompt.d.ts +2 -0
- package/dist/cli/prompt.d.ts.map +1 -0
- package/dist/cli/prompt.js +54 -0
- package/dist/cli/prompt.js.map +1 -0
- package/dist/cli/replay.d.ts +2 -0
- package/dist/cli/replay.d.ts.map +1 -0
- package/dist/cli/replay.js +196 -0
- package/dist/cli/replay.js.map +1 -0
- package/dist/cli/report.d.ts +57 -0
- package/dist/cli/report.d.ts.map +1 -0
- package/dist/cli/report.js +298 -0
- package/dist/cli/report.js.map +1 -0
- package/dist/cli/scan.d.ts +2 -0
- package/dist/cli/scan.d.ts.map +1 -0
- package/dist/cli/scan.js +172 -0
- package/dist/cli/scan.js.map +1 -0
- package/dist/cli/skill.d.ts +15 -0
- package/dist/cli/skill.d.ts.map +1 -0
- package/dist/cli/skill.js +131 -0
- package/dist/cli/skill.js.map +1 -0
- package/dist/cli/tokens.d.ts +31 -0
- package/dist/cli/tokens.d.ts.map +1 -0
- package/dist/cli/tokens.js +73 -0
- package/dist/cli/tokens.js.map +1 -0
- package/dist/cli/types.d.ts +46 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +3 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/cli/validate.d.ts +19 -0
- package/dist/cli/validate.d.ts.map +1 -0
- package/dist/cli/validate.js +205 -0
- package/dist/cli/validate.js.map +1 -0
- package/dist/cli/zod.d.ts +36 -0
- package/dist/cli/zod.d.ts.map +1 -0
- package/dist/cli/zod.js +226 -0
- package/dist/cli/zod.js.map +1 -0
- package/dist/contract.d.ts +13 -13
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +21 -21
- package/dist/contract.js.map +1 -1
- package/dist/core/config-loader.d.ts +1 -1
- package/dist/core/config-loader.js +35 -17
- package/dist/core/config-loader.js.map +1 -1
- package/dist/core/grounding.d.ts +49 -2
- package/dist/core/grounding.d.ts.map +1 -1
- package/dist/core/grounding.js +302 -142
- package/dist/core/grounding.js.map +1 -1
- package/dist/core/nl-parser.d.ts.map +1 -1
- package/dist/core/nl-parser.js +74 -2
- package/dist/core/nl-parser.js.map +1 -1
- package/dist/core/pattern-factory.d.ts +4 -4
- package/dist/core/pattern-factory.d.ts.map +1 -1
- package/dist/core/pattern-factory.js +46 -4
- package/dist/core/pattern-factory.js.map +1 -1
- package/dist/core/patterns.d.ts +78 -4
- package/dist/core/patterns.d.ts.map +1 -1
- package/dist/core/patterns.js +211 -3
- package/dist/core/patterns.js.map +1 -1
- package/dist/core/spans.d.ts +1 -1
- package/dist/core/spans.d.ts.map +1 -1
- package/dist/core/spans.js.map +1 -1
- package/dist/core/sto.d.ts +32 -62
- package/dist/core/sto.d.ts.map +1 -1
- package/dist/core/sto.js +32 -90
- package/dist/core/sto.js.map +1 -1
- package/dist/index.d.ts +77 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +172 -133
- package/dist/index.js.map +1 -1
- package/dist/integrations/openai-agents.d.ts.map +1 -1
- package/dist/integrations/openai-agents.js +5 -4
- package/dist/integrations/openai-agents.js.map +1 -1
- package/dist/render/tokens.d.ts.map +1 -1
- package/dist/render/tokens.js +1 -0
- package/dist/render/tokens.js.map +1 -1
- package/package.json +28 -4
- package/prompts/onboard.md +250 -0
- package/prompts/refresh.md +118 -0
- package/prompts/scan.md +125 -0
- package/skills/SKILL.md +502 -0
|
@@ -19,12 +19,42 @@
|
|
|
19
19
|
# time, but a sponsio-native rule is the right defense — it travels
|
|
20
20
|
# with the user's config to any host (Cursor, Codex, custom MCP).
|
|
21
21
|
#
|
|
22
|
+
# A second escalation vector lives one level up: an agent can
|
|
23
|
+
# ``import sponsio; print(sponsio.__file__)`` to locate the
|
|
24
|
+
# installed package, then edit the upstream capability bundle (or
|
|
25
|
+
# the evaluation engine itself) to delete the rule about to fire.
|
|
26
|
+
# This works on **any** user-writable Python install — editable
|
|
27
|
+
# (``pip install -e .``), ``pip install --user``, conda envs,
|
|
28
|
+
# venvs. Only system-wide ``/usr/lib/python*`` installs are safe
|
|
29
|
+
# by filesystem permission alone, and that's the minority of real
|
|
30
|
+
# deployments. This pack closes that vector.
|
|
31
|
+
#
|
|
22
32
|
# What this pack denies:
|
|
23
33
|
# - Edit / Write / MultiEdit on the legacy host guard config:
|
|
24
34
|
# ``~/.sponsio/plugins/_host/sponsio.yaml``
|
|
25
35
|
# - Edit / Write / MultiEdit on ANY per-plugin / per-MCP-server
|
|
26
36
|
# library (``~/.sponsio/plugins/<plugin-id>/sponsio.yaml``
|
|
27
37
|
# where ``<plugin-id>`` does NOT start with ``_host``).
|
|
38
|
+
# - Edit / Write / MultiEdit on the **upstream sponsio package** —
|
|
39
|
+
# specifically the contract bundles under
|
|
40
|
+
# ``sponsio/contracts/**/*.yaml`` and the evaluation-engine
|
|
41
|
+
# Python files (``guard_stdin``, ``config``, ``core``, plus
|
|
42
|
+
# anything under ``runtime/``, ``patterns/``, ``formulas/``,
|
|
43
|
+
# ``tracer/``, ``integrations/``). Without this, an agent can
|
|
44
|
+
# simply ``import sponsio; print(sponsio.__file__)`` to locate
|
|
45
|
+
# the package, then edit a capability bundle (or monkey-patch
|
|
46
|
+
# the loader) to delete the rule about to fire — bypassing the
|
|
47
|
+
# per-bucket protection above.
|
|
48
|
+
# - Bash write operators (``>``, ``>>``, ``tee``, ``sed -i``,
|
|
49
|
+
# ``cp/mv/rm/dd``) targeting any of the above paths — the
|
|
50
|
+
# "shell shortcut" bypass of the structured Edit/Write block.
|
|
51
|
+
# - Bash interpreter invocations (``python``, ``node``, ``ruby``,
|
|
52
|
+
# ``perl``, ``deno``, ``bun``, etc.) targeting any protected
|
|
53
|
+
# path — the "run a script that does the write" bypass.
|
|
54
|
+
# - Write / Edit content that creates a script which itself
|
|
55
|
+
# mutates a protected path — the "stage a file then invoke it"
|
|
56
|
+
# two-step bypass.
|
|
57
|
+
#
|
|
28
58
|
# The legitimate way to add or update these bundles is the
|
|
29
59
|
# ``sponsio plugin install`` / ``sponsio plugin scan --apply``
|
|
30
60
|
# CLI — those write via Python subprocess, not the agent's
|
|
@@ -34,6 +64,17 @@
|
|
|
34
64
|
# own Edit/Write tools to weaken or rewrite a bundle that's
|
|
35
65
|
# about to fire against it.
|
|
36
66
|
#
|
|
67
|
+
# **Sponsio dev exception**: contributors working on the sponsio
|
|
68
|
+
# package itself routinely edit these files. Override in your
|
|
69
|
+
# project-level config:
|
|
70
|
+
#
|
|
71
|
+
# customized:
|
|
72
|
+
# - match: {source: "library:tier1.self-modify"}
|
|
73
|
+
# disabled: true
|
|
74
|
+
#
|
|
75
|
+
# This loses self-modify protection inside the sponsio repo —
|
|
76
|
+
# acceptable for the maintainer workflow, not for end users.
|
|
77
|
+
#
|
|
37
78
|
# Per-host buckets (``_host_cursor`` / ``_host_claude_code`` / etc.)
|
|
38
79
|
# carry their own targeted self-modify rules INSIDE their starter
|
|
39
80
|
# yaml, scoped to that one bucket only. The split keeps the
|
|
@@ -56,6 +97,13 @@
|
|
|
56
97
|
# ``sponsio onboard`` writes into the user's repo). That file
|
|
57
98
|
# IS supposed to evolve — onboard / scan / refresh all rewrite
|
|
58
99
|
# it. Locking it would break the core happy path.
|
|
100
|
+
# - Edits to non-engine sponsio package files (``cli.py``,
|
|
101
|
+
# ``discovery/``, ``reporting/``, ``scoring/``, ``demos/``,
|
|
102
|
+
# ``generation/``, ``models/``). These don't sit on the hook
|
|
103
|
+
# evaluation hot path — modifying them can't disable a rule
|
|
104
|
+
# against the agent's NEXT call. Sponsio contributors edit
|
|
105
|
+
# them frequently; locking them would make the dev workflow
|
|
106
|
+
# unworkable.
|
|
59
107
|
# - Direct edits via the user's IDE, terminal, or
|
|
60
108
|
# ``sponsio plugin install`` / ``plugin scan --apply`` CLI —
|
|
61
109
|
# those don't go through the ``Edit`` / ``Write`` tool surface
|
|
@@ -82,11 +130,11 @@ agents:
|
|
|
82
130
|
contracts:
|
|
83
131
|
|
|
84
132
|
# =================================================================
|
|
85
|
-
# § 1 — No agent-mediated Edit of
|
|
133
|
+
# § 1 — No agent-mediated Edit of any sponsio config or engine
|
|
86
134
|
# =================================================================
|
|
87
135
|
|
|
88
|
-
- desc: "Host agent must not edit any sponsio guard config
|
|
89
|
-
|
|
136
|
+
- desc: "Host agent must not edit any sponsio guard config or engine file — use `sponsio plugin install` / `plugin scan --apply`, or hand-edit"
|
|
137
|
+
G:
|
|
90
138
|
pattern: arg_blacklist
|
|
91
139
|
args:
|
|
92
140
|
- Edit
|
|
@@ -101,10 +149,17 @@ agents:
|
|
|
101
149
|
# still manage downstream plugin policy.
|
|
102
150
|
- - "(^|/)\\.sponsio/plugins/_host/sponsio\\.yaml$"
|
|
103
151
|
- "(^|/)\\.sponsio/plugins/[^_/][^/]*/sponsio\\.yaml$"
|
|
152
|
+
# Upstream sponsio package — contract bundles (rule data)
|
|
153
|
+
# and evaluation-engine .py files. Anchored on
|
|
154
|
+
# ``(^|/)sponsio/...`` so it matches editable installs,
|
|
155
|
+
# site-packages, --user installs, conda/venv all the same.
|
|
156
|
+
- "(^|/)sponsio/contracts/[^/]+/[^/]+\\.yaml$"
|
|
157
|
+
- "(^|/)sponsio/(guard_stdin|config|core)\\.py$"
|
|
158
|
+
- "(^|/)sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py$"
|
|
104
159
|
source: "library:tier1.self-modify"
|
|
105
160
|
|
|
106
161
|
# =================================================================
|
|
107
|
-
# § 2 — No agent-mediated Write of
|
|
162
|
+
# § 2 — No agent-mediated Write of any sponsio config or engine
|
|
108
163
|
# =================================================================
|
|
109
164
|
#
|
|
110
165
|
# ``Write`` is the "create or overwrite whole file" tool —
|
|
@@ -112,28 +167,173 @@ agents:
|
|
|
112
167
|
# rules removed" workaround a pure ``Edit`` block would leave
|
|
113
168
|
# open.
|
|
114
169
|
|
|
115
|
-
- desc: "Host agent must not overwrite any sponsio guard config
|
|
116
|
-
|
|
170
|
+
- desc: "Host agent must not overwrite any sponsio guard config or engine file — use the CLI or hand-edit"
|
|
171
|
+
G:
|
|
117
172
|
pattern: arg_blacklist
|
|
118
173
|
args:
|
|
119
174
|
- Write
|
|
120
175
|
- file_path
|
|
121
176
|
- - "(^|/)\\.sponsio/plugins/_host/sponsio\\.yaml$"
|
|
122
177
|
- "(^|/)\\.sponsio/plugins/[^_/][^/]*/sponsio\\.yaml$"
|
|
178
|
+
- "(^|/)sponsio/contracts/[^/]+/[^/]+\\.yaml$"
|
|
179
|
+
- "(^|/)sponsio/(guard_stdin|config|core)\\.py$"
|
|
180
|
+
- "(^|/)sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py$"
|
|
123
181
|
source: "library:tier1.self-modify"
|
|
124
182
|
|
|
125
183
|
# =================================================================
|
|
126
|
-
# § 3 — No agent-mediated MultiEdit of
|
|
184
|
+
# § 3 — No agent-mediated MultiEdit of any sponsio config or engine
|
|
127
185
|
# =================================================================
|
|
128
186
|
|
|
129
|
-
- desc: "Host agent must not multi-edit any sponsio guard config
|
|
130
|
-
|
|
187
|
+
- desc: "Host agent must not multi-edit any sponsio guard config or engine file — use the CLI or hand-edit"
|
|
188
|
+
G:
|
|
131
189
|
pattern: arg_blacklist
|
|
132
190
|
args:
|
|
133
191
|
- MultiEdit
|
|
134
192
|
- file_path
|
|
135
193
|
- - "(^|/)\\.sponsio/plugins/_host/sponsio\\.yaml$"
|
|
136
194
|
- "(^|/)\\.sponsio/plugins/[^_/][^/]*/sponsio\\.yaml$"
|
|
195
|
+
- "(^|/)sponsio/contracts/[^/]+/[^/]+\\.yaml$"
|
|
196
|
+
- "(^|/)sponsio/(guard_stdin|config|core)\\.py$"
|
|
197
|
+
- "(^|/)sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py$"
|
|
198
|
+
source: "library:tier1.self-modify"
|
|
199
|
+
|
|
200
|
+
# =================================================================
|
|
201
|
+
# § 4 — No agent-mediated creation of a *script* that writes to
|
|
202
|
+
# a protected path (the "Python file I/O bypass")
|
|
203
|
+
# =================================================================
|
|
204
|
+
#
|
|
205
|
+
# Observed bypass: agent's ``Write`` to the host bucket gets denied
|
|
206
|
+
# by §1–§3, agent recovers by writing a small ``merge_host_*.py``
|
|
207
|
+
# script in the workspace whose content opens the host bucket
|
|
208
|
+
# path in write mode and mutates it. The script's file_path is a
|
|
209
|
+
# normal repo path so §1–§3 don't fire; the Bash invocation
|
|
210
|
+
# ``python merge.py`` doesn't carry the host bucket path on the
|
|
211
|
+
# command line so §6 below also doesn't fire. The signal IS
|
|
212
|
+
# present: the script's *content* mentions a protected path
|
|
213
|
+
# AND uses an open-for-write idiom.
|
|
214
|
+
#
|
|
215
|
+
# The lookahead form ``(?s)(?=.*PATH).*(WRITE_SHAPE)`` requires
|
|
216
|
+
# both signals in the same content blob — pure docs that mention
|
|
217
|
+
# the path stay editable; only files that mention the path AND
|
|
218
|
+
# carry write-shaped code are denied.
|
|
219
|
+
#
|
|
220
|
+
# The PATH alternation covers all four protected families:
|
|
221
|
+
# - host buckets (~/.sponsio/plugins/_host*/...)
|
|
222
|
+
# - per-plugin libs (~/.sponsio/plugins/<id>/...)
|
|
223
|
+
# - upstream contract bundles (sponsio/contracts/.../*.yaml)
|
|
224
|
+
# - upstream engine .py (sponsio/{guard_stdin,config,core}.py
|
|
225
|
+
# and sponsio/{runtime,patterns,formulas,tracer,
|
|
226
|
+
# integrations}/*.py)
|
|
227
|
+
#
|
|
228
|
+
# Tools covered: Write.content, Edit.new_string,
|
|
229
|
+
# MultiEdit.edits[*].new_string (the ``new_string`` projection
|
|
230
|
+
# that grounding extracts from MultiEdit's edit list).
|
|
231
|
+
|
|
232
|
+
- desc: "Host agent must not write a script that mutates a sponsio guard config or engine file — use `sponsio plugin append`/`install`"
|
|
233
|
+
G:
|
|
234
|
+
pattern: arg_blacklist
|
|
235
|
+
args:
|
|
236
|
+
- Write
|
|
237
|
+
- content
|
|
238
|
+
- - "(?s)(?=.*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)).*(\\.write_text\\s*\\(|\\.write_bytes\\s*\\(|\\bf\\.write\\s*\\(|\\bopen\\s*\\([^)]*['\\\"][aw][\\+bxt]*['\\\"]\\s*\\)|\\bfs\\.(writeFileSync|appendFileSync|createWriteStream|writeFile)\\s*\\(|\\bFile\\.(open|write)\\s*\\(|\\b(IO|File)\\.write\\b)"
|
|
239
|
+
source: "library:tier1.self-modify"
|
|
240
|
+
|
|
241
|
+
- desc: "Host agent must not edit a script that mutates a sponsio guard config or engine file — use `sponsio plugin append`/`install`"
|
|
242
|
+
G:
|
|
243
|
+
pattern: arg_blacklist
|
|
244
|
+
args:
|
|
245
|
+
- Edit
|
|
246
|
+
- new_string
|
|
247
|
+
- - "(?s)(?=.*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)).*(\\.write_text\\s*\\(|\\.write_bytes\\s*\\(|\\bf\\.write\\s*\\(|\\bopen\\s*\\([^)]*['\\\"][aw][\\+bxt]*['\\\"]\\s*\\)|\\bfs\\.(writeFileSync|appendFileSync|createWriteStream|writeFile)\\s*\\(|\\bFile\\.(open|write)\\s*\\(|\\b(IO|File)\\.write\\b)"
|
|
248
|
+
source: "library:tier1.self-modify"
|
|
249
|
+
|
|
250
|
+
# =================================================================
|
|
251
|
+
# § 5 — No interpreter invocation that targets a protected path
|
|
252
|
+
# =================================================================
|
|
253
|
+
#
|
|
254
|
+
# Catches the inline form (``python -c "...sponsio/contracts/..."``)
|
|
255
|
+
# and the path-as-argument form (``python merge.py
|
|
256
|
+
# ~/.sponsio/plugins/...sponsio.yaml``). Pairs with §4 — that
|
|
257
|
+
# rule blocks the *creation* of bypass scripts, this rule blocks
|
|
258
|
+
# the *invocation* path that doesn't go through a separate file.
|
|
259
|
+
#
|
|
260
|
+
# The interpreter list is the common scripting set; add new ones
|
|
261
|
+
# via a project-local ``customized:`` extending the regex if your
|
|
262
|
+
# environment uses a less common runtime. The trailing path
|
|
263
|
+
# regex is the same shape as §1–§3 / §6 so the privilege boundary
|
|
264
|
+
# stays consistent across tools.
|
|
265
|
+
#
|
|
266
|
+
# Legitimate sponsio CLIs that read the path
|
|
267
|
+
# (``sponsio validate --config <path>``, ``sponsio plugin
|
|
268
|
+
# show <name>``) are not blocked because the leading verb is
|
|
269
|
+
# ``sponsio``, not an interpreter alias. ``sponsio plugin
|
|
270
|
+
# append --target <plugin-id>`` doesn't pass the path at all —
|
|
271
|
+
# it takes the plugin id and resolves the path internally.
|
|
272
|
+
|
|
273
|
+
- desc: "Host agent must not run an interpreter against a sponsio guard config or engine file — use `sponsio plugin append`/`install`"
|
|
274
|
+
G:
|
|
275
|
+
pattern: arg_blacklist
|
|
276
|
+
args:
|
|
277
|
+
- Bash
|
|
278
|
+
- command
|
|
279
|
+
# ``[^|\n]*`` excludes pipe + newline so we don't match
|
|
280
|
+
# across pipelines, but keeps ``;`` permitted because
|
|
281
|
+
# Python's ``-c "..."`` payloads commonly use it as a
|
|
282
|
+
# statement separator (``python -c "import x; x.do()"``).
|
|
283
|
+
- - "\\b(python|python2|python3|node|deno|bun|ruby|perl|php|lua|tclsh|R|Rscript)\\b[^|\\n]*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)"
|
|
284
|
+
source: "library:tier1.self-modify"
|
|
285
|
+
|
|
286
|
+
# =================================================================
|
|
287
|
+
# § 6 — No Bash write operators against a protected path
|
|
288
|
+
# =================================================================
|
|
289
|
+
#
|
|
290
|
+
# The "shell shortcut" bypass: ``echo … > sponsio/contracts/…``,
|
|
291
|
+
# ``sed -i … sponsio/runtime/monitor.py``, ``cp /tmp/replacement
|
|
292
|
+
# sponsio/patterns/library.py``. These don't go through Edit /
|
|
293
|
+
# Write / MultiEdit so §1–§3 don't see them. Each operator
|
|
294
|
+
# gets one regex, applied against the same alternation of
|
|
295
|
+
# protected paths as §1–§3.
|
|
296
|
+
#
|
|
297
|
+
# Operator list: redirect (``>``, ``>>``), explicit writers
|
|
298
|
+
# (``tee``, ``sed -i``), file movers (``cp``, ``mv``, ``rm``,
|
|
299
|
+
# ``dd``). The ``[^|&;]*`` segment between operator and path
|
|
300
|
+
# keeps each match local to its own command (won't cross
|
|
301
|
+
# pipelines or statement separators).
|
|
302
|
+
|
|
303
|
+
- desc: "Host agent must not redirect Bash output (`>` / `>>`) into a sponsio guard config or engine file"
|
|
304
|
+
G:
|
|
305
|
+
pattern: arg_blacklist
|
|
306
|
+
args:
|
|
307
|
+
- Bash
|
|
308
|
+
- command
|
|
309
|
+
- - ">>?\\s*[^|&;]*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)"
|
|
310
|
+
source: "library:tier1.self-modify"
|
|
311
|
+
|
|
312
|
+
- desc: "Host agent must not `tee` into a sponsio guard config or engine file"
|
|
313
|
+
G:
|
|
314
|
+
pattern: arg_blacklist
|
|
315
|
+
args:
|
|
316
|
+
- Bash
|
|
317
|
+
- command
|
|
318
|
+
- - "\\btee\\b\\s+[^|&;]*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)"
|
|
319
|
+
source: "library:tier1.self-modify"
|
|
320
|
+
|
|
321
|
+
- desc: "Host agent must not `sed -i` a sponsio guard config or engine file"
|
|
322
|
+
G:
|
|
323
|
+
pattern: arg_blacklist
|
|
324
|
+
args:
|
|
325
|
+
- Bash
|
|
326
|
+
- command
|
|
327
|
+
- - "\\bsed\\b\\s+-i\\b[^|&;]*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)"
|
|
328
|
+
source: "library:tier1.self-modify"
|
|
329
|
+
|
|
330
|
+
- desc: "Host agent must not `cp` / `mv` / `rm` / `dd` against a sponsio guard config or engine file"
|
|
331
|
+
G:
|
|
332
|
+
pattern: arg_blacklist
|
|
333
|
+
args:
|
|
334
|
+
- Bash
|
|
335
|
+
- command
|
|
336
|
+
- - "\\b(cp|mv|rm|dd)\\b\\s+[^|&;]*(\\.sponsio/plugins/(_host[^/]*|[^_/][^/]*)/sponsio\\.yaml|sponsio/contracts/[^/]+/[^/]+\\.yaml|sponsio/(guard_stdin|config|core)\\.py|sponsio/(runtime|patterns|formulas|tracer|integrations)/[^/]+\\.py)"
|
|
137
337
|
source: "library:tier1.self-modify"
|
|
138
338
|
|
|
139
339
|
# -----------------------------------------------------------------------------
|
|
@@ -150,3 +350,8 @@ agents:
|
|
|
150
350
|
# trying to touch this same file is covered by the broader
|
|
151
351
|
# ``sponsio:incident/subagent-escape`` pack, which denies the
|
|
152
352
|
# ENTIRE ``~/.sponsio/`` tree to sub-agents.
|
|
353
|
+
#
|
|
354
|
+
# - Upstream package paths are matched WITHOUT the install prefix —
|
|
355
|
+
# ``(^|/)sponsio/contracts/...`` matches editable installs, site-
|
|
356
|
+
# packages, --user installs, conda/venv all the same. The first
|
|
357
|
+
# ``sponsio/`` directory boundary anchors the match cleanly.
|
|
@@ -52,7 +52,7 @@ agents:
|
|
|
52
52
|
# =================================================================
|
|
53
53
|
|
|
54
54
|
- desc: "Ban recursive deletes of sensitive roots"
|
|
55
|
-
|
|
55
|
+
G:
|
|
56
56
|
pattern: arg_blacklist
|
|
57
57
|
args:
|
|
58
58
|
- exec
|
|
@@ -72,7 +72,7 @@ agents:
|
|
|
72
72
|
source: "library:tier1.shell"
|
|
73
73
|
|
|
74
74
|
- desc: "Ban fork-bomb and obvious denial-of-service patterns"
|
|
75
|
-
|
|
75
|
+
G:
|
|
76
76
|
pattern: arg_blacklist
|
|
77
77
|
args:
|
|
78
78
|
- exec
|
|
@@ -88,7 +88,7 @@ agents:
|
|
|
88
88
|
source: "library:tier1.shell"
|
|
89
89
|
|
|
90
90
|
- desc: "Ban curl-to-shell and wget-to-shell (ClawHavoc ClickFix vector)"
|
|
91
|
-
|
|
91
|
+
G:
|
|
92
92
|
pattern: arg_blacklist
|
|
93
93
|
args:
|
|
94
94
|
- exec
|
|
@@ -100,7 +100,7 @@ agents:
|
|
|
100
100
|
source: "library:tier1.shell"
|
|
101
101
|
|
|
102
102
|
- desc: "Ban outbound reverse-shell / exfiltration primitives"
|
|
103
|
-
|
|
103
|
+
G:
|
|
104
104
|
pattern: arg_blacklist
|
|
105
105
|
args:
|
|
106
106
|
- exec
|
|
@@ -119,7 +119,7 @@ agents:
|
|
|
119
119
|
# a privilege-sensitive command token. Keeps the CVE coverage
|
|
120
120
|
# while eliminating the biggest day-1 false-positive source.
|
|
121
121
|
- desc: "Ban shell line-continuation chained into a privileged command (CVE-2026-28460)"
|
|
122
|
-
|
|
122
|
+
G:
|
|
123
123
|
pattern: arg_blacklist
|
|
124
124
|
args:
|
|
125
125
|
- exec
|
|
@@ -130,7 +130,7 @@ agents:
|
|
|
130
130
|
|
|
131
131
|
- desc: "Ban undefined-variable-looking patterns that expand to empty in shell"
|
|
132
132
|
# rm -rf {undefined}/{also_undefined} → rm -rf /
|
|
133
|
-
|
|
133
|
+
G:
|
|
134
134
|
pattern: arg_blacklist
|
|
135
135
|
args:
|
|
136
136
|
- exec
|
|
@@ -144,33 +144,26 @@ agents:
|
|
|
144
144
|
# =================================================================
|
|
145
145
|
|
|
146
146
|
- desc: "Reject exec commands with suspiciously long inline payloads (injection indicator)"
|
|
147
|
-
|
|
147
|
+
G:
|
|
148
148
|
pattern: arg_length_limit
|
|
149
149
|
args: [exec, command, 2000]
|
|
150
150
|
source: "library:tier1.shell"
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
#
|
|
159
|
-
#
|
|
160
|
-
#
|
|
161
|
-
#
|
|
162
|
-
#
|
|
163
|
-
#
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
# development workflows. The session-wide rate_limit(exec, 50)
|
|
168
|
-
# below remains the harder backstop.
|
|
169
|
-
- desc: "No more than 20 consecutive exec calls (runaway loop cap)"
|
|
170
|
-
E:
|
|
171
|
-
pattern: loop_detection
|
|
172
|
-
args: [exec, 20]
|
|
173
|
-
source: "library:tier1.shell"
|
|
152
|
+
# NOTE: Previously shipped two session-wide backstops here:
|
|
153
|
+
# 1. `rate_limit(exec, 50)` (later 200) — removed earlier; the
|
|
154
|
+
# cross-session trace store (24h TTL) made a "per-session"
|
|
155
|
+
# cap behave like a rolling 24h cap and false-positive
|
|
156
|
+
# heavy interactive work.
|
|
157
|
+
# 2. `loop_detection(exec, 20)` — also removed. Even at 20
|
|
158
|
+
# consecutive calls the rule false-positived routine
|
|
159
|
+
# coding-agent loops (build/lint/test/regen cycles can hit
|
|
160
|
+
# 20+ shell calls without any of them being destructive),
|
|
161
|
+
# and contributed nothing the targeted §1 arg_blacklists
|
|
162
|
+
# and §3/§4 confirm-gate didn't already cover. Runaway
|
|
163
|
+
# detection at this layer just generated noise without
|
|
164
|
+
# catching real attacks.
|
|
165
|
+
# When per-session trace isolation lands, we can revisit a
|
|
166
|
+
# tighter per-session loop cap that won't roll across sessions.
|
|
174
167
|
|
|
175
168
|
# =================================================================
|
|
176
169
|
# § 3 — Privileged commands require confirmation
|
|
@@ -182,7 +175,7 @@ agents:
|
|
|
182
175
|
# =================================================================
|
|
183
176
|
|
|
184
177
|
- desc: "Privileged exec patterns (sudo, chmod 777, dd if=) require preceding human confirmation"
|
|
185
|
-
|
|
178
|
+
G:
|
|
186
179
|
ltl: 'G(called_with(exec, "(sudo\\s|dd\\s+if=|chmod\\s+777|chown\\s+-R|mount\\s)") -> count(confirm_reconfirmed) >= count_with(exec, "(sudo\\s|dd\\s+if=|chmod\\s+777|chown\\s+-R|mount\\s)"))'
|
|
187
180
|
source: "library:tier1.shell"
|
|
188
181
|
|
|
@@ -221,7 +214,7 @@ agents:
|
|
|
221
214
|
|
|
222
215
|
- desc: "Each exec call needs its own confirm_reconfirmed (no confirmation reuse)"
|
|
223
216
|
A: "called `confirm_reconfirmed`"
|
|
224
|
-
|
|
217
|
+
G:
|
|
225
218
|
ltl: "G(called(exec) -> count(confirm_reconfirmed) >= count(exec))"
|
|
226
219
|
source: "library:tier1.shell"
|
|
227
220
|
|
|
@@ -242,5 +235,5 @@ agents:
|
|
|
242
235
|
# - The LTL contracts in §3 and §4 depend on the `ltl:` schema field
|
|
243
236
|
# being supported by the config parser. Until the LTL parser lands,
|
|
244
237
|
# these can be temporarily commented out; the arg_blacklist contracts
|
|
245
|
-
# in §1 and the
|
|
238
|
+
# in §1 and the arg_length_limit
|
|
246
239
|
# contracts in §2 work on current master.
|
|
@@ -82,7 +82,7 @@ agents:
|
|
|
82
82
|
# whether to commit.
|
|
83
83
|
|
|
84
84
|
- desc: "Sub-agents may not commit, push, force-push, or rewrite git history"
|
|
85
|
-
|
|
85
|
+
G:
|
|
86
86
|
pattern: arg_blacklist
|
|
87
87
|
args:
|
|
88
88
|
- exec
|
|
@@ -111,7 +111,7 @@ agents:
|
|
|
111
111
|
# sub-agents shouldn't decide unilaterally.
|
|
112
112
|
|
|
113
113
|
- desc: "Sub-agents may not install packages globally or system-wide"
|
|
114
|
-
|
|
114
|
+
G:
|
|
115
115
|
pattern: arg_blacklist
|
|
116
116
|
args:
|
|
117
117
|
- exec
|
|
@@ -136,7 +136,7 @@ agents:
|
|
|
136
136
|
# arbitrary host is appropriate.
|
|
137
137
|
|
|
138
138
|
- desc: "Sub-agents may not make outbound HTTP / shell-tunneled network calls"
|
|
139
|
-
|
|
139
|
+
G:
|
|
140
140
|
pattern: arg_blacklist
|
|
141
141
|
args:
|
|
142
142
|
- exec
|
|
@@ -158,7 +158,7 @@ agents:
|
|
|
158
158
|
# agent should do it with user visibility.
|
|
159
159
|
|
|
160
160
|
- desc: "Sub-agents may not write to system / user-home paths"
|
|
161
|
-
|
|
161
|
+
G:
|
|
162
162
|
pattern: arg_blacklist
|
|
163
163
|
args:
|
|
164
164
|
- write
|
|
@@ -171,7 +171,7 @@ agents:
|
|
|
171
171
|
source: "library:tier1.subagent"
|
|
172
172
|
|
|
173
173
|
- desc: "Sub-agents may not edit system / user-home paths"
|
|
174
|
-
|
|
174
|
+
G:
|
|
175
175
|
pattern: arg_blacklist
|
|
176
176
|
args:
|
|
177
177
|
- edit
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
# =============================================================================
|
|
2
2
|
# sponsio/contracts/core/llm_safety.yaml
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
4
|
+
# !! Sponsio Cloud only !! — this pack is composed entirely of LLM-judged
|
|
5
|
+
# stochastic atoms (`injection_free`, `jailbreak_free`, `harmful`,
|
|
6
|
+
# `toxic_free`, `semantic_pii_free`). The OSS engine ships no evaluator
|
|
7
|
+
# for them and will refuse to load this pack with a clear pointer to
|
|
8
|
+
# `pip install sponsio[cloud]`.
|
|
9
|
+
#
|
|
10
|
+
# It still ships in the OSS package so Cloud installs see the same on-disk
|
|
11
|
+
# layout — Cloud's StoEvaluator (auto-discovered via the
|
|
12
|
+
# `sponsio.evaluators` entry-point group) is what actually evaluates
|
|
13
|
+
# these contracts.
|
|
14
|
+
#
|
|
15
|
+
# Once Cloud is installed, opt in from your config:
|
|
6
16
|
#
|
|
7
17
|
# include:
|
|
8
18
|
# - sponsio:core/llm_safety
|
|
9
19
|
#
|
|
10
|
-
# Why opt-in: every contract here
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
14
|
-
#
|
|
15
|
-
#
|
|
20
|
+
# Why opt-in even on Cloud: every contract here triggers a judge LLM call
|
|
21
|
+
# on each evaluation. That's the right default for response-quality work
|
|
22
|
+
# but the wrong default for tool-call-only agents (no LLM responses to
|
|
23
|
+
# score → judge calls add latency without value). Splitting out of
|
|
24
|
+
# `core/universal` was the user-driven fix for "why is the SRE tool-call
|
|
25
|
+
# demo running prompt-injection scoring".
|
|
16
26
|
#
|
|
17
27
|
# Source tag convention for this file:
|
|
18
28
|
# library:tier0.<category> where category ∈
|
|
@@ -44,7 +54,7 @@ agents:
|
|
|
44
54
|
# 0.95 — prompt-injection slip-throughs cause downstream tool
|
|
45
55
|
# misuse with full agent privileges. High slip-through cost.
|
|
46
56
|
- desc: "Every LLM response must be free of prompt-injection compliance"
|
|
47
|
-
|
|
57
|
+
G:
|
|
48
58
|
pattern: injection_free
|
|
49
59
|
context_scope: full_trace
|
|
50
60
|
source: "library:tier0.adversarial"
|
|
@@ -53,7 +63,7 @@ agents:
|
|
|
53
63
|
# 0.90 — jailbreak compliance is bad but mostly self-contained
|
|
54
64
|
# (response-level harm, not tool-level harm).
|
|
55
65
|
- desc: "LLM must not comply with jailbreak attempts (DAN, roleplay, hypothetical bypass)"
|
|
56
|
-
|
|
66
|
+
G:
|
|
57
67
|
pattern: jailbreak_free
|
|
58
68
|
source: "library:tier0.adversarial"
|
|
59
69
|
beta: 0.9
|
|
@@ -63,7 +73,7 @@ agents:
|
|
|
63
73
|
# 0.95 — real-world-harm enablement (CSAM, weapons, self-harm
|
|
64
74
|
# methods) carries the same high slip-through cost as injection.
|
|
65
75
|
- desc: "Response must not encourage or enable real-world harm"
|
|
66
|
-
|
|
76
|
+
G:
|
|
67
77
|
pattern: harmful
|
|
68
78
|
source: "library:tier0.harm"
|
|
69
79
|
beta: 0.95
|
|
@@ -71,7 +81,7 @@ agents:
|
|
|
71
81
|
# 0.90 — toxic language is corrosive but not safety-critical;
|
|
72
82
|
# match the jailbreak weight rather than the harm weight.
|
|
73
83
|
- desc: "Response free of toxic / harassing language"
|
|
74
|
-
|
|
84
|
+
G:
|
|
75
85
|
pattern: toxic_free
|
|
76
86
|
source: "library:tier0.harm"
|
|
77
87
|
beta: 0.9
|
|
@@ -81,7 +91,7 @@ agents:
|
|
|
81
91
|
# 0.95 — PII slip-throughs are regulatory issues (GDPR / CCPA)
|
|
82
92
|
# not just trust issues. High slip-through cost.
|
|
83
93
|
- desc: "Response free of contextual PII (names tied to conditions, inferable identity)"
|
|
84
|
-
|
|
94
|
+
G:
|
|
85
95
|
pattern: semantic_pii_free
|
|
86
96
|
source: "library:tier0.privacy"
|
|
87
97
|
beta: 0.95
|
|
@@ -66,13 +66,12 @@ agents:
|
|
|
66
66
|
# § 1 — Trace-aware: secret-emitting commands followed by exfil-shape
|
|
67
67
|
# network call.
|
|
68
68
|
#
|
|
69
|
-
# Each rule uses the explicit A/
|
|
69
|
+
# Each rule uses the explicit A/G + ``activate_at: first_match`` form:
|
|
70
70
|
# the assumption A names the trigger event (e.g. `docker compose
|
|
71
71
|
# config`), and the enforcement E forbids the exfil shape from the
|
|
72
72
|
# *first* position where the trigger occurred. Events before
|
|
73
73
|
# activation are not subject to E — so a `curl` issued before any
|
|
74
|
-
# secret-emitting command is unaffected.
|
|
75
|
-
# ``docs/internal/contract-activate-at.md`` for the semantic.
|
|
74
|
+
# secret-emitting command is unaffected.
|
|
76
75
|
#
|
|
77
76
|
# We use `arg_field_has` (per-field regex) rather than `called_with`
|
|
78
77
|
# (full-args regex) to avoid (a) the `{'command': ...}` dict-wrapping
|
|
@@ -98,7 +97,7 @@ agents:
|
|
|
98
97
|
activate_at: first_match
|
|
99
98
|
A:
|
|
100
99
|
ltl: 'F(arg_field_has(Bash, command, "docker[ -]+compose[ -]+config\b|docker[ -]+config\b|docker[ -]+inspect\b"))'
|
|
101
|
-
|
|
100
|
+
G:
|
|
102
101
|
ltl: 'G(!arg_field_has(Bash, command, "(curl|wget|httpie|http)\b.*(?<!\S)(-d|--data[a-z-]*)(?!\S).*(@-(\s|$)|\$\([^)]*\)|`[^`]*`)"))'
|
|
103
102
|
source: "incident:claude-code-secret-bypass.docker_then_exfil"
|
|
104
103
|
|
|
@@ -106,7 +105,7 @@ agents:
|
|
|
106
105
|
activate_at: first_match
|
|
107
106
|
A:
|
|
108
107
|
ltl: 'F(arg_field_has(Bash, command, "\bop[ ]+run\b|\baws-vault\b|\bdirenv\b|\bdotenvx[ ]+run\b|\benvchain\b"))'
|
|
109
|
-
|
|
108
|
+
G:
|
|
110
109
|
ltl: 'G(!arg_field_has(Bash, command, "(curl|wget|httpie|http)\b.*(?<!\S)(-d|--data[a-z-]*)(?!\S).*(@-(\s|$)|\$\([^)]*\)|`[^`]*`)"))'
|
|
111
110
|
source: "incident:claude-code-secret-bypass.vault_then_exfil"
|
|
112
111
|
|
|
@@ -120,7 +119,7 @@ agents:
|
|
|
120
119
|
# `export -p` (always lists exports)
|
|
121
120
|
A:
|
|
122
121
|
ltl: 'F(arg_field_has(Bash, command, "(?<!\S)(printenv|export[ ]+-p)\b|(?<!\S)(env|set)(\s*$|\s*[|>])"))'
|
|
123
|
-
|
|
122
|
+
G:
|
|
124
123
|
ltl: 'G(!arg_field_has(Bash, command, "(curl|wget|httpie|http)\b.*(?<!\S)(-d|--data[a-z-]*)(?!\S).*(@-(\s|$)|\$\([^)]*\)|`[^`]*`)"))'
|
|
125
124
|
source: "incident:claude-code-secret-bypass.envdump_then_exfil"
|
|
126
125
|
|
|
@@ -128,7 +127,7 @@ agents:
|
|
|
128
127
|
activate_at: first_match
|
|
129
128
|
A:
|
|
130
129
|
ltl: 'F(arg_field_has(Bash, command, "git[ ]+(log|show|reflog)\b.*(-p\b|-G\b|--all\b)|git[ ]+grep\b"))'
|
|
131
|
-
|
|
130
|
+
G:
|
|
132
131
|
ltl: 'G(!arg_field_has(Bash, command, "(curl|wget|httpie|http)\b.*(?<!\S)(-d|--data[a-z-]*)(?!\S).*(@-(\s|$)|\$\([^)]*\)|`[^`]*`)"))'
|
|
133
132
|
source: "incident:claude-code-secret-bypass.githist_then_exfil"
|
|
134
133
|
|
|
@@ -138,7 +137,7 @@ agents:
|
|
|
138
137
|
# =====================================================================
|
|
139
138
|
|
|
140
139
|
- desc: "Reading /proc/<pid>/environ via Bash is the canonical env-leak path"
|
|
141
|
-
|
|
140
|
+
G:
|
|
142
141
|
pattern: arg_blacklist
|
|
143
142
|
args:
|
|
144
143
|
- Bash
|
|
@@ -147,7 +146,7 @@ agents:
|
|
|
147
146
|
source: "incident:claude-code-secret-bypass.proc_environ_bash"
|
|
148
147
|
|
|
149
148
|
- desc: "Reading /proc/<pid>/environ via the Read tool"
|
|
150
|
-
|
|
149
|
+
G:
|
|
151
150
|
pattern: arg_blacklist
|
|
152
151
|
args:
|
|
153
152
|
- Read
|
|
@@ -156,7 +155,7 @@ agents:
|
|
|
156
155
|
source: "incident:claude-code-secret-bypass.proc_environ_read"
|
|
157
156
|
|
|
158
157
|
- desc: "Bare exfil-shape POST: curl/wget with -d/--data carrying @- / \\$(...) / backtick"
|
|
159
|
-
|
|
158
|
+
G:
|
|
160
159
|
pattern: arg_blacklist
|
|
161
160
|
args:
|
|
162
161
|
- Bash
|
|
@@ -186,7 +185,7 @@ agents:
|
|
|
186
185
|
# - Hosts: the egress regex is host-agnostic. Operators wanting
|
|
187
186
|
# a positive allowlist (`api.openai.com`, `*.amazonaws.com`)
|
|
188
187
|
# should add an `customized:` rule that further requires the
|
|
189
|
-
# URL argument to be off-allowlist. See `docs/contracts.md`
|
|
188
|
+
# URL argument to be off-allowlist. See `docs/concepts/contracts.md`
|
|
190
189
|
# § Overrides for the wiring.
|
|
191
190
|
#
|
|
192
191
|
# - Mode: this pack is enforce-mode safe by design — every rule
|
|
@@ -93,7 +93,7 @@ agents:
|
|
|
93
93
|
- desc: >-
|
|
94
94
|
Block destructive Railway control-plane API calls
|
|
95
95
|
(PocketOS-style 9-second prod wipe via curl + token).
|
|
96
|
-
|
|
96
|
+
G:
|
|
97
97
|
pattern: arg_blacklist
|
|
98
98
|
args:
|
|
99
99
|
- exec
|
|
@@ -124,7 +124,7 @@ agents:
|
|
|
124
124
|
- desc: >-
|
|
125
125
|
Block Railway CLI destructive verbs (down / volume delete /
|
|
126
126
|
environment delete / project delete / service delete).
|
|
127
|
-
|
|
127
|
+
G:
|
|
128
128
|
pattern: arg_blacklist
|
|
129
129
|
args:
|
|
130
130
|
- exec
|
|
@@ -150,7 +150,7 @@ agents:
|
|
|
150
150
|
Block ``curl -X DELETE`` against known cloud / PaaS control
|
|
151
151
|
planes (Railway / Fly / Render / Supabase / Vercel / Heroku /
|
|
152
152
|
Cloudflare / DigitalOcean / Linode / Hetzner / AWS / GCP / Azure).
|
|
153
|
-
|
|
153
|
+
G:
|
|
154
154
|
pattern: arg_blacklist
|
|
155
155
|
args:
|
|
156
156
|
- exec
|