[contextlock]
Integrity & provenance for AI instruction files

Your agent trusts its instructions. Prove they haven’t changed.

A SKILL.md, CLAUDE.md, rules file or prompt pack steers a model with near system-prompt privilege — yet ships as plain markdown anything can silently edit. ContextLock gives those files the same authenticity and integrity guarantees software already expects of packages and binaries, checked before they reach the model.

$ npm i -g @contextlock/cli-user
Quick start
Apache-2.0 Ed25519 + Sigstore keyless npm provenance-attested 375 tests
SPEC §2 — Why this must exist

Instruction files are executable in effect, but treated as data.

Git proves history, not provenance. A commit says “this content entered this repo,” never who authored it or whether it matches what a publisher released. The highest-value files — ~/.claude/CLAUDE.md, global skills, plugin caches — live outside any repo entirely: mutable, invisible, implicitly trusted.

Worse, prompt injection can persist. An injected agent appends a line to its own CLAUDE.md and the compromise survives every future session — the agent-world equivalent of malware writing to a startup script. This is no longer hypothetical.

“Require cryptographic signatures (ed25519) on all published skills; reject unsigned installs.”

OWASP Agentic Skills Top 10 — AST01, Malicious Skills

The Agent Skills spec — adopted by 40+ clients — defines no integrity or signing mechanism at all. That silence is the gap ContextLock fills. And because adaptive attacks bypass content-scanning defenses 78–93% of the time, prevention beats detection here: ContextLock doesn’t judge content, it makes tampering and impersonation detectable no matter how clever the payload.

The incident record — 2026
JAN–FEB
ClawHavoc341 malicious skills on ClawHub (~11.9% of the registry). ~300k OpenClaw users exposed, delivering the AMOS macOS stealer.
FEB 05
ToxicSkills — SnykOf 3,984 skills scanned, 36.8% carried a flaw, 534 critical. 91% of confirmed-malicious skills used prompt injection.
2025–26
Config-file CVEsCVE-2025-59536 & CVE-2026-21852 — repo-controlled config files triggering command execution and credential theft.
ONGOING
Invisible Unicode injectionUnicode Tag characters (U+E0000–E007F) smuggled inside SKILL.md — invisible to a human reviewer, live to the model.
SPEC §6 — Mechanism

Sign once. Verify on every load.

Publishers seal a package into a signed manifest. Users pin the keys they trust. Every time a protected file loads, the engine re-checks the whole chain before a single byte reaches the model — then allows, warns, or blocks by policy.

Publisher — seal

  1. 01normalize — UTF-8 / LF / no-BOM, at sign time only
  2. 02lint — reject Unicode Tags, zero-width, bidi controls
  3. 03hash — SHA-256 + length over the exact bytes
  4. 04manifest — contextlock/2: version, expiry, files
  5. 05envelope — DSSE, Ed25519 over PAE → one artifact

User — verify

  1. 01discover — bounded envelope lookup, no walk-up
  2. 02signature — against pinned keys or rotatable root
  3. 03anti-rollback — version ≥ highest ever seen
  4. 04expiry — manifest must not be stale (freeze defense)
  5. 05hash + length — compare, then a verdict
trusted

Signature valid, rollback & expiry pass, hash matches.

policy · allow
modified

File content or length changed since it was signed or sealed.

policy · block, block, audit
untrusted

No envelope, unknown signer, or a file the manifest never listed.

policy · block, warn, audit
SPEC §4 — Threat model

What a signed manifest actually buys you.

Each guarantee is a named threat with a concrete mechanism. Nothing here judges whether content is safe — only whether it is authentic and unchanged.

ID
Threat
Mechanism
T1
Local tampering after download or review
SHA-256 mismatch vs seal or signed manifest
T2
Prompt-injection persistence — an agent editing its own instruction files
Seal / manifest mismatch on the next load; write-deny on protected paths
T3
A malicious mirror or marketplace serving altered files
Signed manifest + publisher key pinning
T5
Packages impersonating a known publisher
Explicit key / identity pinning — no trust from names or URLs
T7
Rollback — replaying an older, vulnerable release
Monotonic version counter + local highest-seen state
T8
Freeze — withholding updates indefinitely
Mandatory expires_at on every manifest
T11
Invisible Unicode smuggling inside markdown
Exact-byte hashing + sign-time content lints

The honest boundary: ContextLock hardens the distribution and persistence channels. A same-privilege attacker with code execution as you can re-seal local state — the managed tier moves that goalpost to admin privilege; beyond it is EDR territory, and the spec says so. Full model in SPEC §4.

SPEC §5 — Trust models

From a solo author to a signing pipeline.

Pick the ceremony that fits. All three produce the same three verdicts and compose freely.

Mode 0 · TOFU

Seal it yourself

Reviewed a file you can’t get signed — your own ~/.claude/CLAUDE.md? Pin its bytes locally. Any later edit reads as modified. Zero publisher, zero keys.

Defeats T2 persistence on day one
Profile A · keys

Signed manifests

Publisher signs with a raw Ed25519 key; users pin the public key or a rotatable, revocable root. Works fully offline. A reviewer can countersign — demand a threshold of signers.

For solo authors & teams
Profile B · keyless

Sigstore in CI

No key to hold. Sign in GitHub Actions; users pin the workflow’s OIDC identity, exactly like npm provenance. Verification is fully offline against a pinned trusted root.

For published, audited packages
Usage — Two commands to a verdict

Verify what you install. Sign what you publish.

verify@contextlock/cli-user
# trust a publisher, then verify before use
$ npm i -g @contextlock/cli-user
$ contextlock trust add "Acme Security" ./acme-public.key
$ contextlock verify ./skills/acme/SKILL.md
  ✓ trusted (publisher: Acme Security, key: cl-acme-2026)

# install a package: verify EVERYTHING, or write nothing
$ contextlock install ./downloads/acme-skills \
      --dest ./.claude/skills/acme
publish@contextlock/cli-publisher
# one command: keygen + manifest + DSSE signature
$ npm i -g @contextlock/cli-publisher
$ contextlock-publisher protect ./my-package \
      --sign --name "Acme Security" --version 1

  generated key · fingerprint c8e4b7d5…
  wrote contextlock.dsse.json · 2 files sealed

# a reviewer can countersign the exact bytes
$ contextlock-publisher countersign \
      ./my-package/contextlock.dsse.json --key reviewer.key

Every @contextlock/* package publishes to npm with a provenance attestation. Full API, CI recipes and integration guides in the README and SPEC.

Adapters — Where it plugs in

One verification engine, every place a file becomes a prompt.

Claude CodeInstallable plugin: a PreToolUse hook verifies instruction files before context assembly.
OpenClawBlocking install-gate and load middleware — the adapter written for the ClawHavoc threat.
VS Code & CopilotWatch copilot-instructions.md, Continue, Cody, Kiro steering files.
MCP serverExpose verify_file as a tool any MCP-capable assistant can call.
GitHub ActionsDrop-in signing recipes for Profile A (key) and Profile B (keyless).
nono interopConsumes nono keyless skill attestations, with an explicit reduced-guarantee warning.
Transparency logAppend-only inclusion proofs — design drafted in the repo.
Bring your ownThe core engine is a library. Any tool that reads local markdown can gate on a verdict.
SPEC §3 — What it is, and is not

Verified means authentic and unmodified — not safe. A trusted publisher can still publish harmful instructions. ContextLock establishes provenance, not content safety. It does the prevention half, deliberately, and composes with the scanning you already run.

Open source · Apache-2.0

Give the files that program your agent a seal worth checking.

$ npm i -g @contextlock/cli-user
View on GitHub Read the spec