opencode-varlock 0.0.8 → 0.0.10
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/README.md +64 -322
- package/assets/permissions.json +47 -0
- package/assets/varlock.config.json +7 -4
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +212 -0
- package/dist/config.js.map +1 -1
- package/dist/guard.d.ts.map +1 -1
- package/dist/guard.js +169 -1
- package/dist/guard.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +45 -2
- package/dist/plugin.js.map +1 -1
- package/dist/scrubber.d.ts +14 -0
- package/dist/scrubber.d.ts.map +1 -0
- package/dist/scrubber.js +33 -0
- package/dist/scrubber.js.map +1 -0
- package/dist/tools.d.ts +3 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +49 -16
- package/dist/tools.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -1,364 +1,106 @@
|
|
|
1
1
|
# opencode-varlock
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/opencode-varlock)
|
|
4
|
+
[](https://github.com/itlackey/opencode-varlock/actions/workflows/test.yml)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
OpenCode plugin that gives agents access to secrets without revealing the values. The plugin leverages [varlock](https://varlock.dev) and [opencode](https://opencode.ai) features to provide a multi-layered defense against intentional and accidental secret leakage by OpenCode agents.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
> [!Important]
|
|
9
|
+
> This plugin is still early in development, and there is active work underway to improve its security model and edge-case protections. PRs, issue reports, and security feedback are very welcome.
|
|
8
10
|
|
|
9
|
-
##
|
|
11
|
+
## What it does
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
│ process.env, returns only key names. │
|
|
24
|
-
├──────────────────────────────────────────────────┤
|
|
25
|
-
│ Layer 2 — Permission rules │
|
|
26
|
-
│ Glob-based deny rules block `cat .env`, │
|
|
27
|
-
│ `printenv`, `echo $SECRET`, etc. │
|
|
28
|
-
├──────────────────────────────────────────────────┤
|
|
29
|
-
│ Layer 3 — EnvGuard hook │
|
|
30
|
-
│ tool.execute.before intercept catches anything │
|
|
31
|
-
│ the glob rules miss (python -c, scripting │
|
|
32
|
-
│ escapes, indirect reads). │
|
|
33
|
-
└──────────────────────────────────────────────────┘
|
|
34
|
-
```
|
|
13
|
+
- provides `load_env` so agents can use `.env` values without seeing them directly
|
|
14
|
+
- provides `load_secrets` and `secret_status` when the [Varlock CLI](https://varlock.dev) is available
|
|
15
|
+
- uses `varlock load --format json` and `varlock printenv` to integrate with the varlock.dev CLI
|
|
16
|
+
- blocks direct secret reads with a `tool.execute.before` guard covering:
|
|
17
|
+
- 50+ bash deny patterns and 9 interpreter-based env read detectors
|
|
18
|
+
- 30+ file processor commands (`sed`, `awk`, `dd`, `tee`, `xxd`, etc.)
|
|
19
|
+
- shell redirects, encoding/eval bypasses, and variable listing commands
|
|
20
|
+
- varlock CLI self-exfiltration (`varlock printenv`, `varlock load --format env`)
|
|
21
|
+
- scrubs loaded secret values from tool output via a `tool.execute.after` hook
|
|
22
|
+
- whitelists `.env.schema` and `.env.example` (safe for AI consumption per varlock.dev design)
|
|
23
|
+
- validates config files and prevents agents from tampering with plugin configuration
|
|
24
|
+
- prevents symlink traversal and command injection in tool arguments
|
|
35
25
|
|
|
36
26
|
## Install
|
|
37
27
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
npm install opencode-varlock
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
```json
|
|
45
|
-
// opencode.json
|
|
46
|
-
{
|
|
47
|
-
"plugin": ["opencode-varlock"]
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
The published package ships compiled ESM in `dist/`, and the root entry exports only the plugin itself so OpenCode can load it cleanly through the normal npm plugin resolution flow.
|
|
52
|
-
|
|
53
|
-
### As a local plugin
|
|
54
|
-
|
|
55
|
-
Reference the package directory locally after building it:
|
|
28
|
+
Add the package to your `opencode.json` file:
|
|
56
29
|
|
|
57
30
|
```json
|
|
58
31
|
{
|
|
59
|
-
"
|
|
32
|
+
"$schema": "https://opencode.ai/config.json",
|
|
33
|
+
"plugin": ["opencode-varlock@latest"]
|
|
60
34
|
}
|
|
61
35
|
```
|
|
62
36
|
|
|
63
37
|
## Configuration
|
|
64
38
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
1. `./varlock.config.json` (project root)
|
|
68
|
-
2. `.opencode/varlock.config.json`
|
|
39
|
+
### Permissions
|
|
69
40
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
### Quick start
|
|
73
|
-
|
|
74
|
-
Copy the default config into your project:
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
cp node_modules/opencode-varlock/assets/varlock.config.json ./varlock.config.json
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Or create a minimal one — only the fields you want to change:
|
|
41
|
+
In addition to adding the plugin to the array, we recommend adding some additional permission settings to your config. There are a few recommended "presets" in the [assets/permissions.json](assets/permissions.json) file, but here is a basic example:
|
|
81
42
|
|
|
82
43
|
```json
|
|
83
44
|
{
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
|
|
45
|
+
"permission": {
|
|
46
|
+
"bash": {
|
|
47
|
+
"cat *.env*": "deny",
|
|
48
|
+
"less *.env*": "deny",
|
|
49
|
+
"more *.env*": "deny",
|
|
50
|
+
"head *.env*": "deny",
|
|
51
|
+
"tail *.env*": "deny",
|
|
52
|
+
"grep * .env*": "deny",
|
|
53
|
+
"echo $*": "deny",
|
|
54
|
+
"python*getenv*": "deny",
|
|
55
|
+
"python*os.environ*": "deny",
|
|
56
|
+
"python*open*env*": "deny",
|
|
57
|
+
"node*process.env*": "deny",
|
|
58
|
+
"printenv*": "deny",
|
|
59
|
+
"env": "deny",
|
|
60
|
+
"export -p": "deny",
|
|
61
|
+
"source .env*": "deny",
|
|
62
|
+
"varlock printenv*": "deny",
|
|
63
|
+
"varlock load --show*": "deny",
|
|
64
|
+
"varlock load --format*": "deny",
|
|
65
|
+
"varlock load -f*": "deny",
|
|
66
|
+
"sed * .env*": "deny",
|
|
67
|
+
"awk * .env*": "deny"
|
|
68
|
+
}
|
|
87
69
|
}
|
|
88
70
|
}
|
|
89
71
|
```
|
|
90
72
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
The bundled template and permission presets now live in `assets/`:
|
|
94
|
-
|
|
95
|
-
```text
|
|
96
|
-
assets/varlock.config.json
|
|
97
|
-
assets/varlock.schema.json
|
|
98
|
-
assets/permissions.json
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
The copied config template points its `$schema` at `./node_modules/opencode-varlock/assets/varlock.schema.json`, so editors can validate and autocomplete it after install.
|
|
102
|
-
|
|
103
|
-
## Repo layout
|
|
104
|
-
|
|
105
|
-
```text
|
|
106
|
-
src/ TypeScript source for the plugin entry, config, guard, and tools
|
|
107
|
-
assets/ JSON assets shipped with the npm package
|
|
108
|
-
docs/ Setup and integration guides
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## Testing
|
|
73
|
+
### Plugin Config
|
|
112
74
|
|
|
113
|
-
|
|
114
|
-
npm run test:unit
|
|
115
|
-
npm run test:integration
|
|
116
|
-
npm run test:coverage
|
|
117
|
-
```
|
|
75
|
+
`varlock.config.json` is optional.
|
|
118
76
|
|
|
119
|
-
-
|
|
120
|
-
- `test:integration` starts a real OpenCode server through `@opencode-ai/sdk` and verifies the plugin inside real sessions
|
|
121
|
-
- `test:coverage` emits text, HTML, and LCOV coverage reports under `coverage/`
|
|
77
|
+
If you do not provide one, the plugin uses its built-in defaults from [assets/varlock.config.json](assets/varlock.config.json). Create a local config and place it in your `.opencode` or `~/.config/opencode` directory when you want to override those defaults.
|
|
122
78
|
|
|
123
|
-
|
|
79
|
+
Quick example:
|
|
124
80
|
|
|
125
81
|
```json
|
|
126
82
|
{
|
|
127
|
-
"
|
|
128
|
-
"enabled": true,
|
|
129
|
-
|
|
130
|
-
"sensitivePatterns": [
|
|
131
|
-
".env", ".secret", ".pem", ".key", "credentials", ".pgpass"
|
|
132
|
-
],
|
|
133
|
-
|
|
134
|
-
"sensitiveGlobs": [
|
|
135
|
-
"**/.env",
|
|
136
|
-
"**/.env.*",
|
|
137
|
-
"**/.env.local",
|
|
138
|
-
"**/.env.production",
|
|
139
|
-
"**/*.pem",
|
|
140
|
-
"**/*.key",
|
|
141
|
-
"**/credentials",
|
|
142
|
-
"**/credentials.*",
|
|
143
|
-
"**/.pgpass",
|
|
144
|
-
"secrets/**"
|
|
145
|
-
],
|
|
146
|
-
|
|
147
|
-
"bashDenyPatterns": [],
|
|
148
|
-
|
|
149
|
-
"blockedReadTools": ["read", "grep", "glob", "view"],
|
|
150
|
-
"blockedWriteTools": ["write", "edit"]
|
|
151
|
-
},
|
|
152
|
-
|
|
153
|
-
"env": {
|
|
154
|
-
"enabled": true,
|
|
155
|
-
"allowedRoot": "."
|
|
156
|
-
},
|
|
157
|
-
|
|
83
|
+
"$schema": "https://raw.githubusercontent.com/itlackey/opencode-varlock/main/assets/varlock.schema.json",
|
|
158
84
|
"varlock": {
|
|
159
|
-
"enabled":
|
|
160
|
-
"
|
|
161
|
-
"command": "varlock",
|
|
162
|
-
"namespace": "app"
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
### Config sections
|
|
168
|
-
|
|
169
|
-
#### `guard` — EnvGuard hook
|
|
170
|
-
|
|
171
|
-
| Field | Type | Default | Description |
|
|
172
|
-
|---|---|---|---|
|
|
173
|
-
| `enabled` | `boolean` | `true` | Master switch for the `tool.execute.before` hook |
|
|
174
|
-
| `sensitivePatterns` | `string[]` | see above | Substring patterns — a path containing any of these is blocked |
|
|
175
|
-
| `sensitiveGlobs` | `string[]` | see above | Glob patterns — matched against full paths using `*`, `**`, `?` |
|
|
176
|
-
| `bashDenyPatterns` | `string[]` | `[]` | Extra bash substrings to deny (merged with ~30 built-ins) |
|
|
177
|
-
| `blockedReadTools` | `string[]` | `["read","grep","glob","view"]` | Tool names that trigger the file-read check |
|
|
178
|
-
| `blockedWriteTools` | `string[]` | `["write","edit"]` | Tool names that trigger the file-write check |
|
|
179
|
-
|
|
180
|
-
#### `env` — .env file loader
|
|
181
|
-
|
|
182
|
-
| Field | Type | Default | Description |
|
|
183
|
-
|---|---|---|---|
|
|
184
|
-
| `enabled` | `boolean` | `true` | Register the `load_env` tool |
|
|
185
|
-
| `allowedRoot` | `string` | `"."` | Path containment boundary (resolved relative to cwd) |
|
|
186
|
-
|
|
187
|
-
#### `varlock` — Varlock integration
|
|
188
|
-
|
|
189
|
-
| Field | Type | Default | Description |
|
|
190
|
-
|---|---|---|---|
|
|
191
|
-
| `enabled` | `boolean` | `false` | Explicitly enable Varlock tools |
|
|
192
|
-
| `autoDetect` | `boolean` | `true` | Probe for the CLI at startup and enable if found |
|
|
193
|
-
| `command` | `string` | `"varlock"` | Path or name of the Varlock binary |
|
|
194
|
-
| `namespace` | `string` | `"app"` | Default namespace for `load_secrets` / `secret_status` |
|
|
195
|
-
|
|
196
|
-
**Varlock resolution logic:**
|
|
197
|
-
|
|
198
|
-
- `enabled: true` → tools are registered (fails at runtime if CLI is missing)
|
|
199
|
-
- `enabled: false, autoDetect: true` → probes `which <command>`, enables if found
|
|
200
|
-
- `enabled: false, autoDetect: false` → Varlock is fully disabled
|
|
201
|
-
|
|
202
|
-
### Config merge behavior
|
|
203
|
-
|
|
204
|
-
Arrays are **replaced**, not concatenated. This means you can fully override the default glob list in your config file without inheriting the defaults:
|
|
205
|
-
|
|
206
|
-
```json
|
|
207
|
-
{
|
|
208
|
-
"guard": {
|
|
209
|
-
"sensitiveGlobs": ["secrets/**", "config/.env.*"]
|
|
85
|
+
"enabled": true,
|
|
86
|
+
"namespace": "myapp"
|
|
210
87
|
}
|
|
211
88
|
}
|
|
212
89
|
```
|
|
213
90
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
### Programmatic overrides
|
|
217
|
-
|
|
218
|
-
For project-specific customization beyond what JSON can express:
|
|
219
|
-
|
|
220
|
-
```typescript
|
|
221
|
-
// .opencode/plugin/secrets.ts
|
|
222
|
-
import { createVarlockPlugin } from "opencode-varlock/plugin"
|
|
223
|
-
|
|
224
|
-
export default createVarlockPlugin({
|
|
225
|
-
guard: {
|
|
226
|
-
sensitiveGlobs: [
|
|
227
|
-
"**/.env",
|
|
228
|
-
"**/.env.*",
|
|
229
|
-
"infra/secrets/**",
|
|
230
|
-
"deploy/*.key",
|
|
231
|
-
],
|
|
232
|
-
bashDenyPatterns: ["vault read", "aws secretsmanager"],
|
|
233
|
-
},
|
|
234
|
-
varlock: {
|
|
235
|
-
enabled: true,
|
|
236
|
-
command: "/usr/local/bin/varlock",
|
|
237
|
-
namespace: "prod",
|
|
238
|
-
},
|
|
239
|
-
})
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
## Glob patterns
|
|
243
|
-
|
|
244
|
-
The guard supports glob patterns alongside the existing substring patterns. Both are checked — a match on either blocks the access.
|
|
245
|
-
|
|
246
|
-
### Supported syntax
|
|
247
|
-
|
|
248
|
-
| Pattern | Matches | Example |
|
|
249
|
-
|---|---|---|
|
|
250
|
-
| `*` | Any characters except `/` | `*.pem` matches `server.pem` |
|
|
251
|
-
| `**` | Any characters including `/` | `secrets/**` matches `secrets/prod/db.key` |
|
|
252
|
-
| `**/` | Zero or more directory levels | `**/.env` matches `.env` and `config/.env` |
|
|
253
|
-
| `?` | Single character except `/` | `?.key` matches `a.key` |
|
|
254
|
-
|
|
255
|
-
### When to use which
|
|
256
|
-
|
|
257
|
-
**Substring patterns** are fast and filename-oriented. Use them for extensions and file names that should be blocked everywhere regardless of path:
|
|
258
|
-
|
|
259
|
-
```json
|
|
260
|
-
"sensitivePatterns": [".env", ".pem", "credentials"]
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
**Glob patterns** are structural and path-aware. Use them for directory-scoped rules and more precise matching:
|
|
264
|
-
|
|
265
|
-
```json
|
|
266
|
-
"sensitiveGlobs": [
|
|
267
|
-
"secrets/**",
|
|
268
|
-
"config/.env.*",
|
|
269
|
-
"deploy/**/*.key",
|
|
270
|
-
"**/node_modules/**/.env"
|
|
271
|
-
]
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
### How globs are checked
|
|
275
|
-
|
|
276
|
-
For file tool calls (`read`, `write`, `edit`, etc.), the glob is matched against the path argument directly.
|
|
277
|
-
|
|
278
|
-
For bash commands, the guard extracts file-path-like tokens from the command string and checks each one against the compiled globs. This catches things like `jq . secrets/config.json` even when the substring patterns wouldn't flag it.
|
|
279
|
-
|
|
280
|
-
## Tools
|
|
281
|
-
|
|
282
|
-
### `load_env`
|
|
283
|
-
|
|
284
|
-
Parses a `.env` file and sets `process.env`. Returns only variable **names**.
|
|
285
|
-
|
|
286
|
-
```
|
|
287
|
-
Agent → load_env(path: ".env")
|
|
288
|
-
← { loaded: ["DATABASE_URL", "REDIS_HOST"], skipped: ["NODE_ENV"] }
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
### `load_secrets` (Varlock)
|
|
292
|
-
|
|
293
|
-
Pulls secrets from Varlock and injects into `process.env`.
|
|
294
|
-
|
|
295
|
-
```
|
|
296
|
-
Agent → load_secrets(namespace: "prod", keys: ["db_url", "api_key"])
|
|
297
|
-
← { loaded: ["DB_URL", "API_KEY"], source: "varlock/prod" }
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
### `secret_status` (Varlock)
|
|
301
|
-
|
|
302
|
-
Read-only check of which secrets exist and which are loaded.
|
|
303
|
-
|
|
304
|
-
```
|
|
305
|
-
Agent → secret_status(namespace: "app")
|
|
306
|
-
← { total: 5, loaded: 3, unloaded: 2, keys: [...] }
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
## Permission sets
|
|
310
|
-
|
|
311
|
-
The `assets/permissions.json` file contains three tiers (standard, strict, lockdown) plus an example agent definition. Copy the tier that fits your threat model into `opencode.json`.
|
|
312
|
-
|
|
313
|
-
These permission rules complement the EnvGuard hook — the rules handle fast-path blocking while the hook catches edge cases the glob-based rules miss.
|
|
314
|
-
|
|
315
|
-
## Architecture
|
|
316
|
-
|
|
317
|
-
### Why three layers?
|
|
318
|
-
|
|
319
|
-
**Permissions alone aren't enough.** An agent can try `python3 -c "print(open('.env').read())"` or `python -c "import os; print(os.getenv('API_KEY'))"` - the obvious glob rules won't catch every runtime exfiltration path.
|
|
320
|
-
|
|
321
|
-
**Prompt instructions alone aren't enough.** Telling an agent "never read .env" is a soft boundary the model can reason past.
|
|
322
|
-
|
|
323
|
-
**The plugin hook is the hard boundary.** `tool.execute.before` runs before every built-in tool call, inspects actual arguments, and throws an error the agent cannot suppress. The error message redirects it to the approved tools.
|
|
324
|
-
|
|
325
|
-
### What the agent sees
|
|
326
|
-
|
|
327
|
-
```
|
|
328
|
-
✓ "Loaded 5 variables: DATABASE_URL, API_KEY, REDIS_HOST, JWT_SECRET, SMTP_PASS"
|
|
329
|
-
✓ Writes code: const db = new Client(process.env.DATABASE_URL)
|
|
330
|
-
✗ cat .env → Blocked: deny pattern
|
|
331
|
-
✗ echo $API_KEY → Blocked: deny pattern
|
|
332
|
-
✗ python -c "os.getenv" → Blocked: runtime env read
|
|
333
|
-
✗ python -c "open..." → Blocked: sensitive file
|
|
334
|
-
✗ jq . secrets/app.json → Blocked: matches glob "secrets/**"
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
## Advanced: composing individual pieces
|
|
338
|
-
|
|
339
|
-
Every component is exported for use in custom plugins:
|
|
91
|
+
## Docs
|
|
340
92
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
93
|
+
- setup and overrides: `docs/configuration.md`
|
|
94
|
+
- security model and limitations: `docs/security.md`
|
|
95
|
+
- tests and validation: `docs/testing.md`
|
|
96
|
+
- exported APIs and tools: `docs/api.md`
|
|
97
|
+
- Docker + pass guide: `docs/docker-pass-guide.md`
|
|
346
98
|
|
|
347
|
-
|
|
348
|
-
const config = loadConfig(process.cwd(), {
|
|
349
|
-
guard: { sensitiveGlobs: ["my-secrets/**"] },
|
|
350
|
-
})
|
|
99
|
+
## Useful files
|
|
351
100
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
// Use just the tool
|
|
356
|
-
const loadEnv = createLoadEnvTool(config.env)
|
|
357
|
-
|
|
358
|
-
// Test a glob pattern
|
|
359
|
-
const regex = globToRegex("**/.env.*")
|
|
360
|
-
regex.test("config/.env.production") // true
|
|
361
|
-
```
|
|
101
|
+
- default config: `assets/varlock.config.json`
|
|
102
|
+
- JSON schema: `assets/varlock.schema.json`
|
|
103
|
+
- recommended permission configurations: `assets/permissions.json`
|
|
362
104
|
|
|
363
105
|
## License
|
|
364
106
|
|
package/assets/permissions.json
CHANGED
|
@@ -18,14 +18,22 @@
|
|
|
18
18
|
"head *.env*": "deny",
|
|
19
19
|
"tail *.env*": "deny",
|
|
20
20
|
"grep * .env*": "deny",
|
|
21
|
+
"sed * .env*": "deny",
|
|
22
|
+
"awk * .env*": "deny",
|
|
21
23
|
"echo $*": "deny",
|
|
22
24
|
"python*getenv*": "deny",
|
|
23
25
|
"python*os.environ*": "deny",
|
|
26
|
+
"python*open*env*": "deny",
|
|
24
27
|
"node*process.env*": "deny",
|
|
28
|
+
"node*readFileSync*env*": "deny",
|
|
25
29
|
"printenv*": "deny",
|
|
26
30
|
"env": "deny",
|
|
27
31
|
"export -p": "deny",
|
|
28
32
|
"source .env*": "deny",
|
|
33
|
+
"varlock printenv*": "deny",
|
|
34
|
+
"varlock load --show*": "deny",
|
|
35
|
+
"varlock load --format*": "deny",
|
|
36
|
+
"varlock load -f*": "deny",
|
|
29
37
|
"npm test": "allow",
|
|
30
38
|
"npm run *": "allow",
|
|
31
39
|
"bun test": "allow",
|
|
@@ -42,22 +50,27 @@
|
|
|
42
50
|
"permission": {
|
|
43
51
|
"read": {
|
|
44
52
|
"*.env*": "deny",
|
|
53
|
+
"*.env.schema": "allow",
|
|
54
|
+
"*.env.example": "allow",
|
|
45
55
|
"*.pem": "deny",
|
|
46
56
|
"*.key": "deny",
|
|
47
57
|
"*credentials*": "deny",
|
|
48
58
|
"*.pgpass": "deny",
|
|
59
|
+
"*varlock.config*": "deny",
|
|
49
60
|
"*": "ask"
|
|
50
61
|
},
|
|
51
62
|
"write": {
|
|
52
63
|
"*.env*": "deny",
|
|
53
64
|
"*.pem": "deny",
|
|
54
65
|
"*.key": "deny",
|
|
66
|
+
"*varlock.config*": "deny",
|
|
55
67
|
"*": "ask"
|
|
56
68
|
},
|
|
57
69
|
"edit": {
|
|
58
70
|
"*.env*": "deny",
|
|
59
71
|
"*.pem": "deny",
|
|
60
72
|
"*.key": "deny",
|
|
73
|
+
"*varlock.config*": "deny",
|
|
61
74
|
"*": "ask"
|
|
62
75
|
},
|
|
63
76
|
"bash": {
|
|
@@ -67,20 +80,39 @@
|
|
|
67
80
|
"head *.env*": "deny",
|
|
68
81
|
"tail *.env*": "deny",
|
|
69
82
|
"grep * .env*": "deny",
|
|
83
|
+
"sed * .env*": "deny",
|
|
84
|
+
"awk * .env*": "deny",
|
|
85
|
+
"cut * .env*": "deny",
|
|
86
|
+
"sort .env*": "deny",
|
|
87
|
+
"dd if=.env*": "deny",
|
|
88
|
+
"tee * .env*": "deny",
|
|
89
|
+
"xxd .env*": "deny",
|
|
70
90
|
"echo $*": "deny",
|
|
71
91
|
"python*getenv*": "deny",
|
|
72
92
|
"python*os.environ*": "deny",
|
|
93
|
+
"python*open*env*": "deny",
|
|
73
94
|
"node*process.env*": "deny",
|
|
95
|
+
"node*readFileSync*env*": "deny",
|
|
96
|
+
"ruby*File.read*env*": "deny",
|
|
74
97
|
"printenv*": "deny",
|
|
75
98
|
"env": "deny",
|
|
76
99
|
"env *": "deny",
|
|
77
100
|
"export -p": "deny",
|
|
78
101
|
"declare -x": "deny",
|
|
102
|
+
"compgen -v": "deny",
|
|
103
|
+
"compgen -A variable": "deny",
|
|
104
|
+
"typeset -x": "deny",
|
|
79
105
|
"source .env*": "deny",
|
|
80
106
|
". .env*": "deny",
|
|
81
107
|
"set -a*": "deny",
|
|
82
108
|
"curl *env*": "deny",
|
|
83
109
|
"wget *env*": "deny",
|
|
110
|
+
"varlock printenv*": "deny",
|
|
111
|
+
"varlock load --show*": "deny",
|
|
112
|
+
"varlock load --format*": "deny",
|
|
113
|
+
"varlock load -f*": "deny",
|
|
114
|
+
"*base64*|*bash*": "deny",
|
|
115
|
+
"*base64*|*sh*": "deny",
|
|
84
116
|
"npm test": "allow",
|
|
85
117
|
"npm run *": "allow",
|
|
86
118
|
"bun test": "allow",
|
|
@@ -97,20 +129,25 @@
|
|
|
97
129
|
"permission": {
|
|
98
130
|
"read": {
|
|
99
131
|
"*.env*": "deny",
|
|
132
|
+
"*.env.schema": "allow",
|
|
133
|
+
"*.env.example": "allow",
|
|
100
134
|
"*.pem": "deny",
|
|
101
135
|
"*.key": "deny",
|
|
102
136
|
"*credentials*": "deny",
|
|
103
137
|
"*secret*": "deny",
|
|
138
|
+
"*varlock.config*": "deny",
|
|
104
139
|
"*": "allow"
|
|
105
140
|
},
|
|
106
141
|
"write": {
|
|
107
142
|
"*.env*": "deny",
|
|
143
|
+
"*varlock.config*": "deny",
|
|
108
144
|
"*.ts": "ask",
|
|
109
145
|
"*.js": "ask",
|
|
110
146
|
"*": "deny"
|
|
111
147
|
},
|
|
112
148
|
"edit": {
|
|
113
149
|
"*.env*": "deny",
|
|
150
|
+
"*varlock.config*": "deny",
|
|
114
151
|
"*.ts": "ask",
|
|
115
152
|
"*.js": "ask",
|
|
116
153
|
"*": "deny"
|
|
@@ -141,17 +178,27 @@
|
|
|
141
178
|
"permission": {
|
|
142
179
|
"read": {
|
|
143
180
|
"*.env*": "deny",
|
|
181
|
+
"*.env.schema": "allow",
|
|
182
|
+
"*.env.example": "allow",
|
|
144
183
|
"*.pem": "deny",
|
|
184
|
+
"*varlock.config*": "deny",
|
|
145
185
|
"*": "allow"
|
|
146
186
|
},
|
|
147
187
|
"bash": {
|
|
148
188
|
"cat *.env*": "deny",
|
|
189
|
+
"sed * .env*": "deny",
|
|
190
|
+
"awk * .env*": "deny",
|
|
149
191
|
"printenv*": "deny",
|
|
150
192
|
"echo $*": "deny",
|
|
151
193
|
"python*getenv*": "deny",
|
|
152
194
|
"python*os.environ*": "deny",
|
|
195
|
+
"python*open*env*": "deny",
|
|
153
196
|
"node*process.env*": "deny",
|
|
154
197
|
"env": "deny",
|
|
198
|
+
"compgen -v": "deny",
|
|
199
|
+
"varlock printenv*": "deny",
|
|
200
|
+
"varlock load --format*": "deny",
|
|
201
|
+
"varlock load --show*": "deny",
|
|
155
202
|
"docker *": "allow",
|
|
156
203
|
"npm *": "allow",
|
|
157
204
|
"bun *": "allow",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/itlackey/opencode-varlock/main/assets/varlock.schema.json",
|
|
3
3
|
"$comment": "opencode-varlock configuration. Place in project root or .opencode/",
|
|
4
4
|
|
|
5
5
|
"guard": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
".pem",
|
|
14
14
|
".key",
|
|
15
15
|
"credentials",
|
|
16
|
-
".pgpass"
|
|
16
|
+
".pgpass",
|
|
17
|
+
"varlock.config"
|
|
17
18
|
],
|
|
18
19
|
|
|
19
20
|
"sensitiveGlobs": [
|
|
@@ -26,7 +27,9 @@
|
|
|
26
27
|
"**/credentials",
|
|
27
28
|
"**/credentials.*",
|
|
28
29
|
"**/.pgpass",
|
|
29
|
-
"secrets/**"
|
|
30
|
+
"secrets/**",
|
|
31
|
+
"**/varlock.config.json",
|
|
32
|
+
"**/.opencode/varlock.config.json"
|
|
30
33
|
],
|
|
31
34
|
|
|
32
35
|
"bashDenyPatterns": [],
|
|
@@ -43,7 +46,7 @@
|
|
|
43
46
|
},
|
|
44
47
|
|
|
45
48
|
"varlock": {
|
|
46
|
-
"$comment": "Varlock integration -
|
|
49
|
+
"$comment": "Varlock integration - uses varlock load/printenv to pull secrets from configured backends",
|
|
47
50
|
|
|
48
51
|
"enabled": false,
|
|
49
52
|
"autoDetect": true,
|
package/dist/config.d.ts
CHANGED
|
@@ -36,6 +36,11 @@ export type PluginConfig = {
|
|
|
36
36
|
varlock: VarlockConfig;
|
|
37
37
|
};
|
|
38
38
|
export declare const DEFAULT_CONFIG: PluginConfig;
|
|
39
|
+
/**
|
|
40
|
+
* Validates a parsed config object against the expected schema.
|
|
41
|
+
* Returns an array of human-readable error strings (empty = valid).
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateConfig(config: unknown, logger?: ConfigLogger): string[];
|
|
39
44
|
export declare function loadConfig(cwd: string, overrides?: DeepPartial<PluginConfig>, logger?: ConfigLogger): PluginConfig;
|
|
40
45
|
type DeepPartial<T> = {
|
|
41
46
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE1B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAA;IAClB,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE;IACjC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;IAC1C,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAChC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE1B,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,UAAU,EAAE,OAAO,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,WAAW,CAAA;IAClB,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,aAAa,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,cAAc,EAAE,YAwC5B,CAAA;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,OAAO,EACf,MAAM,CAAC,EAAE,YAAY,GACpB,MAAM,EAAE,CA8HV;AAwFD,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,SAAS,GAAE,WAAW,CAAC,YAAY,CAAM,EACzC,MAAM,CAAC,EAAE,YAAY,GACpB,YAAY,CAkFd;AAED,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAChE,CAAA;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACrD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,GACrB,CAAC,CAyBH;AAED,YAAY,EAAE,WAAW,EAAE,CAAA"}
|