mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-09-30 12:39:42 +02:00
Trims the repo root listing so the README is reached with less scrolling. Only these two were movable; the other five root .md files are load-bearing and stay put: - README.md / README.zh-CN.md — the landing page and the language-switcher entry point - CLAUDE.md — Claude Code loads project instructions from the ROOT path; moving it silently breaks every future session in this repo - AGENTS.md — the agent-convention file Codex reads from the root and injects as context (see the comments in session-routes.ts) - CHANGELOG.md — the changesets default writer emits it next to package.json, so moving it breaks `npm run version-packages` GitHub officially resolves .github/SECURITY.md, so the Security policy tab keeps working. Inbound links updated in both READMEs, CLAUDE.md and docs/versioning-policy.md. CHANGELOG.md also names SECURITY.md but is left alone: it is a historical record, not a live reference. The move broke a link the other direction too: SECURITY.md pointed at docs/security-architecture.md, which from .github/ resolved to .github/docs/... — repointed to ../docs/. All relative links in the six touched files verified resolving (62 links, 0 broken). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
79 lines
5.6 KiB
Markdown
79 lines
5.6 KiB
Markdown
# Security Policy
|
|
|
|
Codeman launches AI coding sessions with `--dangerously-skip-permissions`, so the
|
|
web UI is **by design a remote-code-execution surface for whoever can reach it**.
|
|
The entire security model exists to control *who* that is. Please read this before
|
|
exposing an instance beyond `localhost`. The full model lives in
|
|
[`docs/security-architecture.md`](../docs/security-architecture.md).
|
|
|
|
## Supported versions
|
|
|
|
Security fixes land on the latest published `codeman@X.Y.Z` release and `master`.
|
|
Older versions are not patched — upgrade to the latest release (App Settings →
|
|
Updates for git-clone installs, or `npm i -g aicodeman@latest`).
|
|
|
|
| Version | Supported |
|
|
| ------- | --------- |
|
|
| latest `0.9.x` / `master` | ✅ |
|
|
| anything older | ❌ (upgrade) |
|
|
|
|
## Reporting a vulnerability
|
|
|
|
**Please do not open a public issue for security problems.**
|
|
|
|
Report privately via **GitHub's private vulnerability reporting**:
|
|
the repository's **Security** tab → **Report a vulnerability**
|
|
(<https://github.com/Ark0N/Codeman/security/advisories/new>). This opens a private
|
|
advisory thread with the maintainer.
|
|
|
|
> Maintainer note: enable *Settings → Code security and analysis → Private
|
|
> vulnerability reporting* so this channel is live.
|
|
|
|
When reporting, please include: affected version/commit, the deployment shape
|
|
(loopback-only, `CODEMAN_PASSWORD` set, tunnel/`tailscale serve`, custom
|
|
reverse proxy), reproduction steps, and impact. We aim to acknowledge within a
|
|
few days. Coordinated disclosure is appreciated — we'll agree a disclosure
|
|
timeline with you once impact is confirmed.
|
|
|
|
### In scope
|
|
- Authentication / session-cookie bypass when `CODEMAN_PASSWORD` is set
|
|
- DNS-rebinding, CSRF/CSWSH, or Origin/Host-guard bypass reaching state-changing routes
|
|
- Remote code execution reachable **without** local OS access (e.g. via a browser, a tunnel, or a foreign origin)
|
|
- Path traversal / arbitrary file read or write through the HTTP API
|
|
- Supply-chain integrity of the in-app self-updater
|
|
|
|
### Out of scope (by design — see Known limitations)
|
|
- Anything requiring an already-trusted **same-machine, same-uid** process. Codeman trusts the local OS user it runs as; a peer process of that user is already inside the boundary.
|
|
- Running an authless instance bound to a non-loopback host after dismissing the startup warning (you explicitly acknowledged it).
|
|
- The default loopback + no-password posture itself (it is reachable only from the same machine).
|
|
|
|
## Trust model (summary)
|
|
|
|
- **Loopback by default.** Binds `127.0.0.1`; the no-password default is safe out of the box. Binding a non-loopback host without `CODEMAN_PASSWORD` *starts but prints a loud warning* with concrete fixes.
|
|
- **Always-on Host + Origin guards.** Block DNS-rebinding and cross-site state-changing requests even on the no-auth loopback install (a missing Origin is allowed so CLI/hooks work).
|
|
- **Optional auth.** HTTP Basic via `CODEMAN_USERNAME`/`CODEMAN_PASSWORD`; success issues an opaque server-side 256-bit cookie. Per-IP rate limiting on failures.
|
|
- **Hardened file serving, tmux launch, transport headers, and multi-instance isolation** — see the full architecture doc.
|
|
|
|
## Known limitations and accepted risk
|
|
|
|
A 1.0 release is an implicit statement that the documented model *is* the model, so
|
|
these residuals are stated explicitly. Most sit **inside the same-uid OS trust
|
|
boundary** or behind the always-on Origin guard; they matter mainly for
|
|
shared-host, multi-user, or tunneled deployments.
|
|
|
|
- **Self-update trusts an unsigned release tag.** The in-app updater does `git checkout <tag> && npm install` (lifecycle scripts run) of a tag matched only by name shape, from whatever `origin` points to — no signature/commit verification. Treat the updater as trusting your `origin` remote and your release pipeline. (Hardening tracked for 1.0.)
|
|
- **CSP ships `'unsafe-inline'`.** Inline handlers mean the Content-Security-Policy is defense-in-depth only; all AI-/file-derived sinks are escaped, but a future missed escape would be executable.
|
|
- **`workingDir` is unconstrained.** A session may be created with any absolute working directory (e.g. `/`), which becomes the file-route boundary for that session. Scope it to trusted paths on shared hosts.
|
|
- **Hook-event auth exemption is loopback-IP-based.** `POST /api/hook-event` is exempt from auth for loopback callers; because tunnels (cloudflared / `tailscale serve`) terminate at `127.0.0.1`, a loopback-terminating tunnel inherits the exemption. Set `CODEMAN_PASSWORD` and prefer a tunnel that preserves the client identity if this matters.
|
|
- **Session cookie is not bound to client IP/UA on reuse, and refreshes without an absolute cap.** A stolen cookie replays until its idle TTL elapses.
|
|
- **Multi-instance tmux socket is process-wide.** Two Codeman instances on the same `CODEMAN_INSTANCE` share a tmux socket and can attach each other's live sessions — isolate with distinct `CODEMAN_INSTANCE` values.
|
|
- **The live log-tail route reads `/var/log` and `~/logs`** in addition to the session working directory (read-only) — a deliberate choice for tailing system/app logs. On a password-protected remote deployment an authenticated user can therefore read those roots outside their session. See `docs/security-architecture.md` §5.
|
|
|
|
Recent hardening (this release): web-push subscription endpoints are restricted
|
|
to https public hosts (SSRF guard — rejects internal/metadata IPs, validated at
|
|
subscribe and send time), and tmux session names discovered on the shared socket
|
|
are validated against the safe-name pattern before reaching any shell call site.
|
|
|
|
For the detailed rationale, defenses, and recommended secure setups, see
|
|
[`docs/security-architecture.md`](../docs/security-architecture.md).
|