@hamzaabili/opencode-integrity 0.0.0-stage → 0.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## 0.1.1
4
+
5
+ - First npm-published build. 0.1.0 was superseded before publication because
6
+ npm 9 created an unapprovable staged placeholder during the initial release.
7
+ - No functional changes from 0.1.0.
8
+
9
+ ## 0.1.0
10
+
11
+ First release.
12
+
13
+ - Audit, lock, check, diff and policy CLI with JSON and SARIF output.
14
+ - Lockfile (`opencode.lock.json`) for plugins, MCP configuration, MCP tool
15
+ descriptors and skills.
16
+ - Runtime capture of live MCP tool descriptions and input schemas, including
17
+ remote servers and Code Mode.
18
+ - Warn/enforce modes: disable changed MCP servers, remove changed skills, deny
19
+ changed MCP tools and skills before execution.
20
+ - Plugin content hashing, detected capabilities and version/source pinning.
21
+ - Deterministic suspicious-content checks (zero-width, bidi, HTML comments,
22
+ hidden instructions, exfiltration language).
23
+ - `integrity_status` and `integrity_lock` tools plus `/integrity` command.
24
+ - V1 static audit adapter; V2 full runtime adapter.
25
+ - Zero runtime dependencies; local only; no telemetry.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hamza-Abili
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,190 @@
1
- # Temporary Holding Version
1
+ # opencode-integrity
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [![CI](https://github.com/Hamza-Abili/opencode-integrity/actions/workflows/ci.yml/badge.svg)](https://github.com/Hamza-Abili/opencode-integrity/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/%40hamzaabili%2Fopencode-integrity)](https://www.npmjs.com/package/@hamzaabili/opencode-integrity)
5
+ [![npm downloads](https://img.shields.io/npm/dt/%40hamzaabili%2Fopencode-integrity)](https://www.npmjs.com/package/@hamzaabili/opencode-integrity)
6
+ [![GitHub stars](https://img.shields.io/github/stars/Hamza-Abili/opencode-integrity?style=social)](https://github.com/Hamza-Abili/opencode-integrity/stargazers)
7
+ [![license](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
8
+
9
+ **The tool you approved is not the tool you are running.**
10
+
11
+ `opencode-integrity` locks what OpenCode can load — plugin content, MCP tool
12
+ descriptions and schemas, and skill files — and detects when any of them
13
+ change. No proxy, no config rewrite, no cloud. Local, zero runtime
14
+ dependencies, OpenCode V1 and V2.
15
+
16
+ ```text
17
+ audit → see plugins, MCP tools and skills with capabilities and hashes
18
+ lock → write opencode.lock.json (commit it)
19
+ check → fail CI when anything drifts
20
+ runtime→ warn or deny changed MCP tools and skills during a session
21
+ ```
22
+
23
+ ## Why
24
+
25
+ An MCP tool description is not inert data: it is instructions the model reads.
26
+ A server can serve one toolset today and a different one tomorrow. Skills are
27
+ Markdown files that can be edited after review. Plugins are npm/Git code that
28
+ runs in the OpenCode server with the agent's privileges. OpenCode policies
29
+ (`plugin.use`, `mcp.use`, `skill.use`) only match names; they do not verify
30
+ content.
31
+
32
+ Existing MCP scanners are on-demand CLIs, and the strongest pinning tool
33
+ (`mcp-pin`) is a stdio proxy for other clients. This is the OpenCode-native
34
+ layer: it sees what OpenCode actually loaded, including remote MCP servers and
35
+ Code Mode, and covers plugins and skills too.
36
+
37
+ ## Install (OpenCode V2)
38
+
39
+ ```jsonc
40
+ {
41
+ "$schema": "https://opencode.ai/config.json",
42
+ "plugins": [
43
+ {
44
+ "package": "@hamzaabili/opencode-integrity",
45
+ "options": { "mode": "warn" }
46
+ }
47
+ ]
48
+ }
49
+ ```
50
+
51
+ ## Install (OpenCode V1)
52
+
53
+ ```jsonc
54
+ {
55
+ "plugin": [
56
+ ["@hamzaabili/opencode-integrity", { "mode": "warn" }]
57
+ ]
58
+ }
59
+ ```
60
+
61
+ V1 can hash project plugins, MCP configuration and skills, and in `enforce`
62
+ mode it blocks changed MCP configuration and skills. The V1 API does not expose
63
+ live MCP tool descriptors, so tool-level drift is V2-only.
64
+
65
+ ## Quick start
66
+
67
+ ```sh
68
+ # 1. See what is loaded, without a lockfile
69
+ npx @hamzaabili/opencode-integrity audit
70
+
71
+ # 2. Inside OpenCode, capture the live MCP tool definitions
72
+ /integrity lock
73
+
74
+ # 3. Commit the lockfile
75
+ git add opencode.lock.json
76
+
77
+ # 4. In CI
78
+ npx @hamzaabili/opencode-integrity check --format sarif
79
+ ```
80
+
81
+ `/integrity lock` is important: only the running OpenCode instance can see the
82
+ tool descriptions and schemas returned by MCP servers (local and remote, with
83
+ or without Code Mode). The CLI locks project plugins, MCP configuration and
84
+ skills; it preserves runtime tool hashes when the server configuration did not
85
+ change.
86
+
87
+ ## What is hashed
88
+
89
+ | Asset | Fields |
90
+ | --- | --- |
91
+ | Plugin | package.json, every package file (capped at 5000 files / 50 MiB), version, source, detected capabilities |
92
+ | MCP server | transport, command, URL, cwd, environment/header **names** and redacted values, codemode |
93
+ | MCP tool | name, description, input/output schema, annotations, suspicious-instruction scan |
94
+ | Skill | full `SKILL.md` content, size, suspicious-instruction scan |
95
+
96
+ Secret-looking environment values and headers (`TOKEN`, `KEY`, `SECRET`,
97
+ `PASSWORD`, `AUTHORIZATION`, `COOKIE`, `CREDENTIAL`) are replaced with
98
+ `[redacted]` before hashing, so rotating a token does not create drift. Their
99
+ names still change the hash.
100
+
101
+ ## Runtime modes
102
+
103
+ | Mode | Behavior |
104
+ | --- | --- |
105
+ | `warn` (default) | Inject a drift report into the session and log it; nothing is blocked. |
106
+ | `enforce` | Disable MCP servers whose configuration changed, remove changed skills, and deny changed MCP tools and skills before execution. |
107
+
108
+ `enforce` is fail-closed for **asset drift**, not a sandbox. A plugin that is
109
+ already loaded cannot be unloaded by a plugin hook; review plugin changes with
110
+ the lock diff and restart OpenCode. MCP and skill transforms are applied at
111
+ startup, so after `/integrity lock` in an existing session, reload to re-enable
112
+ previously quarantined assets.
113
+
114
+ ## CLI
115
+
116
+ ```sh
117
+ npx @hamzaabili/opencode-integrity audit [--json] [--strict]
118
+ npx @hamzaabili/opencode-integrity lock
119
+ npx @hamzaabili/opencode-integrity check [--format text|json|sarif]
120
+ npx @hamzaabili/opencode-integrity diff
121
+ npx @hamzaabili/opencode-integrity policy
122
+ ```
123
+
124
+ - `check` exits `1` on drift or when no lockfile exists.
125
+ - CLI `check` verifies project files/configuration; live MCP tool descriptors are
126
+ only verifiable by the running V2 adapter. Use `/integrity check` or the
127
+ `integrity_status` tool inside OpenCode for the full check.
128
+ - `audit --strict` exits `1` on drift or an unlocked project.
129
+ - `policy` emits native OpenCode `mcp.use`, `skill.use` and `plugin.use`
130
+ allow statements from the lockfile. It is an allowlist, not a hash check;
131
+ pair it with `check`/runtime enforcement.
132
+
133
+ ## Options
134
+
135
+ | Option | Default | Meaning |
136
+ | --- | --- | --- |
137
+ | `lockfile` | `<project>/opencode.lock.json` | Lockfile path. |
138
+ | `mode` | `"warn"` | `warn` or `enforce`. |
139
+ | `include` | `["plugins","mcp","skills"]` | Asset classes to inspect. |
140
+ | `ignore` | `[]` | Asset ids or globs to ignore, e.g. `mcp:local-dev`, `skill:experimental-*`. |
141
+ | `includeGlobal` | `false` | Include global MCP config and, at runtime, global plugins/skills. Project-scoped assets are the default so a committed lock stays portable. |
142
+ | `trace` | unset | Reserved for redacted diagnostics. |
143
+
144
+ ## Capabilities and suspicious content
145
+
146
+ `audit` reports heuristic capabilities found in plugin entry code (`network`,
147
+ `filesystem`, `process`, `environment`, `dynamic-code`) and flags zero-width
148
+ characters, bidi controls, HTML comments, “ignore previous instructions”,
149
+ “do not tell”, and exfiltration language in tool descriptions and skills.
150
+
151
+ These are **signals**, not proof. They are deliberately deterministic and
152
+ offline; a clean scan does not make a plugin safe.
153
+
154
+ ## Differences from other tools
155
+
156
+ | | opencode-integrity | mcp-pin | mcp-scan / Cisco | Socket/npm audit |
157
+ | --- | --- | --- | --- | --- |
158
+ | OpenCode-native runtime | yes | no (proxy) | no (on-demand) | no |
159
+ | MCP tool descriptor pinning | yes | yes (stdio only) | scan only | no |
160
+ | Remote MCP | yes | no | yes | no |
161
+ | Plugins and skills | yes | no | no | packages only |
162
+ | Runtime deny/quarantine | yes | proxy block | no | no |
163
+ | Policy/SARIF output | yes | no | partial | no |
164
+ | Zero runtime deps | yes | yes | varies | varies |
165
+
166
+ ## Security model
167
+
168
+ The lockfile is a review artifact, not a signature. It catches changes between
169
+ the version you reviewed and the version that runs; it does not prove that the
170
+ reviewed version was safe. Use it with code review, OpenCode permissions,
171
+ `opencode-sandbox`, and least-privilege MCP servers.
172
+
173
+ Read [SECURITY.md](SECURITY.md) before enabling `enforce` on a shared machine.
174
+
175
+ ## Support
176
+
177
+ - Bugs: [open an issue](https://github.com/Hamza-Abili/opencode-integrity/issues/new/choose)
178
+ with `audit --json` and the relevant lock diff (redact secrets).
179
+ - Questions: [Discussions](https://github.com/Hamza-Abili/opencode-integrity/discussions).
180
+ - Security: [private advisory](https://github.com/Hamza-Abili/opencode-integrity/security/advisories/new),
181
+ never a public issue.
182
+
183
+ ## Development
184
+
185
+ ```sh
186
+ bun install
187
+ bun run ci # biome + tsc + tests + build + smoke
188
+ ```
189
+
190
+ MIT. Zero runtime dependencies.
package/SECURITY.md ADDED
@@ -0,0 +1,61 @@
1
+ # Security
2
+
3
+ ## What this tool is
4
+
5
+ `opencode-integrity` records SHA-256 hashes of OpenCode plugin content, MCP
6
+ server configuration, MCP tool descriptors and skill files, then compares them
7
+ with the running environment. It is a **drift detector**, not a malware
8
+ scanner, sandbox, signature verifier or proof of safety.
9
+
10
+ A lockfile catches the classic rug pull: the plugin/MCP/skill you reviewed is
11
+ not the one now loaded. It cannot tell whether the reviewed version was
12
+ malicious.
13
+
14
+ ## Trust model
15
+
16
+ - `opencode.lock.json` is committed and reviewed like code. Anyone who can
17
+ change both the lockfile and the asset can approve the change.
18
+ - The model-callable `integrity_lock` tool is exposed only when an evaluate
19
+ hook can force the dedicated `integrity_lock` action to `ask`; the
20
+ user-invoked `/integrity lock` command asks for the same permission.
21
+ - `warn` mode never blocks; `enforce` mode blocks **changed** assets only.
22
+ - Runtime enforcement covers MCP tools and skills that the plugin can observe.
23
+ A plugin that is already executing cannot be unloaded by a plugin hook.
24
+ - V1 enforces static MCP configuration and skill drift, but cannot verify live
25
+ MCP tool descriptors; tool-level enforcement is V2-only.
26
+
27
+ ## Secrets
28
+
29
+ Config hashes replace values of secret-looking keys (`TOKEN`, `SECRET`,
30
+ `PASSWORD`, `API_KEY`, `AUTHORIZATION`, `COOKIE`, `CREDENTIAL`) with
31
+ `[redacted]`. The keys still affect the hash; rotating a token does not.
32
+
33
+ The lockfile contains hashes, paths, versions, capability labels and
34
+ suspicious-content labels. It never stores tool descriptions, skill bodies or
35
+ environment values.
36
+
37
+ ## Capability and poisoning heuristics
38
+
39
+ Capability detection and suspicious-instruction labels are deterministic text
40
+ heuristics. They produce false positives and false negatives. A clean report is
41
+ not a safety guarantee; a suspicious label is a reason to review, not proof of
42
+ malice.
43
+
44
+ ## Limitations
45
+
46
+ - MCP tool descriptors are only visible at runtime. A CLI `check` verifies
47
+ configuration and files, not what a server returns today.
48
+ - A server can change behavior without changing names, descriptions or schemas.
49
+ - A tool can be malicious while its descriptor is clean.
50
+ - `enforce` disables changed MCP servers and skills at load time; a changed
51
+ plugin is reported but cannot be unloaded by a hook.
52
+ - The lockfile is not signed. Protect the repository and review lockfile diffs.
53
+ - Windows is not tested. Use WSL.
54
+
55
+ ## Reporting
56
+
57
+ Open a private advisory:
58
+ <https://github.com/Hamza-Abili/opencode-integrity/security/advisories/new>
59
+
60
+ Do not include live tokens, private MCP URLs or full environment dumps. A
61
+ minimal reproduction with fake values is enough.