Skip to content

strangerDanger v0.2.0

Latest

Choose a tag to compare

@gitdamnit gitdamnit released this 17 Oct 00:27
· 2 commits to master since this release
b634ce5

strangerDanger v0.2.0

Secret and PII redaction guard for AI coding agents — now enforcing at the
OpenCode V2 request boundaries.

strangerDanger does not guarantee prevention of every secret leak. It
protects the specific surfaces listed below and fails closed everywhere else.
Read the limitations before relying on it.

Features

  • Boundary redaction, not just auditing. Registers all four V2 model-request
    hooks — session.prompt, session.context, session.generate,
    session.title — plus session.compaction and tool.execute.after, so
    prompts, tool results, transient generations, titles, and compaction
    transcripts are scanned immediately before transmission. Redaction is
    ordering-independent: whatever path a request takes, its assembled
    system/messages are re-scanned before dispatch.
  • 236 detection rules — 221 vendored from gitleaks (MIT), 12 clean-room
    additions for AI/ML providers, and 3 entropy detectors.
  • Standalone CLI (sd): scan, redact, audit, rules, allowlist,
    version.
  • Five plugin tools: sd_status, sd_audit, sd_allowlist_add,
    sd_allowlist_show, sd_scan.
  • Allowlist by fingerprint, rule ID, path, or regex
    (.strangerdanger-allowlist.toml).
  • Independent: requires no companion plugin; the only interop surface is the
    optional, read-only, semver-versioned @gitdamnit/stranger-danger/engine export.

Security improvements

  • File reads never modify files. The pre-read hook is strictly read-only; a
    detected secret no longer rewrites the file on disk.
  • Effective outbound protection. 0.1.0's V1 event handler only audited
    after the fact. 0.2.0 redacts before transmission.
  • Fail-closed by construction. Bounded, windowed scanning: content over the
    size ceiling, a window timeout/error, a cyclic structure, or nesting beyond 32
    levels is replaced with an explicit marker instead of being passed through.
  • Cycle-safe structured redaction — fixes a fail-open where a self-referential
    tool output left the entire result, including plain string secrets, unredacted.
  • Tool.Error.metadata is redacted (it is surfaced to the model).
  • No raw secrets in output. CLI, tools, and the audit log report safe metadata
    only (rule, description, source, line/column, 8-hex fingerprint, redaction
    token). The audit log never stores the matched value.
  • Safe sd redact — atomic write (temp + fsync + rename); no plaintext backup
    in the working tree unless opted in, and then a 0600 backup outside the tree.
  • Critical regex fix — RE2/Pcre constructs that crashed new RegExp at import
    time are translated to valid JavaScript.
  • sd_scan input bounded to 8 MiB so a model-invoked scan cannot exhaust
    memory or hang the server.
  • Directory installs load — the package ships a root index.js, so
    { "package": "/path/to/stranger-danger" } no longer silently fails with
    "Plugin entrypoint not found".

Compatibility

  • OpenCode V2 runtime, @opencode/plugin >= 2.0.0
    (validated against @opencode/plugin@2.0.29 on OpenCode 2.0.21).
  • Node >= 20 (CI and runtime validation on Node 22).

Installation

OpenCode V2 plugin

{
  "$schema": "https://opencode.ai/config.json",
  "plugins": ["@gitdamnit/stranger-danger"]
}

npm publication is pending (see Distribution). Until then,
install from the repository, or point plugins at a local checkout directory.

Standalone CLI

npm install -g @gitdamnit/stranger-danger   # once published to npm

Upgrade notes

  • Breaking: 0.1.0 → 0.2.0 migrates to the OpenCode V2 plugin API.
    Configure the plugin under plugins (not the V1 plugin key) and run an
    OpenCode V2 host.
  • Rule count is now 236 (was ~172).
  • The pre-read hook no longer rewrites files. If you relied on that behavior,
    use sd redact (or your own tooling) to remediate files on disk.
  • The audit log moved to a project-scoped path:
    <project>/.opencode/state/strangerdanger-audit.jsonl (git-ignored, 0600).

Known limitations

  • Provider-native WebSocket traffic is not inspected. The experimental
    experimental.ws.* hooks are deliberately not registered. Plain-HTTP providers
    and the HTTP fallback of a WebSocket route are covered.
  • Raw http.request bodies are not scanned. The plugin edits assembled
    system/messages, not HTTP bodies. Content a provider layer adds outside
    those is not covered. event.subscribe is observation-only (post-admission).
  • Structured values: only string leaves of plain objects/arrays are redacted.
    Exotic objects (Map, Set, Date, typed arrays) are passed through unchanged.
  • Encoded secrets: detection is pattern/entropy based; secrets obfuscated so
    they match no rule are not caught.
  • No universal guarantee: a secret that no rule matches, or that travels
    through one of the surfaces above, is not stopped. Use it alongside
    .gitignore, secret managers, and provider-side controls.

See SECURITY.md
for the full policy.

Testing summary

  • Local: typecheck, lint, and build pass; npm test 322 pass / 0 fail;
    package validation (pack → isolated install → exercise artifact) passes.
  • Docker Plugin Test Lab: OpenCode 2.0.21, Node 22.23.3, image
    opencode-plugin-lab:local
    (sha256:76ebd805cd548a638b9b1508e5f16e680cd5b082cd3f3561d28f2f2301336ff1):
    145 passed / 0 failed / 0 skipped, covering runtime loading, tool
    registration, synthetic secret detection, context and tool-output redaction,
    large-output windowed scanning, fail-closed oversize handling, allowlist
    behavior, secret-free audit logging, per-session isolation, the offline
    model-request path, all six plugin load orders, and failure isolation.
  • The released source tree is byte-identical to the verified development
    commit 9cfd8135429bffb2e5e32e97f23bec3f5b6277bd; this release adds
    documentation and package metadata only.

Distribution

This is the GitHub release. The package is not yet on npm: the
@gitdamnit scope has no published package and the repository has no NPM_TOKEN
configured. The publish.yml workflow runs on v*.*.* tags and will publish to
npm once registry credentials are set up.

Licence

MIT — see LICENSE.

Attribution

  • gitleaks/gitleaks (MIT) — vendored detection rules.
  • Yelp/detect-secrets (Apache-2.0) — entropy detection approach (clean-room
    TypeScript implementation).
  • boxpositron/envsitter-guard (MIT) — complementary plugin.