We take the security of the Artagon Agent CLI Plugin suite seriously, including its three plugins (Claude Code, Codex CLI, Gemini host), the OpenAI HTTP facade, and the cost-recording infrastructure.
Please do not file public GitHub issues for security vulnerabilities.
Use one of these channels instead, in order of preference:
-
GitHub Private Security Advisory (preferred): https://github.com/artagon/artagon-agent-cli-plugin/security/advisories/new
-
Email:
security@artagon.dev(TLS-in-transit only; no published PGP key currently). For reports containing exploitation details or unredacted PoC artifacts, prefer the GitHub private security advisory route above — it offers transport-equivalent protection plus access-controlled disclosure history.
We aim to acknowledge a report within 3 business days and provide an initial assessment within 7 business days. Critical findings get faster turnaround.
- A clear description of the vulnerability + impact (read access? write access? remote code execution? local privilege escalation?)
- Reproduction steps or proof-of-concept (a minimal one is fine).
- Affected version(s) — commit SHA preferred over tag if known.
- Whether you've found this issue elsewhere or if it has a CVE.
- Whether you intend to publicly disclose, and on what timeline.
We follow coordinated disclosure: we'd prefer a private window to fix and ship before public details land. The default window is 90 days from acknowledgement; we can negotiate shorter or longer based on severity and your needs.
We patch security issues on:
- The current
mainbranch - The latest published release on npm (
artagon-agent-cli-plugin) - Any release < 6 months old where patching is practical
Older releases are best-effort. If you're running an older version and a vulnerability is reported, we recommend upgrading rather than backporting.
In scope:
- Code in this repository (
lib/,bin/,plugins/, workflows, tests). - The published npm package and its supply chain (provenance, SBOM, install scripts).
- The cost-record persistence layer (file permissions, log path resolution, env var handling).
- The OpenAI HTTP facade (
/v1/chat/completions,/v1/models,/health).
Out of scope (for this project — report upstream):
- Bugs in the underlying vendor CLIs (
claude,codex,gemini). Those CLIs are external dependencies; we shell out to them. - Bugs in transitive npm dependencies — please report to the upstream package maintainer first. We'll mirror upstream advisories via Dependabot once disclosed.
Reviewable in the codebase:
- CodeQL javascript-typescript scan runs on every PR + weekly
schedule (
.github/workflows/codeql.yml). - GitHub Actions pinned to commit SHAs (40-char) — defense
against tag-replacement supply-chain attacks
(
.github/workflows/*.yml). - npm publish via OIDC + Sigstore — provenance attestation on
every release (
.github/workflows/npm-publish.yml). - CycloneDX SBOM (JSON + XML) attached as a release artifact;
generator pinned via
pnpm-lock.yamlintegrity SHA-512 (notnpx <pkg>which would resolve fresh). - Crypto-strong randomness for session IDs and chat-completion
IDs (
crypto.randomBytes, neverMath.random) — enforced by CodeQLjs/insecure-randomness. - Cost record write mode 0o600 — owner-only read/write.
- No stack-trace exposure in HTTP facade error responses;
detail goes to stderr (
js/stack-trace-exposure). - Constant-time API key comparison in the OpenAI facade —
crypto.timingSafeEqualover equal-length buffers, with a pre-check that exits the comparison loop without leaking which configured key matched (lib/server/openai-facade.mjscompareKeysConstantTime). - PID-reuse hardening in the orphan-runner reaper — captures
OS-reported start time at register; refuses to SIGKILL on PID
recycle (
lib/runners/orphan-check.mjs). - Audit log is append-only JSONL keyed by cryptographically
random session ID, default mode 0o600
(
~/.acp-plugins/audit/<session>/audit.jsonl). - Defense-in-depth credential redaction across three layers —
lib/middleware/redaction.mjsDEFAULT_FIELD_NAMES(primary, applied at session entry, redaction-first invariant enforced bycomposeMiddleware),lib/wire-log.mjsREDACT_TOKENS(regex scrubbing of serialized JSON-RPC frames captured to the env-gated wire log), andlib/logger.mjsREDACTED_PATHS(pino redact paths for structured stderr logs). The credential field-name set must agree across all three; mechanically enforced bytests/unit/cross-layer-redaction.test.mjsso a regression in any of the three lists fails CI immediately.
We'll credit reporters in release notes (with permission). If you'd like to remain anonymous, just say so.