Skip to content

fix(core): security hardening — auth fail-closed, arg injection, secret file perms - #28

Merged
medomar merged 1 commit into
release/v0.1.1from
fix/security-hardening-batch-1
May 23, 2026
Merged

fix(core): security hardening — auth fail-closed, arg injection, secret file perms#28
medomar merged 1 commit into
release/v0.1.1from
fix/security-hardening-batch-1

Conversation

@medomar

@medomar medomar commented May 23, 2026

Copy link
Copy Markdown
Owner

Summary

Security hardening batch from a full-project audit. Fixes the critical fail-open paths and the quick-win HIGH findings. Each item was verified against the actual code path; tests updated to assert the new fail-closed behavior.

ID Severity Fix
C1 Critical Empty auth.whitelist now fails closed (denies all) instead of authorizing everyone. New opt-in auth.allowAllSenders flag for local dev. Paired users still authorized via access_control.
C2 Critical Strip path components from attacker-controlled email MIME attachment filenames (basename + ./.. guard) — blocks arbitrary file write via crafted .eml.
H1 High checkAccessControl fails closed: a getAccess DB error denies (was: allow); an unknown/corrupt role falls back to viewer (was: unrestricted). /role & /approve default an un-provisioned caller to viewer, not owner.
H2 High Neutralize CLI argument injection: a positional prompt beginning with - is space-prefixed so it can't be parsed as a flag (e.g. --dangerously-skip-permissions, --mcp-config).
H3 High Unknown spawn profile falls back to read-only tools instead of leaving the worker unrestricted.
H6 High Per-worker MCP temp config and .openbridge/mcp-config.json written with mode 0600 (they hold raw MCP tokens).
H7 High IMAP TLS cert verification on by default; opt out via options.allowInsecureTLS.
M4 Medium config.json written with mode 0600 (holds bot tokens / MCP env).

Breaking change

V0 configs that relied on an empty whitelist for open access will now deny all senders. Either add entries to auth.whitelist, or set auth.allowAllSenders: true (intended for local/console dev only). A loud startup error explains this when the whitelist is empty.

Testing

  • npm run typecheck, npm run lint, npm run build — pass.
  • npm run test — 5518 pass. Updated 7 tests that encoded the old insecure behavior; added opt-in/fail-closed assertions.
  • 2 unrelated failures remain and are pre-existing on develop (date-dependent naming-series year-rollover; flaky pdf-processor OCR timeout) — not touched by this PR.

Not included (larger redesigns, follow-up)

C3 (FileServer auth + public-tunnel exposure), H5 (OpenAPI SSRF allowlist), H8 (WebChat 0.0.0.0 default + token-in-URL), plus medium items M1–M7. Happy to tackle these in separate PRs.

…erms

Security batch (audit findings C1, C2, H1, H2, H3, H6, H7, M4):

- C1 auth: empty whitelist now FAILS CLOSED (denies all) instead of
  authorizing everyone. Opt into open access with the new
  auth.allowAllSenders flag (local dev only). Paired users are still
  authorized via access_control even with an empty whitelist.
  BREAKING: V0 configs relying on an empty whitelist for open access
  must now set auth.allowAllSenders=true.
- C2 email: strip path components from attacker-controlled MIME
  attachment filenames (basename + ./.. guard) to block arbitrary file
  write via crafted .eml.
- H1 auth: checkAccessControl fails closed — a getAccess DB error now
  denies instead of granting access, and an unknown/corrupt role falls
  back to the most restrictive (viewer) instead of unrestricted. The
  /role and /approve handlers default an un-provisioned caller to
  viewer, not owner.
- H2 agent-runner: neutralize CLI argument injection — a prompt passed
  as a positional argv element that begins with '-' is prefixed with a
  space so it can never be parsed as a flag (e.g. a message of
  "--dangerously-skip-permissions" or "--mcp-config ...").
- H3 agent-runner: an unknown spawn profile now falls back to read-only
  tools instead of leaving the worker unrestricted.
- H6 secrets: write the per-worker MCP temp config and the global
  .openbridge/mcp-config.json with mode 0600 (they hold raw MCP tokens).
- H7 email: enable IMAP TLS certificate verification by default; opt out
  explicitly via options.allowInsecureTLS.
- M4 cli: write config.json with mode 0600 (holds bot tokens / MCP env).

Tests updated to assert the new fail-closed behavior.
@medomar
medomar changed the base branch from develop to release/v0.1.1 May 23, 2026 14:44
@medomar
medomar merged commit 8781601 into release/v0.1.1 May 23, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant