Skip to main content
← Back to list
01Issue
BugClosedSwamp CLIPublic
AssigneesNone

Relationships

≡ duplicate of #1668

#2284 lab lifecycle API: dollar-key guard scans the serialised payload and rejects ordinary prose

Opened by skunk-ape · 9/18/2026

Split out of swamp-club#2279, which covers the client half in the swamp repo. This issue covers the server half.

What happened

routes/api/v1/lab/issues/[number]/lifecycle.ts guards the lifecycle payload against mongo-style operator keys like so:

const payloadStr = JSON.stringify(data.payload);
if (/"\$/.test(payloadStr)) {
  return Response.json(
    { error: "payload keys must not start with $" },
    { status: 400 },
  );
}

The guard scans the serialised body rather than walking the parsed object, so it matches a double-quote character immediately followed by the sigil anywhere in the JSON — including inside string values.

Blast radius

Verified against the exact regex:

payload shape current result correct result
{ $set: { a: 1 } } — operator key rejected rejected
{ inner: { $gt: 1 } } — nested operator key rejected rejected
prose containing a quoted shell variable rejected accepted
string value beginning with the sigil rejected accepted
array element beginning with the sigil rejected accepted
sigil mid-word, e.g. costs 5 per run accepted accepted

The last three rows are ordinary prose and code snippets. Any agent writing triage reasoning, a plan step, or a verification log that quotes a shell command gets its lifecycle entry silently dropped.

Why it matters

The lifecycle record is the audit trail for triage, planning, approval and attestation. Because the swamp-side client treats the post as best-effort (swamp-club#2279), a rejection here is invisible to the caller — the step reports success and the reasoning is lost.

Suggested fix

Walk the parsed object recursively and reject only when an actual key begins with the sigil. Objects and arrays both need traversal. Keep the same 400 and error message so existing clients are unaffected.

Extend tests/routes/lifecycle_api_test.ts with the false-positive cases above so the guard cannot regress to a serialised-body scan.

02Bog Flow
✓OPEN○TRIAGED○IN PROGRESS◉CLOSED

Closed

9/30/2026, 4:48:43 PM

No activity in this phase yet.

03Sludge Pulse
skunk-ape linked duplicate of #16689/30/2026, 4:48:42 PM
Editable. Press Enter to edit.

skunk-ape commented 9/30/2026, 4:48:43 PM

Closing as a duplicate of #1668, which reports the same server-side dollar-key guard and was filed earlier. Follow the fix there.

Sign in to post a ripple.