@sponsio/sdk 0.1.0-alpha.3
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/contracts/capability/credentials.yaml +188 -0
- package/contracts/capability/database.yaml +141 -0
- package/contracts/capability/filesystem-strict.yaml +101 -0
- package/contracts/capability/filesystem.yaml +239 -0
- package/contracts/capability/self-modify.yaml +152 -0
- package/contracts/capability/shell.yaml +246 -0
- package/contracts/capability/subagent.yaml +184 -0
- package/contracts/core/llm_safety.yaml +130 -0
- package/contracts/core/runaway.yaml +43 -0
- package/contracts/core/universal.yaml +34 -0
- package/contracts/incident/claude-code-secret-bypass.yaml +197 -0
- package/contracts/incident/cursor-railway-wipe.yaml +164 -0
- package/contracts/incident/mcp-composition.yaml +418 -0
- package/contracts/incident/openclaw.yaml +500 -0
- package/contracts/incident/subagent-escape.yaml +177 -0
- package/contracts/premium/.gitkeep +7 -0
- package/dist/contract.d.ts +59 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +97 -0
- package/dist/contract.js.map +1 -0
- package/dist/core/config-loader.d.ts +90 -0
- package/dist/core/config-loader.d.ts.map +1 -0
- package/dist/core/config-loader.js +530 -0
- package/dist/core/config-loader.js.map +1 -0
- package/dist/core/evaluator.d.ts +15 -0
- package/dist/core/evaluator.d.ts.map +1 -0
- package/dist/core/evaluator.js +87 -0
- package/dist/core/evaluator.js.map +1 -0
- package/dist/core/formula.d.ts +103 -0
- package/dist/core/formula.d.ts.map +1 -0
- package/dist/core/formula.js +167 -0
- package/dist/core/formula.js.map +1 -0
- package/dist/core/grounding.d.ts +43 -0
- package/dist/core/grounding.d.ts.map +1 -0
- package/dist/core/grounding.js +269 -0
- package/dist/core/grounding.js.map +1 -0
- package/dist/core/nl-parser.d.ts +12 -0
- package/dist/core/nl-parser.d.ts.map +1 -0
- package/dist/core/nl-parser.js +152 -0
- package/dist/core/nl-parser.js.map +1 -0
- package/dist/core/pack-loader.d.ts +15 -0
- package/dist/core/pack-loader.d.ts.map +1 -0
- package/dist/core/pack-loader.js +220 -0
- package/dist/core/pack-loader.js.map +1 -0
- package/dist/core/parser.d.ts +19 -0
- package/dist/core/parser.d.ts.map +1 -0
- package/dist/core/parser.js +235 -0
- package/dist/core/parser.js.map +1 -0
- package/dist/core/pattern-factory.d.ts +38 -0
- package/dist/core/pattern-factory.d.ts.map +1 -0
- package/dist/core/pattern-factory.js +222 -0
- package/dist/core/pattern-factory.js.map +1 -0
- package/dist/core/patterns.d.ts +67 -0
- package/dist/core/patterns.d.ts.map +1 -0
- package/dist/core/patterns.js +585 -0
- package/dist/core/patterns.js.map +1 -0
- package/dist/core/session-log.d.ts +91 -0
- package/dist/core/session-log.d.ts.map +1 -0
- package/dist/core/session-log.js +196 -0
- package/dist/core/session-log.js.map +1 -0
- package/dist/core/spans.d.ts +92 -0
- package/dist/core/spans.d.ts.map +1 -0
- package/dist/core/spans.js +148 -0
- package/dist/core/spans.js.map +1 -0
- package/dist/core/sto.d.ts +120 -0
- package/dist/core/sto.d.ts.map +1 -0
- package/dist/core/sto.js +147 -0
- package/dist/core/sto.js.map +1 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +540 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/claude-agent.d.ts +29 -0
- package/dist/integrations/claude-agent.d.ts.map +1 -0
- package/dist/integrations/claude-agent.js +40 -0
- package/dist/integrations/claude-agent.js.map +1 -0
- package/dist/integrations/google-adk.d.ts +27 -0
- package/dist/integrations/google-adk.d.ts.map +1 -0
- package/dist/integrations/google-adk.js +81 -0
- package/dist/integrations/google-adk.js.map +1 -0
- package/dist/integrations/langchain.d.ts +26 -0
- package/dist/integrations/langchain.d.ts.map +1 -0
- package/dist/integrations/langchain.js +74 -0
- package/dist/integrations/langchain.js.map +1 -0
- package/dist/integrations/openai-agents.d.ts +45 -0
- package/dist/integrations/openai-agents.d.ts.map +1 -0
- package/dist/integrations/openai-agents.js +81 -0
- package/dist/integrations/openai-agents.js.map +1 -0
- package/dist/integrations/openai.d.ts +24 -0
- package/dist/integrations/openai.d.ts.map +1 -0
- package/dist/integrations/openai.js +77 -0
- package/dist/integrations/openai.js.map +1 -0
- package/dist/integrations/vercel-ai.d.ts +38 -0
- package/dist/integrations/vercel-ai.d.ts.map +1 -0
- package/dist/integrations/vercel-ai.js +107 -0
- package/dist/integrations/vercel-ai.js.map +1 -0
- package/dist/render/components.d.ts +23 -0
- package/dist/render/components.d.ts.map +1 -0
- package/dist/render/components.js +133 -0
- package/dist/render/components.js.map +1 -0
- package/dist/render/derive.d.ts +23 -0
- package/dist/render/derive.d.ts.map +1 -0
- package/dist/render/derive.js +92 -0
- package/dist/render/derive.js.map +1 -0
- package/dist/render/session-view.d.ts +19 -0
- package/dist/render/session-view.d.ts.map +1 -0
- package/dist/render/session-view.js +236 -0
- package/dist/render/session-view.js.map +1 -0
- package/dist/render/tokens.d.ts +44 -0
- package/dist/render/tokens.d.ts.map +1 -0
- package/dist/render/tokens.js +72 -0
- package/dist/render/tokens.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# sponsio/contracts/capability/credentials.yaml
|
|
3
|
+
#
|
|
4
|
+
# Capability pack — credential-shaped strings in file-write content.
|
|
5
|
+
# Include when your agent exposes write / edit tools and you don't
|
|
6
|
+
# want secrets to leak from the agent's working memory into committed
|
|
7
|
+
# files, READMEs, or anywhere else that gets diff'd / pushed / shared.
|
|
8
|
+
#
|
|
9
|
+
# Real-world incidents this pack defends against:
|
|
10
|
+
#
|
|
11
|
+
# - Cursor + ``.cursorignore`` bypass (Apr 2024 → Dec 2025): agent
|
|
12
|
+
# read ``.env`` (allowed by user) then included its content in
|
|
13
|
+
# prompts that were silently sent to AI providers. Same pattern
|
|
14
|
+
# surfaces when a sub-agent is told "summarize the project setup"
|
|
15
|
+
# and writes the env values verbatim into a README.
|
|
16
|
+
# - Claude Code sub-agent leak pattern (recurring r/ClaudeAI):
|
|
17
|
+
# parent agent reads ``.env`` for setup verification, spawns a
|
|
18
|
+
# ``Task`` sub-agent with full context, sub-agent dutifully echoes
|
|
19
|
+
# ``STRIPE_SECRET_KEY=...`` into a generated file. Then a final
|
|
20
|
+
# ``git commit && git push`` pushes secrets to a public repo.
|
|
21
|
+
# - Generic agent-in-IDE foot-guns: API keys ending up in commit
|
|
22
|
+
# messages, log lines, Slack messages composed by an agent.
|
|
23
|
+
#
|
|
24
|
+
# Threat model boundary: this pack catches credential SHAPES in tool
|
|
25
|
+
# *arguments* — i.e. the content the agent is about to write. It
|
|
26
|
+
# does NOT catch:
|
|
27
|
+
# - Credentials reformatted (base64'd, split across lines, etc.)
|
|
28
|
+
# - Read tools (read of ``.env`` is allowed by default; the
|
|
29
|
+
# sensitive-path read denies live in ``_host.yaml`` for the
|
|
30
|
+
# cases that DO matter)
|
|
31
|
+
# - Token exfil via outbound HTTP that happens not to use
|
|
32
|
+
# ``Bash``/``Write`` (use ``capability/network`` for that —
|
|
33
|
+
# planned)
|
|
34
|
+
#
|
|
35
|
+
# Include via:
|
|
36
|
+
# include:
|
|
37
|
+
# - sponsio:capability/credentials
|
|
38
|
+
#
|
|
39
|
+
# Tool naming:
|
|
40
|
+
# The pack uses canonical ``write`` / ``edit`` / ``apply_patch``
|
|
41
|
+
# for the write surface. Claude Code's ``_host.yaml`` adds
|
|
42
|
+
# ``write: Write`` / ``edit: Edit`` / ``apply_patch: MultiEdit``
|
|
43
|
+
# to its ``tool_rename`` block; OpenClaw's ``_host_openclaw.yaml``
|
|
44
|
+
# inherits canonical names directly.
|
|
45
|
+
#
|
|
46
|
+
# Source tag convention:
|
|
47
|
+
# library:tier1.credentials
|
|
48
|
+
# =============================================================================
|
|
49
|
+
|
|
50
|
+
version: "1"
|
|
51
|
+
|
|
52
|
+
tools:
|
|
53
|
+
- name: write
|
|
54
|
+
description: "Write or overwrite a file (placeholder — replace with your tool's name)"
|
|
55
|
+
params: "path: str, content: str"
|
|
56
|
+
- name: edit
|
|
57
|
+
description: "In-place edit of an existing file"
|
|
58
|
+
params: "path: str, new_string: str"
|
|
59
|
+
- name: apply_patch
|
|
60
|
+
description: "Apply a unified diff to a file"
|
|
61
|
+
params: "path: str, diff: str"
|
|
62
|
+
|
|
63
|
+
agents:
|
|
64
|
+
"*":
|
|
65
|
+
contracts:
|
|
66
|
+
|
|
67
|
+
# =================================================================
|
|
68
|
+
# § 1 — Block credential shapes in file-write CONTENT
|
|
69
|
+
# =================================================================
|
|
70
|
+
#
|
|
71
|
+
# The regex inventory targets the most common shapes that
|
|
72
|
+
# `git secrets`, gitleaks, trufflehog and friends recognise.
|
|
73
|
+
# Conservative on purpose: false positives here only block one
|
|
74
|
+
# write — the user can re-prompt with a redacted version.
|
|
75
|
+
# False negatives mean the secret ships, which is much worse.
|
|
76
|
+
|
|
77
|
+
- desc: "Block writes containing AWS / GCP / Azure / cloud creds"
|
|
78
|
+
E:
|
|
79
|
+
pattern: arg_blacklist
|
|
80
|
+
args:
|
|
81
|
+
- write
|
|
82
|
+
- content
|
|
83
|
+
- - "AKIA[A-Z0-9]{16}" # AWS access key
|
|
84
|
+
- "ASIA[A-Z0-9]{16}" # AWS temp creds
|
|
85
|
+
- "(?i)aws_secret_access_key\\s*=\\s*[A-Za-z0-9/+=]{40}"
|
|
86
|
+
- "AIza[A-Za-z0-9_-]{35}" # Google API key
|
|
87
|
+
- "ya29\\.[A-Za-z0-9_-]{20,}" # Google OAuth
|
|
88
|
+
source: "library:tier1.credentials"
|
|
89
|
+
|
|
90
|
+
- desc: "Block writes containing GitHub tokens"
|
|
91
|
+
E:
|
|
92
|
+
pattern: arg_blacklist
|
|
93
|
+
args:
|
|
94
|
+
- write
|
|
95
|
+
- content
|
|
96
|
+
- - "ghp_[A-Za-z0-9]{36,}" # personal access
|
|
97
|
+
- "ghu_[A-Za-z0-9]{36,}" # OAuth user
|
|
98
|
+
- "ghs_[A-Za-z0-9]{36,}" # server
|
|
99
|
+
- "gho_[A-Za-z0-9]{36,}" # OAuth app
|
|
100
|
+
- "github_pat_[A-Za-z0-9_]{82}" # fine-grained PAT
|
|
101
|
+
source: "library:tier1.credentials"
|
|
102
|
+
|
|
103
|
+
- desc: "Block writes containing payment-processor / SaaS API keys"
|
|
104
|
+
E:
|
|
105
|
+
pattern: arg_blacklist
|
|
106
|
+
args:
|
|
107
|
+
- write
|
|
108
|
+
- content
|
|
109
|
+
# Two key-prefix shapes co-exist in the wild:
|
|
110
|
+
# underscore-style (Stripe): sk_live_<base64ish>
|
|
111
|
+
# dash-style (OpenAI / Anthropic): sk-proj-<base64-with-dashes>
|
|
112
|
+
# Both random suffixes are >= 20 chars in practice.
|
|
113
|
+
- - "sk_(live|test)_[A-Za-z0-9]{20,}" # Stripe
|
|
114
|
+
- "sk-(live|test|proj|ant)-[A-Za-z0-9_-]{20,}" # OpenAI / Anthropic
|
|
115
|
+
- "rk_(live|test)_[A-Za-z0-9]{20,}" # Stripe restricted
|
|
116
|
+
- "xox[baprs]-[A-Za-z0-9-]{10,}" # Slack
|
|
117
|
+
- "SG\\.[A-Za-z0-9_-]{22}\\.[A-Za-z0-9_-]{43}" # SendGrid
|
|
118
|
+
- "key-[a-f0-9]{32}" # Mailgun
|
|
119
|
+
source: "library:tier1.credentials"
|
|
120
|
+
|
|
121
|
+
- desc: "Block writes containing private keys / SSH material"
|
|
122
|
+
E:
|
|
123
|
+
pattern: arg_blacklist
|
|
124
|
+
args:
|
|
125
|
+
- write
|
|
126
|
+
- content
|
|
127
|
+
- - "-----BEGIN\\s+(RSA|OPENSSH|EC|DSA|PGP)\\s+PRIVATE KEY"
|
|
128
|
+
- "-----BEGIN\\s+ENCRYPTED\\s+PRIVATE KEY"
|
|
129
|
+
source: "library:tier1.credentials"
|
|
130
|
+
|
|
131
|
+
# =================================================================
|
|
132
|
+
# § 2 — Mirror rules for in-place edit (Claude Code's `Edit`)
|
|
133
|
+
# =================================================================
|
|
134
|
+
#
|
|
135
|
+
# Editing is the same threat surface as Write — sub-agents that
|
|
136
|
+
# leak secrets often do so by editing a README in place rather
|
|
137
|
+
# than creating a new file. Same regex inventory; pinned to
|
|
138
|
+
# ``new_string`` (the canonical `edit` tool's payload field).
|
|
139
|
+
|
|
140
|
+
- desc: "Block edits containing AWS / GCP / Azure / cloud creds"
|
|
141
|
+
E:
|
|
142
|
+
pattern: arg_blacklist
|
|
143
|
+
args:
|
|
144
|
+
- edit
|
|
145
|
+
- new_string
|
|
146
|
+
- - "AKIA[A-Z0-9]{16}"
|
|
147
|
+
- "ASIA[A-Z0-9]{16}"
|
|
148
|
+
- "(?i)aws_secret_access_key\\s*=\\s*[A-Za-z0-9/+=]{40}"
|
|
149
|
+
- "AIza[A-Za-z0-9_-]{35}"
|
|
150
|
+
- "ya29\\.[A-Za-z0-9_-]{20,}"
|
|
151
|
+
source: "library:tier1.credentials"
|
|
152
|
+
|
|
153
|
+
- desc: "Block edits containing GitHub tokens"
|
|
154
|
+
E:
|
|
155
|
+
pattern: arg_blacklist
|
|
156
|
+
args:
|
|
157
|
+
- edit
|
|
158
|
+
- new_string
|
|
159
|
+
- - "ghp_[A-Za-z0-9]{36,}"
|
|
160
|
+
- "ghu_[A-Za-z0-9]{36,}"
|
|
161
|
+
- "ghs_[A-Za-z0-9]{36,}"
|
|
162
|
+
- "gho_[A-Za-z0-9]{36,}"
|
|
163
|
+
- "github_pat_[A-Za-z0-9_]{82}"
|
|
164
|
+
source: "library:tier1.credentials"
|
|
165
|
+
|
|
166
|
+
- desc: "Block edits containing payment-processor / SaaS API keys"
|
|
167
|
+
E:
|
|
168
|
+
pattern: arg_blacklist
|
|
169
|
+
args:
|
|
170
|
+
- edit
|
|
171
|
+
- new_string
|
|
172
|
+
- - "sk_(live|test)_[A-Za-z0-9]{20,}"
|
|
173
|
+
- "sk-(live|test|proj|ant)-[A-Za-z0-9_-]{20,}"
|
|
174
|
+
- "rk_(live|test)_[A-Za-z0-9]{20,}"
|
|
175
|
+
- "xox[baprs]-[A-Za-z0-9-]{10,}"
|
|
176
|
+
- "SG\\.[A-Za-z0-9_-]{22}\\.[A-Za-z0-9_-]{43}"
|
|
177
|
+
- "key-[a-f0-9]{32}"
|
|
178
|
+
source: "library:tier1.credentials"
|
|
179
|
+
|
|
180
|
+
- desc: "Block edits containing private keys / SSH material"
|
|
181
|
+
E:
|
|
182
|
+
pattern: arg_blacklist
|
|
183
|
+
args:
|
|
184
|
+
- edit
|
|
185
|
+
- new_string
|
|
186
|
+
- - "-----BEGIN\\s+(RSA|OPENSSH|EC|DSA|PGP)\\s+PRIVATE KEY"
|
|
187
|
+
- "-----BEGIN\\s+ENCRYPTED\\s+PRIVATE KEY"
|
|
188
|
+
source: "library:tier1.credentials"
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# sponsio/contracts/capability/database.yaml
|
|
3
|
+
#
|
|
4
|
+
# Capability pack — destructive database operations via shell. Include
|
|
5
|
+
# when your agent exposes a tool that runs arbitrary shell commands
|
|
6
|
+
# (`exec`, `bash`, `Bash`, `run_command`, …) and the agent has database
|
|
7
|
+
# credentials in its environment.
|
|
8
|
+
#
|
|
9
|
+
# Real-world incidents this pack defends against:
|
|
10
|
+
#
|
|
11
|
+
# - Replit agent (Jul 2025): deleted live production DB during a code
|
|
12
|
+
# freeze, affecting 1,200+ companies. The model executed
|
|
13
|
+
# ``psql -c "DROP DATABASE prod"`` after misinterpreting a
|
|
14
|
+
# freeze instruction. Highest-profile data-loss incident from an
|
|
15
|
+
# LLM agent to date.
|
|
16
|
+
# - Anecdotal: agents running migration tools at the wrong scope —
|
|
17
|
+
# ``alembic downgrade base`` rolling back to an empty schema.
|
|
18
|
+
# - Anecdotal: agents using ``redis-cli FLUSHALL`` to "reset state"
|
|
19
|
+
# during debugging, wiping a shared dev cache.
|
|
20
|
+
#
|
|
21
|
+
# This pack is shell-only. For per-MCP-server rules (e.g.
|
|
22
|
+
# ``mcp__postgres__execute_sql.statement``), generate a per-plugin
|
|
23
|
+
# library via ``sponsio plugin scan --introspect`` against that
|
|
24
|
+
# server.
|
|
25
|
+
#
|
|
26
|
+
# Include via:
|
|
27
|
+
# include:
|
|
28
|
+
# - sponsio:capability/database
|
|
29
|
+
#
|
|
30
|
+
# Tool naming:
|
|
31
|
+
# The pack uses canonical ``exec``. Rename if your agent's shell
|
|
32
|
+
# tool has a different name — Claude Code's ``Bash`` is auto-handled
|
|
33
|
+
# by the ``_host.yaml`` library's ``tool_rename:`` block.
|
|
34
|
+
#
|
|
35
|
+
# Source tag convention:
|
|
36
|
+
# library:tier1.database
|
|
37
|
+
# =============================================================================
|
|
38
|
+
|
|
39
|
+
version: "1"
|
|
40
|
+
|
|
41
|
+
tools:
|
|
42
|
+
- name: exec
|
|
43
|
+
description: "Shell command execution (placeholder — replace with your tool's real name)"
|
|
44
|
+
params: "command: str"
|
|
45
|
+
|
|
46
|
+
agents:
|
|
47
|
+
"*":
|
|
48
|
+
contracts:
|
|
49
|
+
|
|
50
|
+
# =================================================================
|
|
51
|
+
# § 1 — Destructive SQL via shell (psql / mysql / sqlite3 / ...)
|
|
52
|
+
# =================================================================
|
|
53
|
+
|
|
54
|
+
- desc: "Ban DROP DATABASE / DROP TABLE / DROP SCHEMA via shell"
|
|
55
|
+
E:
|
|
56
|
+
pattern: arg_blacklist
|
|
57
|
+
args:
|
|
58
|
+
- exec
|
|
59
|
+
- command
|
|
60
|
+
# Word boundaries on either side to avoid matching prose
|
|
61
|
+
# like ``"how to drop a table"``; case-insensitive because
|
|
62
|
+
# SQL is conventionally uppercase but agents often emit
|
|
63
|
+
# lowercase.
|
|
64
|
+
- - "(?i)\\bdrop\\s+(database|table|schema|view|index)\\b"
|
|
65
|
+
source: "library:tier1.database"
|
|
66
|
+
|
|
67
|
+
- desc: "Ban TRUNCATE TABLE via shell (whole-table wipe)"
|
|
68
|
+
E:
|
|
69
|
+
pattern: arg_blacklist
|
|
70
|
+
args:
|
|
71
|
+
- exec
|
|
72
|
+
- command
|
|
73
|
+
# Require the literal "TABLE" keyword to avoid colliding
|
|
74
|
+
# with the unrelated POSIX ``truncate`` command (which
|
|
75
|
+
# extends/shrinks files via ``truncate -s N file``).
|
|
76
|
+
- - "(?i)\\btruncate\\s+table\\s+\\w+"
|
|
77
|
+
source: "library:tier1.database"
|
|
78
|
+
|
|
79
|
+
- desc: "Ban unbounded DELETE FROM (no WHERE clause)"
|
|
80
|
+
E:
|
|
81
|
+
pattern: arg_blacklist
|
|
82
|
+
args:
|
|
83
|
+
- exec
|
|
84
|
+
- command
|
|
85
|
+
# ``DELETE FROM users;`` matches; ``DELETE FROM users
|
|
86
|
+
# WHERE id=1;`` does not, because the table name isn't
|
|
87
|
+
# immediately followed by a terminator. Catches the
|
|
88
|
+
# canonical "wipe a whole table" foot-gun without false-
|
|
89
|
+
# positing real DELETE-by-key statements.
|
|
90
|
+
- - "(?i)\\bdelete\\s+from\\s+\\w+\\s*;"
|
|
91
|
+
source: "library:tier1.database"
|
|
92
|
+
|
|
93
|
+
# =================================================================
|
|
94
|
+
# § 2 — Destructive DB CLI tools
|
|
95
|
+
# =================================================================
|
|
96
|
+
|
|
97
|
+
- desc: "Ban dropdb / mysqladmin drop / redis FLUSHALL / FLUSHDB"
|
|
98
|
+
E:
|
|
99
|
+
pattern: arg_blacklist
|
|
100
|
+
args:
|
|
101
|
+
- exec
|
|
102
|
+
- command
|
|
103
|
+
- - "(?i)\\bdropdb\\b"
|
|
104
|
+
- "(?i)\\bmysqladmin\\b.{0,80}\\bdrop\\b"
|
|
105
|
+
- "(?i)\\bredis-cli\\b.{0,80}\\b(flushall|flushdb)\\b"
|
|
106
|
+
- "(?i)\\bmongo\\s.{0,80}\\bdropDatabase\\s*\\("
|
|
107
|
+
source: "library:tier1.database"
|
|
108
|
+
|
|
109
|
+
- desc: "Ban migration rollback to empty schema"
|
|
110
|
+
E:
|
|
111
|
+
pattern: arg_blacklist
|
|
112
|
+
args:
|
|
113
|
+
- exec
|
|
114
|
+
- command
|
|
115
|
+
# ``downgrade base`` rolls schema back to the very
|
|
116
|
+
# beginning of migration history — irreversible without
|
|
117
|
+
# backups. Single-step downgrades (``-1``) stay allowed.
|
|
118
|
+
- - "(?i)\\balembic\\s+downgrade\\s+base\\b"
|
|
119
|
+
- "(?i)\\bflask\\s+db\\s+downgrade\\s+base\\b"
|
|
120
|
+
- "(?i)\\bdjango-admin\\s+flush\\b"
|
|
121
|
+
source: "library:tier1.database"
|
|
122
|
+
|
|
123
|
+
# =================================================================
|
|
124
|
+
# § 3 — Deletion of database data directories
|
|
125
|
+
# =================================================================
|
|
126
|
+
|
|
127
|
+
- desc: "Ban deletion of database data directories"
|
|
128
|
+
E:
|
|
129
|
+
pattern: arg_blacklist
|
|
130
|
+
args:
|
|
131
|
+
- exec
|
|
132
|
+
- command
|
|
133
|
+
# Common data-dir locations across distros; covers the
|
|
134
|
+
# "rm -rf /var/lib/postgresql/data" foot-gun that the
|
|
135
|
+
# capability/shell pack's ``rm -rf /`` rule misses
|
|
136
|
+
# because the path doesn't end at the root delimiter.
|
|
137
|
+
- - "rm\\s+-[rRf]+\\s+/var/lib/(postgresql|mysql|mongodb|redis|elasticsearch|cassandra|couchdb)\\b"
|
|
138
|
+
- "rm\\s+-[rRf]+\\s+/var/data/(postgresql|mysql|mongodb)\\b"
|
|
139
|
+
- "rm\\s+-[rRf]+\\s+/data/db\\b"
|
|
140
|
+
- "rm\\s+-[rRf]+\\s+/opt/(postgresql|mysql|mongodb)\\b"
|
|
141
|
+
source: "library:tier1.database"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# sponsio/contracts/capability/filesystem-strict.yaml
|
|
3
|
+
#
|
|
4
|
+
# Capability pack — strict workspace scoping for filesystem tools. Add
|
|
5
|
+
# alongside ``sponsio:capability/filesystem`` when you want every
|
|
6
|
+
# read/write/edit/apply_patch confined to an explicit workspace
|
|
7
|
+
# prefix.
|
|
8
|
+
#
|
|
9
|
+
# Why this pack is opt-in (not part of the base ``capability/filesystem``):
|
|
10
|
+
#
|
|
11
|
+
# - These rules require an absolute ``<workspace>/`` placeholder
|
|
12
|
+
# resolved at load time. Configs without a ``workspace:`` field
|
|
13
|
+
# can't satisfy them and produce silent "no path matched"
|
|
14
|
+
# evaluations on every call.
|
|
15
|
+
# - Recorded-trajectory demos and replay test fixtures often use
|
|
16
|
+
# RELATIVE paths (``src/components/UserList.tsx``). ``scope_limit``
|
|
17
|
+
# interprets these as outside the workspace, which generates
|
|
18
|
+
# "WOULD-BLOCK" noise on every benign read in observe mode and
|
|
19
|
+
# wedges the agent at step 1 in enforce mode.
|
|
20
|
+
# - For agents whose actual filesystem footprint is broad
|
|
21
|
+
# (CI/CD pipelines, system-administration assistants, monorepo
|
|
22
|
+
# refactor tools), workspace scope is wrong-by-design — they
|
|
23
|
+
# legitimately operate across many directories.
|
|
24
|
+
#
|
|
25
|
+
# In short: the sensitive-path blacklists in the base pack are the
|
|
26
|
+
# universal "every agent needs this" rules. Workspace scoping is
|
|
27
|
+
# the opinionated "I know my agent stays in one tree" addition.
|
|
28
|
+
# Include this pack when (a) your agent does stay in one tree AND
|
|
29
|
+
# (b) your traces use absolute paths under that tree.
|
|
30
|
+
#
|
|
31
|
+
# Include via:
|
|
32
|
+
# include:
|
|
33
|
+
# - sponsio:capability/filesystem # base — credential blacklists
|
|
34
|
+
# - sponsio:capability/filesystem-strict # this pack — workspace scope
|
|
35
|
+
#
|
|
36
|
+
# Source tag convention:
|
|
37
|
+
# library:tier1.filesystem-strict
|
|
38
|
+
# =============================================================================
|
|
39
|
+
|
|
40
|
+
version: "1"
|
|
41
|
+
|
|
42
|
+
agents:
|
|
43
|
+
"*":
|
|
44
|
+
contracts:
|
|
45
|
+
|
|
46
|
+
# =================================================================
|
|
47
|
+
# Workspace scoping — writes / edits / apply_patch.
|
|
48
|
+
#
|
|
49
|
+
# ``<workspace>/`` is a literal placeholder. The integration
|
|
50
|
+
# layer (or a hand-edited config) substitutes the actual root
|
|
51
|
+
# before load. Without resolution, scope_limit on relative
|
|
52
|
+
# paths is a silent always-pass.
|
|
53
|
+
# =================================================================
|
|
54
|
+
|
|
55
|
+
- desc: "Writes restricted to workspace"
|
|
56
|
+
E:
|
|
57
|
+
pattern: scope_limit
|
|
58
|
+
args:
|
|
59
|
+
- write
|
|
60
|
+
- ["<workspace>/"]
|
|
61
|
+
source: "library:tier1.filesystem-strict"
|
|
62
|
+
|
|
63
|
+
- desc: "In-place edits restricted to workspace"
|
|
64
|
+
E:
|
|
65
|
+
pattern: scope_limit
|
|
66
|
+
args:
|
|
67
|
+
- edit
|
|
68
|
+
- ["<workspace>/"]
|
|
69
|
+
source: "library:tier1.filesystem-strict"
|
|
70
|
+
|
|
71
|
+
- desc: "Patch application restricted to workspace"
|
|
72
|
+
E:
|
|
73
|
+
pattern: scope_limit
|
|
74
|
+
args:
|
|
75
|
+
- apply_patch
|
|
76
|
+
- ["<workspace>/"]
|
|
77
|
+
source: "library:tier1.filesystem-strict"
|
|
78
|
+
|
|
79
|
+
# Read scope is broader than write scope: agents legitimately
|
|
80
|
+
# inspect system state (/etc/hosts, /var/log/*), link headers
|
|
81
|
+
# (/usr/include/), and read stdlib for grounding. The
|
|
82
|
+
# sensitive-path blacklist in the base ``filesystem`` pack
|
|
83
|
+
# keeps secrets hard-denied under any of these roots.
|
|
84
|
+
- desc: "Reads restricted to workspace, /tmp, and read-only system paths"
|
|
85
|
+
E:
|
|
86
|
+
pattern: scope_limit
|
|
87
|
+
args:
|
|
88
|
+
- read
|
|
89
|
+
- - "<workspace>/"
|
|
90
|
+
- "/tmp/"
|
|
91
|
+
- "/etc/"
|
|
92
|
+
- "/var/log/"
|
|
93
|
+
- "/usr/include/"
|
|
94
|
+
- "/usr/local/include/"
|
|
95
|
+
- "/usr/lib/"
|
|
96
|
+
- "/usr/local/lib/"
|
|
97
|
+
- "/usr/share/"
|
|
98
|
+
- "/opt/"
|
|
99
|
+
- "/proc/"
|
|
100
|
+
- "/sys/"
|
|
101
|
+
source: "library:tier1.filesystem-strict"
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# sponsio/contracts/capability/filesystem.yaml
|
|
3
|
+
#
|
|
4
|
+
# Capability pack — filesystem access. Include when your agent exposes
|
|
5
|
+
# read / write / edit / apply_patch tools against the host filesystem.
|
|
6
|
+
#
|
|
7
|
+
# Real-world incidents this pack defends against:
|
|
8
|
+
#
|
|
9
|
+
# - OpenClaw "weather-skill" incident: skill exfiltrated
|
|
10
|
+
# ~/.clawdbot/.env, leaking paid AI API keys.
|
|
11
|
+
# - OpenClaw AMOS payload: stole SSH keys, keychain, browser creds.
|
|
12
|
+
# - Cursor forum (Apr 2024 → Dec 2025): `.cursorignore` not honored in
|
|
13
|
+
# Auto Context; .env content silently sent to AI server.
|
|
14
|
+
# - Claude Code Issue #10077: recursive delete wiped /home files.
|
|
15
|
+
# - OpenClaw agent editing its own AGENTS.md / SOUL.md bootstrap files
|
|
16
|
+
# → persistent-prompt-injection at bootstrap time.
|
|
17
|
+
#
|
|
18
|
+
# Tool name conventions in this file:
|
|
19
|
+
# - read, write, edit, apply_patch (OpenClaw / Claude Code default)
|
|
20
|
+
# Rename to match your agent (e.g. Cursor uses edit_file/read_file).
|
|
21
|
+
#
|
|
22
|
+
# Include via:
|
|
23
|
+
# include:
|
|
24
|
+
# - sponsio:capability/filesystem
|
|
25
|
+
#
|
|
26
|
+
# Source tag convention:
|
|
27
|
+
# library:tier1.filesystem
|
|
28
|
+
# =============================================================================
|
|
29
|
+
|
|
30
|
+
version: "1"
|
|
31
|
+
|
|
32
|
+
tools:
|
|
33
|
+
- name: read
|
|
34
|
+
description: "Read file contents"
|
|
35
|
+
params: "path: str"
|
|
36
|
+
- name: write
|
|
37
|
+
description: "Create or overwrite a file"
|
|
38
|
+
params: "path: str, content: str"
|
|
39
|
+
- name: edit
|
|
40
|
+
description: "In-place edit of an existing file"
|
|
41
|
+
params: "path: str, patch: str"
|
|
42
|
+
- name: apply_patch
|
|
43
|
+
description: "Apply a unified diff"
|
|
44
|
+
params: "path: str, diff: str"
|
|
45
|
+
|
|
46
|
+
agents:
|
|
47
|
+
"*":
|
|
48
|
+
contracts:
|
|
49
|
+
|
|
50
|
+
# =================================================================
|
|
51
|
+
# § 1 — Sensitive-path hard denies
|
|
52
|
+
#
|
|
53
|
+
# These paths never have a legitimate reason to appear in an agent
|
|
54
|
+
# trace. If the agent needs one of them (e.g. a git credential
|
|
55
|
+
# rotator that legitimately reads .aws/credentials), the including
|
|
56
|
+
# config overrides this section.
|
|
57
|
+
# =================================================================
|
|
58
|
+
|
|
59
|
+
# The .env regex deliberately *excludes* the conventional
|
|
60
|
+
# non-secret variants (.env.example / .env.sample / .env.template
|
|
61
|
+
# / .env.dist) — those files exist to be committed to git and
|
|
62
|
+
# serve as documentation of expected variables. Blocking them
|
|
63
|
+
# would generate noisy false positives on day 1, which is the
|
|
64
|
+
# fastest way to get a security pack disabled. All other
|
|
65
|
+
# `.env` and `.env.<suffix>` paths are still blocked.
|
|
66
|
+
#
|
|
67
|
+
# `crontab` is end-anchored to avoid matching paths like
|
|
68
|
+
# `/projects/crontab-tests/` or `mycrontab.txt`.
|
|
69
|
+
- desc: "Deny reads of SSH keys, AWS credentials, browser keychains, dotenv secrets"
|
|
70
|
+
E:
|
|
71
|
+
pattern: arg_blacklist
|
|
72
|
+
args:
|
|
73
|
+
- read
|
|
74
|
+
- path
|
|
75
|
+
- - "(^|/)\\.ssh/"
|
|
76
|
+
- "(^|/)\\.aws/credentials"
|
|
77
|
+
- "(^|/)\\.aws/config"
|
|
78
|
+
- "(^|/)\\.env(\\.(?!example$|sample$|template$|dist$)[\\w.-]+)?$"
|
|
79
|
+
- "(^|/)\\.netrc"
|
|
80
|
+
- "(^|/)\\.pgpass"
|
|
81
|
+
- "(^|/)\\.kube/config"
|
|
82
|
+
- "(^|/)\\.docker/config\\.json"
|
|
83
|
+
- "(^|/)Library/Keychains"
|
|
84
|
+
- "(^|/)\\.gnupg/"
|
|
85
|
+
- "(^|/)id_rsa($|\\.)"
|
|
86
|
+
- "(^|/)id_ed25519($|\\.)"
|
|
87
|
+
# /etc/ is permitted for reads in §2 (hosts, resolv.conf,
|
|
88
|
+
# os-release are routinely needed for diagnostics) but
|
|
89
|
+
# these specific entries under /etc hold credentials or
|
|
90
|
+
# escalation config and must stay hard-denied:
|
|
91
|
+
- "^/etc/shadow($|/)"
|
|
92
|
+
- "^/etc/sudoers($|\\.d/|$)"
|
|
93
|
+
- "^/etc/ssh/ssh_host_"
|
|
94
|
+
- "^/etc/ssl/private/"
|
|
95
|
+
- "^/etc/krb5\\.keytab$"
|
|
96
|
+
source: "library:tier1.filesystem"
|
|
97
|
+
|
|
98
|
+
- desc: "Deny writes / edits into sensitive paths (prevent persistence or cred overwrite)"
|
|
99
|
+
E:
|
|
100
|
+
pattern: arg_blacklist
|
|
101
|
+
args:
|
|
102
|
+
- write
|
|
103
|
+
- path
|
|
104
|
+
- - "(^|/)\\.ssh/"
|
|
105
|
+
- "(^|/)\\.aws/"
|
|
106
|
+
- "(^|/)\\.bashrc$"
|
|
107
|
+
- "(^|/)\\.zshrc$"
|
|
108
|
+
- "(^|/)\\.profile$"
|
|
109
|
+
- "(^|/)crontab$"
|
|
110
|
+
- "(^|/)LaunchAgents/"
|
|
111
|
+
- "(^|/)LaunchDaemons/"
|
|
112
|
+
- "/etc/"
|
|
113
|
+
- "/usr/local/bin/"
|
|
114
|
+
source: "library:tier1.filesystem"
|
|
115
|
+
|
|
116
|
+
- desc: "Same denial applies to in-place edits"
|
|
117
|
+
E:
|
|
118
|
+
pattern: arg_blacklist
|
|
119
|
+
args:
|
|
120
|
+
- edit
|
|
121
|
+
- path
|
|
122
|
+
- - "(^|/)\\.ssh/"
|
|
123
|
+
- "(^|/)\\.aws/"
|
|
124
|
+
- "(^|/)\\.bashrc$"
|
|
125
|
+
- "(^|/)\\.zshrc$"
|
|
126
|
+
- "(^|/)\\.profile$"
|
|
127
|
+
- "(^|/)crontab$"
|
|
128
|
+
- "(^|/)LaunchAgents/"
|
|
129
|
+
- "(^|/)LaunchDaemons/"
|
|
130
|
+
- "/etc/"
|
|
131
|
+
source: "library:tier1.filesystem"
|
|
132
|
+
|
|
133
|
+
- desc: "And to unified-diff patches"
|
|
134
|
+
E:
|
|
135
|
+
pattern: arg_blacklist
|
|
136
|
+
args:
|
|
137
|
+
- apply_patch
|
|
138
|
+
- path
|
|
139
|
+
- - "(^|/)\\.ssh/"
|
|
140
|
+
- "(^|/)\\.aws/"
|
|
141
|
+
- "/etc/"
|
|
142
|
+
source: "library:tier1.filesystem"
|
|
143
|
+
|
|
144
|
+
# =================================================================
|
|
145
|
+
# § 2 — Workspace scoping (moved to filesystem-strict)
|
|
146
|
+
#
|
|
147
|
+
# The four ``scope_limit`` rules that used to live here
|
|
148
|
+
# (Writes / Edits / Patch / Reads restricted to workspace +
|
|
149
|
+
# system-read paths) are now in
|
|
150
|
+
# ``sponsio:capability/filesystem-strict``. Reason: they
|
|
151
|
+
# require an absolute workspace prefix that many real agents
|
|
152
|
+
# don't have, and they false-positive on relative-path traces
|
|
153
|
+
# (e.g. ``src/components/UserList.tsx``).
|
|
154
|
+
#
|
|
155
|
+
# Add the strict pack alongside this one when you actually
|
|
156
|
+
# want workspace bounding:
|
|
157
|
+
#
|
|
158
|
+
# include:
|
|
159
|
+
# - sponsio:capability/filesystem
|
|
160
|
+
# - sponsio:capability/filesystem-strict
|
|
161
|
+
# =================================================================
|
|
162
|
+
|
|
163
|
+
# =================================================================
|
|
164
|
+
# § 3 — Operational hygiene
|
|
165
|
+
# =================================================================
|
|
166
|
+
|
|
167
|
+
- desc: "Must read a file before editing it (no blind patches)"
|
|
168
|
+
E:
|
|
169
|
+
pattern: must_precede
|
|
170
|
+
args: [read, edit]
|
|
171
|
+
source: "library:tier1.filesystem"
|
|
172
|
+
|
|
173
|
+
- desc: "Must read a file before apply_patch (no blind diffs)"
|
|
174
|
+
E:
|
|
175
|
+
pattern: must_precede
|
|
176
|
+
args: [read, apply_patch]
|
|
177
|
+
source: "library:tier1.filesystem"
|
|
178
|
+
|
|
179
|
+
# =================================================================
|
|
180
|
+
# § 4 — Self-modification guardrails
|
|
181
|
+
#
|
|
182
|
+
# Agents with a persistent workspace often have "bootstrap" files
|
|
183
|
+
# whose contents get injected into the system prompt every
|
|
184
|
+
# session (OpenClaw: AGENTS.md, SOUL.md, IDENTITY.md, USER.md;
|
|
185
|
+
# Claude Code: CLAUDE.md; Cursor: .cursorrules). The agent
|
|
186
|
+
# editing these is persistent prompt injection — an attacker who
|
|
187
|
+
# compromises one session can seed instructions that fire every
|
|
188
|
+
# future session.
|
|
189
|
+
#
|
|
190
|
+
# We gate self-modification behind a confirm_reconfirmed marker.
|
|
191
|
+
# =================================================================
|
|
192
|
+
|
|
193
|
+
- desc: "Editing bootstrap / system-prompt files requires human confirmation"
|
|
194
|
+
E:
|
|
195
|
+
ltl: 'G(called_with(edit, "(AGENTS|SOUL|IDENTITY|USER|CLAUDE|\\.cursorrules)\\.md?") -> count(confirm_reconfirmed) >= count_with(edit, "(AGENTS|SOUL|IDENTITY|USER|CLAUDE|\\.cursorrules)\\.md?"))'
|
|
196
|
+
source: "library:tier1.filesystem"
|
|
197
|
+
|
|
198
|
+
- desc: "apply_patch against bootstrap files requires confirmation"
|
|
199
|
+
E:
|
|
200
|
+
ltl: 'G(called_with(apply_patch, "(AGENTS|SOUL|IDENTITY|USER|CLAUDE|\\.cursorrules)\\.md?") -> count(confirm_reconfirmed) >= count_with(apply_patch, "(AGENTS|SOUL|IDENTITY|USER|CLAUDE|\\.cursorrules)\\.md?"))'
|
|
201
|
+
source: "library:tier1.filesystem"
|
|
202
|
+
|
|
203
|
+
# =================================================================
|
|
204
|
+
# § 5 — Data-leak prevention
|
|
205
|
+
#
|
|
206
|
+
# Generic no-data-leak from read → external sinks. The including
|
|
207
|
+
# config must name the external sinks (send_message, http_post,
|
|
208
|
+
# etc.) — we can't enumerate them here since sink inventory is
|
|
209
|
+
# agent-specific. The `send_message` form below is the most
|
|
210
|
+
# common instance and OpenClaw-derived; it's harmless to keep
|
|
211
|
+
# here because if the agent doesn't have send_message the formula
|
|
212
|
+
# is vacuously satisfied.
|
|
213
|
+
# =================================================================
|
|
214
|
+
|
|
215
|
+
- desc: "Data read from filesystem must not flow to outbound messages"
|
|
216
|
+
E:
|
|
217
|
+
pattern: no_data_leak
|
|
218
|
+
args: [read, send_message]
|
|
219
|
+
source: "library:tier1.filesystem"
|
|
220
|
+
|
|
221
|
+
# -----------------------------------------------------------------------------
|
|
222
|
+
# Integration requirements
|
|
223
|
+
# -----------------------------------------------------------------------------
|
|
224
|
+
#
|
|
225
|
+
# - `<workspace>/` is a literal prefix — resolve it at include time or
|
|
226
|
+
# pre-process the YAML with a sed substitution before handing to
|
|
227
|
+
# config.load(). A cleaner fix is a resolver hook in the include
|
|
228
|
+
# mechanism; tracked as future work.
|
|
229
|
+
#
|
|
230
|
+
# - `confirm_reconfirmed` must be emitted by the integration on human
|
|
231
|
+
# approval. Same marker convention as capability/shell.yaml.
|
|
232
|
+
#
|
|
233
|
+
# - If your agent's filesystem tools aren't named read/write/edit/
|
|
234
|
+
# apply_patch, rename them at include time or at config-load.
|
|
235
|
+
#
|
|
236
|
+
# - The sensitive-path blacklists are conservative. Agents with a
|
|
237
|
+
# legitimate reason to touch one of those paths (e.g. an SSH key
|
|
238
|
+
# rotator, a cron editor) should narrow the blacklist in their own
|
|
239
|
+
# config rather than removing this file from the include chain.
|