Skip to content

sealed: marker wire format is forgeable by the agent — consider a nonce'd marker #33

Open

Description

@Wilbert957

Context

internal/platform/markers.go injects platform context into agent-owned, chain-tracked files between two fixed HTML-comment markers, and StripInjected removes that section before evolution hashing so chain payloads carry only agent-owned bytes.

4c62951 (on feat/multi-framework-seam, PR #30) hardened the strip: markers only count as section boundaries on lines of their own, the start marker is matched from the end of the file, and an unpaired start strips nothing. That closed the realistic data-loss case — agent prose mentioning a marker mid-line used to be taken as the section start, deleting everything from the mention to the real end marker (on disk and on chain, unrecoverably).

Residual ambiguity (this issue)

An agent-written exact reproduction of the wire format — both markers, each on a line of its own — is byte-wise indistinguishable from a real section, and the next upsert removes it (pinned by TestStrip_ExactAnchoredPairInOwnerContent_IsAmbiguous).

Realistic ways this happens, and their blast radius:

scenario what gets eaten
agent quotes the injected block verbatim in a fenced code block (code fences don't prefix lines, so the markers stay line-anchored) the quoted platform text itself — bounded, low value
agent copies a whole file (cp TOOLS.md backup.md) into a tracked path the injected section inside the copy — platform text
agent deliberately adopts the marker convention to wrap its own content the agent's own content — the actually bad case, but requires intent

So today's exposure is mostly self-limiting; the dangerous variant needs the agent to co-opt the exact format.

Options

  1. Soft (cheap): add one line to the injected doctrine/SOUL text — "never reproduce the platform marker lines verbatim; refer to them by name". Prompt-level, no format change.
  2. Hard (real fix): per-agent random nonce in the markers, e.g. <!-- 0g-platform-injected:start:a3f9c2 -->. The agent can't forge what it can't predict... except it reads the nonce in its own files, so the nonce must rotate per boot (files are rewritten from chain plaintext by Restore before the first upsert, so a per-boot nonce needs no persistence and stale nonces can't survive a boot). Strip then anchors on the nonce'd prefix.

Option 2 is a wire-format change touching UpsertMarkedSection/StripInjected and every adapter's round-trip tests — deliberately not done in PR #30 to keep the fix surgical.

Refs

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions