AntFleet

Anatomy · cdf9ffa0-2

jq --argjson resp $resp will crash the result-writer if curl/server returns non-JSON, dropping the error record

mediumbugclosed in 4b9b492
repo 6f7fc663·PR #4·reviewed 1 week ago·closed 1 week ago

The vulnerable code

scripts/postprocess-admanage-create.sh:87-96

87
88 if [ "$success" != "true" ] || [ -z "$campaign_id" ]; then
89 err=$(echo "$resp" | jq -r '.message // .error // "unknown campaign create error"')
90 echo "postprocess-admanage-create: FAILED '$cfg_name': $err"
91 jq -n --arg name "$cfg_name" --arg err "$err" --argjson resp "$resp" \
92 '{configName:$name, type:"campaign", success:false, error:$err, response:$resp, ts:now}' \
93 > "$RESULTS_DIR/campaign-${basename}.json"
94 summary_lines+=("campaign '$cfg_name' — FAILED: $err")
95 campaign_fail=$((campaign_fail + 1))
96 mv "$file" "$RESULTS_DIR/campaign-${basename}.input.json" 2>/dev/null || true

The reasoning

Opus

jq --argjson resp $resp will crash the result-writer if curl/server returns non-JSON, dropping the error record

mediumbughigh
  • scripts/postprocess-admanage-create.sh:87-96
  • scripts/postprocess-admanage.sh:96-100
curl with `-sS` plus `||` only substitutes a JSON fallback when curl exits non-zero. If the API returns HTTP 5xx with an HTML body (or proxy text), curl exits 0 with non-JSON output. `jq -r '.success // false'` on non-JSON prints a parse error to stderr and outputs nothing → `success` is empty → the failure branch runs, but then `jq -n --argjson resp "$resp"` REQUIRES valid JSON for `--argjson` and will error out, so the result file is never written. The pending input file is then mv'd into results anyway (because `mv ... || true`), but the failure context is lost. Set -e isn't on (only `set -uo pipefail`), so the loop continues but the operator gets no error record for the failed entity.

Recommendation

Validate `resp` is parseable JSON (e.g., `echo "$resp" | jq empty 2>/dev/null || resp='{"success":false,"error":"non_json_response","raw":"..."}'`) before passing to `--argjson`. Apply same fix in postprocess-admanage.sh for launch_resp and batch_resp.

GPT-5

Both postprocess scripts use jq --argjson with untrusted API responses, causing result/error files to be dropped on non-JSON responses

mediumbughigh
  • scripts/postprocess-admanage-create.sh:91-93
  • scripts/postprocess-admanage-create.sh:109-111
  • scripts/postprocess-admanage-create.sh:155-160
  • scripts/postprocess-admanage-create.sh:173-175
  • scripts/postprocess-admanage.sh:96-98
  • scripts/postprocess-admanage.sh:124-131
--argjson expects valid JSON; if the API returns non-JSON (e.g., HTML error page, empty body, or truncated response), jq will exit non-zero and no results file will be written, contradicting the stated behavior to always write an error to results and continue. This affects both success and failure branches and both scripts.

Recommendation

Use --arg resp "$resp" (string) instead of --argjson for untrusted external responses, or attempt jq -e parsing with a fallback: parsed=$(echo "$resp" | jq -c . 2>/dev/null || printf '%s' 'null'); then pass parsed via --argjson parsed "$parsed" and also include the raw string via --arg raw "$resp". Additionally, consider curl -f to treat non-2xx as errors and feed a synthetic JSON error object.

The agreement

Both frontier models flagged this within the same line range. AntFleet's unanimous gate fired — the finding posted on the PR. Closed in 4b9b492.

The fix

87
88 if [ "$success" != "true" ] || [ -z "$campaign_id" ]; then
89 err=$(echo "$resp" | jq -r '.message // .error // "unknown campaign create error"')
90 echo "postprocess-admanage-create: FAILED '$cfg_name': $err"
91 jq -n --arg name "$cfg_name" --arg err "$err" --argjson resp "$resp" \
92 '{configName:$name, type:"campaign", success:false, error:$err, response:$resp, ts:now}' \
93 > "$RESULTS_DIR/campaign-${basename}.json"
94 summary_lines+=("campaign '$cfg_name' — FAILED: $err")
95 campaign_fail=$((campaign_fail + 1))
96 mv "$file" "$RESULTS_DIR/campaign-${basename}.input.json" 2>/dev/null || true

Closure

Closed 1 week ago

SHA: 4b9b49251c8c9808bf147d55aa2930352af2e8c0

View closure receipt on GitHub →

Tweet thread template

tweet 1 of 8193 / 280

Two frontier models reviewed PR #4 on 6f7fc663. Both found this bug: medium bug: jq --argjson resp $resp will crash the result-writer if curl/server returns non-JSON, dropping the error record

tweet 2 of 8130 / 280

The vulnerable code (scripts/postprocess-admanage-create.sh:87-96): (full snippet at https://www.antfleet.dev/anatomy/cdf9ffa0-2)

tweet 3 of 8280 / 280

What Opus saw: "curl with `-sS` plus `||` only substitutes a JSON fallback when curl exits non-zero. If the API returns HTTP 5xx with an HTML body (or proxy text), curl exits 0 with non-JSON output. `jq -r '.success // false'` on non-JSON prints a parse error to stderr and outp…

tweet 4 of 8280 / 280

What GPT-5 saw: "--argjson expects valid JSON; if the API returns non-JSON (e.g., HTML error page, empty body, or truncated response), jq will exit non-zero and no results file will be written, contradicting the stated behavior to always write an error to results and continue. …

tweet 5 of 897 / 280

Both flagged the same line range. AntFleet's unanimous gate fired — the finding posted on the PR.

tweet 6 of 893 / 280

The fix landed in commit 4b9b492: (view diff at https://www.antfleet.dev/anatomy/cdf9ffa0-2)

tweet 7 of 881 / 280

AntFleet reviews every PR with two frontier models. Only unanimous findings post.

tweet 8 of 877 / 280

Full anatomy + reasoning + diffs: https://www.antfleet.dev/anatomy/cdf9ffa0-2

Paste into X composer one tweet at a time. X has no multi-tweet intent API.