Skip to content

chernistry/bernstein

v3.6.0 Security

This release includes 2 security fixes for security teams reviewing exposed deployments.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →
This release patches 2 known CVEs

Topics

agent-orchestrator agentic-ai ai-agents aider air-gap audit-trail
+14 more
claude-code cli-tool codex-cli coding-agent deterministic-replay deterministic-scheduler hmac-audit mcp-server model-context-protocol multi-agent parallel-worktrees provenance python reproducibility

Affected surfaces

auth rbac rce_ssrf deps breaking_upgrade

ReleasePort's take

Moderate signal
editorial:auto 9d

Release v3.6.0 enforces a minimum safe version floor for adapter spawns with signed refusal receipts and adds provenance trust classes to prevent untrusted data laundering.

Why it matters: Security: Enforced minimum version floor (signed refusal) blocks unsafe adapters; Provenance trust classes block untrusted data laundering – critical protections now active.

Summary

AI summary

Provenance trust classes anchor egress decisions to signed lineage, preventing untrusted data from laundering into approved actions.

Changes in this release

Security Critical

Enforces minimum safe version floor for adapter spawns with signed refusal receipts.

Enforces minimum safe version floor for adapter spawns with signed refusal receipts.

Source: llm_adapter@2026-07-17

Confidence: high

Security High

Introduces provenance trust classes with lineage-propagated egress confinement to prevent untrusted data laundering.

Introduces provenance trust classes with lineage-propagated egress confinement to prevent untrusted data laundering.

Source: llm_adapter@2026-07-17

Confidence: high

Feature High

Implements intent capsules that bind approved goals to run execution via deterministic drift monitoring.

Implements intent capsules that bind approved goals to run execution via deterministic drift monitoring.

Source: llm_adapter@2026-07-17

Confidence: high

Feature Medium

Adds receipt‑backed fleet steering with pause, resume, guidance, redirect, and abort controls.

Adds receipt‑backed fleet steering with pause, resume, guidance, redirect, and abort controls.

Source: llm_adapter@2026-07-17

Confidence: high

Feature Medium

Introduces content‑addressed registered recipes with collision receipts, definition lineage, and advanced scheduling options.

Introduces content‑addressed registered recipes with collision receipts, definition lineage, and advanced scheduling options.

Source: llm_adapter@2026-07-17

Confidence: high

Full changelog

v3.6.0

Released 2026-07-17.

Security: provenance trust classes with lineage-propagated egress confinement (#2513)

Worker context ingests tool results from sources with very different trust
levels: web and browser output, tracker issue bodies, third-party MCP results.
The capability matrix tagged tools statically, so UNTRUSTED_INPUT was a
property of the tool, not of the bytes. Once a result entered context,
downstream egress checks could not tell whether the exact bytes they acted on
derived from content an outsider could have written. The structural gate closed
the direct path; the data-flow path stayed open.

  • Every tool result is recorded as a content-addressed lineage entry carrying a
    trust_class (operator, workspace, first-party, third-party, public). The
    label lives inside the signed, HMAC-chained lineage entry, and the taint
    verdict is a pure projection over the graph's parent_hashes edges, so the
    confinement is anchored to the lineage graph rather than to a runtime tag.
  • The effective trust of any artefact is the minimum trust class over its
    lineage closure, a deterministic projection recomputable offline. Absence of
    provenance is fail-closed to the lowest class.
  • bernstein audit taint <artefact> recomputes the verdict offline: two
    verifiers on different machines produce a byte-identical result with no live
    process. It runs the lineage gate first, so a mutated provenance record or a
    reparented edge fails verification exactly like a tampered lineage entry fails
    the existing gate.
  • The capability matrix now carries UNTRUSTED_INPUT by data: a chain that
    unions private data, a tainted-derived operand, and external communication is
    denied even when every tool's static tags would pass. Auto-approve never
    returns APPROVE for a command whose text derives from a tainted artefact.
  • Untrusted payloads pass through a quarantined structural parser
    (schema-validated fields only) before anything reaches prompt context;
    instruction-bearing free text is withheld and represented by a content hash,
    and the extraction is a lineage edge back to the tainted source.
  • The source-to-trust-class map is reviewed data
    (templates/provenance/trust_sources.yaml); an unlisted source fails closed.

Content written by outsiders can no longer launder into approved egress
unnoticed, and every egress decision becomes reconstructable, offline, to the
exact bytes it acted on and their signed origin.

Adapters: enforced security floor with signed refusal receipts (#2515)

The spawn boundary is the most privileged hand-off in the system: the CLI
binary Bernstein execs receives the task context, the workspace, and the
worker's credential scope. The minimum-safe-version floor is now an enforced
spawn-time contract rather than an advisory a doctor warning may never surface.

  • Spawning a tracked adapter below its security floor is refused by default. An
    ordinary version check prints a warning; here the refusal itself is the proof
    artefact: a content-addressed adapter.spawn_preflight_receipt anchored to
    the HMAC audit chain and verifiable offline.
  • Every preflight decision, including permits and warn-only overrides, is
    chain-anchored. Given a contiguous audit-chain slice, a verifier can prove no
    below-floor adapter spawn was permitted during a window, and a gap in the
    slice is detectable rather than silently exculpatory.
  • bernstein doctor seals the environment's version posture into an
    adapter.version_posture receipt, so the posture is provable offline instead
    of living only in console text.
  • The conformance canary refuses to certify a below-floor version and records
    the refusal; the last-green projection can never advance onto a below-floor
    version.
  • Each receipt pins the floor map's content hash, so a mutated map is flagged
    at verification. A floor bump lands as a data-only diff accompanied by a
    signed update receipt (scripts/refresh_adapter_floors.py).
  • Opt-out: BERNSTEIN_ADAPTER_FLOOR_POLICY=warn permits a below-floor spawn and
    records a warn-override receipt rather than refusing.

See docs/adapters/security-floor.md.

Audit: intent capsules with deterministic drift escalation (#2514)

Approving an unattended run approves a sentence, not a contract: nothing bound
the running worker's action stream to the goal the operator signed off on. Scope
drift was only discoverable in retrospect by reading the journal. Intent capsules
close that gap.

  • At approval time the goal is compiled into an intent capsule: a canonical
    structured envelope listing the allowed action classes, file-scope globs,
    permitted adapters, egress classes, a cost-envelope reference, and an expiry.
    The capsule is written to the HMAC audit chain (intent.capsule) and its hash
    is bound into the run journal, so every subsequent step is attributable to one
    approved capsule. The goal is bound by digest, never stored verbatim.
  • A deterministic drift monitor maps observed journal events to action classes
    and compares them against the capsule. The conformance verdict is a pure
    function of (journal, capsule): two verifiers on different machines recompute
    the byte-identical verdict offline. No model runs on the drift-decision path.
  • On divergence the monitor emits a signed escalation receipt reusing the stall
    escalation shape, binding the capsule hash and the divergent events. The
    receipt passes bernstein escalation verify, so stalls and drift now produce
    the same class of verifiable artefact.
  • bernstein intent verify <task-id> recomputes conformance offline: it checks
    the capsule hash against the audit chain, walks the run journal Merkle chain,
    and maps action classes against the capsule. A tampered capsule or a reordered
    journal fails verification with no live process required.
  • Rollout defaults to warn-only (drift is surfaced and escalated but not
    blocked); a blocking policy is opt-in.

See docs/operations/intent-capsules.md.

Orchestration: receipt-backed fleet steering (#2508)

Once a worker was running a task an operator had no mid-task controls: no pause,
no way to queue guidance, no redirect of the objective, no clean abort. The only
recourse was to abort the whole run and respawn, losing the budget already spent,
or to edit files under a running worker and leave no record, so an audited run a
human touched could no longer be explained end to end. Fleet steering closes that
gap without weakening the run's verifiability: every action is a receipt first
and an effect second.

  • Five steering kinds (pause, resume, guidance, redirect, abort) each
    record a signed steering.receipt on the HMAC audit chain before any effect
    runs. The delivered effect references that receipt's chain HMAC, so an effect
    with no matching receipt is rejected; the receipt binds the exact command
    payload the operator confirmed, and a request whose confirmed payload differs
    from the executed command fails before the chain is touched.
  • Delivery rides the existing task mailbox journal as new steer.* message
    kinds, so queued guidance reaches the worker in chain append order, exactly
    once, even mid-tool-call. The worker records each consumed steering message as
    a first-class step in the per-step journal, so a steered run replays
    byte-identically and a second host walking the same journal computes identical
    step hashes.
  • Divergence detection distinguishes an operator-steered run from a tampered one:
    a run that verifies and carries steering steps is steered; mutating a
    recorded receipt or steering step fails verification at exactly its chain
    position and is labelled tampered.
  • Pause checkpoints the running worker and parks its claim; resume continues from
    the checkpoint without restarting the task. Abort is enforced by the scheduler
    on the worker process through a filesystem stop signal, never routed through
    the model, and touches only the target session, so steering one worker leaves
    other workers' worktrees and claims untouched.
  • Steering requires an authorised operator-scoped dashboard token; a viewer
    token or a request with no valid credential is recorded in the denial tracker
    and rejected. Surfaces: POST /tasks/{task_id}/steer, the bernstein fleet steer CLI subcommand, and steering controls with a queued-guidance indicator
    on the fleet screen.

Scheduling: content-addressed registered recipes with collision receipts and definition lineage (#2546)

A recurring run under governed configuration was split across three surfaces:
file-discovered recipes with no registered identity, content-hash schedules that
could only speak UTC 5-field cron and had no pause state, and a separate scenario
registry. The supervisor also fired over a still-running previous fire, so a slow
nightly run that overran its window double-wrote with no record that an overlap
was even evaluated.

  • A registered recipe is now a content-addressed run definition: the recipe id
    is the sha256 of its canonical body, which pins the git commit plus adapter,
    model, and prompt-pack hashes. Two operators registering the same manifest at
    the same commit derive the byte-identical hash; changing any pinned input
    changes it. Registration seals the canonical bytes into the lineage spine and
    writes a recipe.register receipt. There is no mutable registry row: the live
    name -> hash mapping is a projection of the receipt history.
  • Schedules gain interval+anchor and RRULE kinds beside cron, plus a declared
    IANA timezone and an explicit DST ambiguity policy. Local-time resolution goes
    through stdlib zoneinfo only, so two hosts in different system timezones
    resolve the DST-forward gap and the DST-back overlap to the byte-identical
    instant, and the declared zone folds into the fire projection hash.
  • Concurrency collisions are a pure decide_collision(policy, running_fire_state)
    evaluated in the supervisor tick, emitting a chain-anchored collision receipt
    for every overlap considered. CANCEL_NEW never dispatches a second task graph
    over a running fire; SUPERSEDE_WITH_HANDOFF resumes the new fire from the
    stale run's recorded checkpoint, downgrading to a cold start when that
    checkpoint row fails chain verification.
  • Every definition change is an offline-verifiable chain of hashes:
    re-registering a changed body writes an operator-signed supersede receipt,
    recipes rollback re-points a name at a prior hash via a new receipt (nothing
    is deleted), and pause/resume are definition-level state records. A paused
    recipe fires nothing yet keeps its identity, and its pause window reconstructs
    from receipts alone. recipes history <name> --verify walks register,
    supersede, rollback, and pause receipts against the HMAC chain with no server
    running and exits non-zero on any broken or reordered link.
  • A declarative fleet manifest makes rebuilding the whole set reviewable:
    recipes plan emits a byte-reproducible diff with a plan_hash, and
    recipes apply --plan <hash> refuses to run against any other registry state,
    naming the divergent recipe.

No new runtime dependency (zoneinfo is stdlib); existing zero-block recipe
manifests and existing sched_ schedules keep working unchanged.

Security Fixes

  • Provenance trust classes close the data‑flow path that allowed untrusted bytes to reach egress without detection; lineage‑anchored confinement ensures every egress decision is reconstructable offline.
  • Adapter spawn preflight enforcement with signed refusal receipts blocks below‑floor versions, preventing privilege escalation via outdated adapters.

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

Track chernistry/bernstein

Get notified when new releases ship.

Sign up free

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.

All releases →

Related context

Earlier breaking changes

  • v3.7.1 `bernstein approve` and `bernstein reject` now enforce identifier regex `[A-Za-z0-9._-]{1,64}`.
  • v3.7.1 Tampered mission ledger reports as unverified rather than not-found.
  • v3.7.1 `mission define` now refuses phases without gate tasks.
  • v3.5.0 MCP client, transport, and gateway become stateless; calls carry content‑derived trace IDs in _meta.

Beta — feedback welcome: [email protected]