computerUseModelCallArgs puts observation_id through stableIdentifier but not
through redactSecrets, so a secret-shaped value under that key is written verbatim
into the persisted tool_call, onto the tool_start event, and into the model's own
replayed history. Every neighbouring field is redacted.
Measured through the real ToolRuntime seam (persisted tool_call args; the
tool_start event was identical in every case):
| argument |
value sent |
persisted |
element_id |
sk-ant-api03-… |
[redacted] |
app |
sk-ant-api03-… |
[redacted] |
element_id |
e7 (control) |
e7 |
observation_id |
sk-ant-api03-… |
sk-ant-api03-AbCdEfGh… |
Introduced by #1891, which moved the projection onto tool-runtime.ts's
persistedArgs line. It is not reachable by an executor-minted id — those are UUIDs —
so this needs a model to send a secret-shaped observation_id, which it can do,
since arguments are not validated before the projection runs (the privacy-boundary
test already asserts that an invalid call still persists a redacted summary).
Why it was not fixed in #1888, where it was found: the model re-sends
observation_id on its next call, so redacting it is not obviously safe.
redactSecrets matches 40-plus contiguous hex among other shapes, and an
executor-minted id that happened to match would be rewritten to [redacted] on the
way into the transcript, which is what the model reads back when it picks its next
element. That would break the observe-then-act loop rather than protect anything.
Fixing it properly needs someone who knows the id format the executor mints and can
say whether a shape check ("this is one of ours, pass it through; anything else is
not an observation id and should not be echoed") is sound. I have not attempted it.
Related, already fixed: the same gap on element_id was closed in #1888.
computerUseModelCallArgsputsobservation_idthroughstableIdentifierbut notthrough
redactSecrets, so a secret-shaped value under that key is written verbatiminto the persisted
tool_call, onto thetool_startevent, and into the model's ownreplayed history. Every neighbouring field is redacted.
Measured through the real
ToolRuntimeseam (persistedtool_callargs; thetool_startevent was identical in every case):element_idsk-ant-api03-…[redacted]appsk-ant-api03-…[redacted]element_ide7(control)e7observation_idsk-ant-api03-…sk-ant-api03-AbCdEfGh…Introduced by #1891, which moved the projection onto
tool-runtime.ts'spersistedArgsline. It is not reachable by an executor-minted id — those are UUIDs —so this needs a model to send a secret-shaped
observation_id, which it can do,since arguments are not validated before the projection runs (the privacy-boundary
test already asserts that an invalid call still persists a redacted summary).
Why it was not fixed in #1888, where it was found: the model re-sends
observation_idon its next call, so redacting it is not obviously safe.redactSecretsmatches 40-plus contiguous hex among other shapes, and anexecutor-minted id that happened to match would be rewritten to
[redacted]on theway into the transcript, which is what the model reads back when it picks its next
element. That would break the observe-then-act loop rather than protect anything.
Fixing it properly needs someone who knows the id format the executor mints and can
say whether a shape check ("this is one of ours, pass it through; anything else is
not an observation id and should not be echoed") is sound. I have not attempted it.
Related, already fixed: the same gap on
element_idwas closed in #1888.