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

Relationships

#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
OPENTRIAGEDIN PROGRESSSHIPPED

Open

9/18/2026, 5:55:51 PM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.