This release includes 12 security fixes for security teams reviewing exposed deployments.
Topics
+14 more
Affected surfaces
Summary
AI summaryOAuth PKCE state validation, SAML signature verification, and webhook HMAC enforcement close multiple security gaps.
Full changelog
v1.8.6
Security hardening and reliability — the largest patch in the 1.8.x line.
Security
- OAuth: PKCE
stateparameter is validated on callback. - SAML: assertion signature is verified.
- Webhooks: every POST requires a valid HMAC; stack traces stripped from hook error responses.
- MCP server: auth required by default; bound to localhost out of the box.
- Licensing: empty signing keys are rejected at load time.
- Agents: real per-agent credential scoping at spawn — an agent can only see the credentials it declared a need for.
- Auth: on by default; unauth bypass paths removed.
- Auto-approve: rules tightened; the
always_allowlist is read-only to agents. - Rate limiter: keyed on the real peer IP, not the trusted forwarded header (closes a spoofing gap).
- Audit log: HMAC key is now stored separately from the log files, so reading the log doesn't leak the key.
- PII redaction: dedup key is now
(rule, span), not rule alone (duplicate rules on different spans used to clobber each other). - File hooks: path validation to prevent traversal.
- Telemetry/logs: dropped OTLP endpoint URL from init logs;
always_allowtamper logs redact sensitive content.
Reliability
- WAL: uncommitted entries are closed on recovery instead of being replayed into failing tasks.
- Cross-process file locks on
.sdd/so concurrent Bernstein processes don't tear state writes. - Atomic writes (temp + rename) for state files.
- Task lifecycle: retry counter consolidated to a typed field; exhausted retries now go to the DLQ instead of vanishing; cancel propagates to children;
claim_by_idrejects double-claim; stale-task release is flushed to JSONL; batch state transitions go through the FSM. - Priority queue: stale-task ordering uses a heap — was O(n·log n) per tick, now O(log n).
- Recovery backup:
.sdd/runtime/is now included in the disaster-recovery snapshot. - Observability file sizes:
api_usage.jsonlrotates instead of growing unbounded.
Cost & budgeting
- Removed the unused
quota_trackerandcost_hooksmodules. - In-memory usage history is now bounded.
- Budget policy is evaluated on each cost event (previously hooked but not invoked).
- Context-degradation detector wired in — flags when token pressure drops answer quality.
- Routing bandit learns the effort level from rewards, not just the model choice.
Git / worktree
- Incremental merge refuses to overwrite
main— the previous behaviour could fast-forward past protected state. - Uncommitted work is salvaged before a worktree is torn down.
- Unmerged agent branches are preserved through hygiene passes.
- Concurrent merges are enqueued through the merge queue instead of racing.
- Rebase-or-merge fallback aborts cleanly on failure instead of leaving a half-merged tree.
Adapters
- Opus aliases across
aider,amp,cody, andgoosenow resolve toclaude-opus-4-7. - GitHub API usage paginates properly instead of capping at
--limit. - Adapter autodetect uses correct binary names.
- All spawn kwargs are forwarded through the caching wrapper.
- Broken
roo_codeandtabbyadapters removed;codyandcontinue_devfixed.
Tokens
- Compactor consolidated to a single source of truth.
- Token estimator consolidated to a single source of truth.
Server
- All routers are now mounted under
/api/v1(several were previously unreachable). - Uvicorn
--reloadis disabled in evolve mode to stop the constant-restart death loop. - Hook-error responses are sanitized before going back to the client.
UX / docs
- README: restored the pluggable-plugin (pluggy) and behavior-anomaly claims; reworked to match current reality; unified adapter count at 17.
- Docs reorganized into topical sub-folders; dead
[email protected]swapped for[email protected]. - HTML nav repaired after the reorg; demo GIF recompressed; fake benchmark numbers purged.
- CLI: restored
init,status,start,wrap-upnames to match the docs. - Splash banner path fixed after the
cli/display/reorg.
Housekeeping
- Communication layer: orphan
discord_botscaffolding removed. scripts/archive/**excluded from lint.- Hardcoded personal paths removed; marketing drafts moved to a private folder.
- Removed
self_healingmodule (no production importers).
Full changelog: https://github.com/chernistry/bernstein/compare/v1.8.5...v1.8.6
Security Fixes
- OAuth PKCE state parameter validation prevents callback abuse (CVE not listed)
- SAML assertion signature verification ensures authentic assertions
- Webhook POSTs now require a valid HMAC; stack traces removed from error responses
- MCP server defaults to auth required and binds to localhost
- Licensing rejects empty signing keys at load time
- Agents receive scoped credentials only for declared needs
- Auth enabled by default with unauth bypass paths removed
- Auto‑approve rules tightened; `always_allow` list is read‑only to agents
- Rate limiter keyed on real peer IP, closing spoofing gap
- Audit log HMAC key stored separately from log files
- PII redaction dedup key now `(rule, span)` preventing clobbering
- File hook path validation prevents directory traversal
Weekly OSS security release digest.
The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.
No spam, unsubscribe anytime.
Share this release
About chernistry/bernstein
Deterministic multi-agent orchestrator for 18 CLI coding agents (Claude Code, Codex, Cursor, Aider, Gemini CLI, OpenAI Agents SDK, and more). MCP server mode (stdio + HTTP/SSE) exposes the orchestrator to any MCP client. Git worktree isolation per agent, HMAC-chained audit trail, cost-aware model routing via contextual bandit. ~11K monthly PyPI downloads, Apache 2.0.
Related context
Related tools
Beta — feedback welcome: [email protected]