Summary
skills/turnstile-spin/scripts/validate.sh reports failure for every correctly-configured integration. The dummy-token check can never observe success: false, which is the exact response it is written to accept.
Cause
Line:
success=$(echo "$dummy" | (jq -r '.success // "missing"' 2>/dev/null || echo "missing"))
jq's // is the alternative operator: it returns the right-hand side when the left is null or false. Since siteverify returns "success": false for a dummy token, .success // "missing" evaluates to "missing", never "false".
$ echo '{"success":false}' | jq -r '.success // "missing"'
missing
$ echo '{"success":false}' | jq -r '.success'
false
Control flow then hits:
if [ "$success" != "false" ]; then
echo "{\"status\":\"error\",\"check\":\"dummy_siteverify\",...}"
exit 1
fi
so the invalid-input-response branch below it is unreachable.
Reproduction
With a valid secret and any dummy token:
$ TURNSTILE_SECRET=<valid secret> ./validate.sh --sitekey <sitekey>
validate: unexpected shape for dummy token: {"error-codes":["invalid-input-response"],"success":false,"messages":[]}
{"status":"error","check":"dummy_siteverify","detail":"expected success:false on a dummy token"}
That response is the documented success signal — SKILL.md's own edge-case table says invalid-input-response "means the secret IS valid. validate.sh treats this as success." It does not.
This is reproducible with the published test secret 1x0000000000000000000000000000000AA, so it needs no real credentials.
Impact
Step 10 (Validation) fails for every user with a working setup. SKILL.md instructs the agent to "surface the error and stop" on validation failure, so a correct integration is reported as broken at the final step.
Suggested fix
success=$(echo "$dummy" | (jq -r 'if has("success") then .success else "missing" end' 2>/dev/null || echo "missing"))
Verified against live siteverify with both the always-pass and always-fail test secrets.
Note on the Python fallback
The || fallbacks throughout these scripts mask this class of bug: when jq is absent the fallback yields "missing", producing the same misleading error for a different reason. Worth distinguishing "parser unavailable" from "field absent".
Summary
skills/turnstile-spin/scripts/validate.shreports failure for every correctly-configured integration. The dummy-token check can never observesuccess: false, which is the exact response it is written to accept.Cause
Line:
success=$(echo "$dummy" | (jq -r '.success // "missing"' 2>/dev/null || echo "missing"))jq's
//is the alternative operator: it returns the right-hand side when the left isnullorfalse. Since siteverify returns"success": falsefor a dummy token,.success // "missing"evaluates to"missing", never"false".Control flow then hits:
so the
invalid-input-responsebranch below it is unreachable.Reproduction
With a valid secret and any dummy token:
That response is the documented success signal — SKILL.md's own edge-case table says
invalid-input-response"means the secret IS valid. validate.sh treats this as success." It does not.This is reproducible with the published test secret
1x0000000000000000000000000000000AA, so it needs no real credentials.Impact
Step 10 (Validation) fails for every user with a working setup. SKILL.md instructs the agent to "surface the error and stop" on validation failure, so a correct integration is reported as broken at the final step.
Suggested fix
success=$(echo "$dummy" | (jq -r 'if has("success") then .success else "missing" end' 2>/dev/null || echo "missing"))Verified against live siteverify with both the always-pass and always-fail test secrets.
Note on the Python fallback
The
||fallbacks throughout these scripts mask this class of bug: whenjqis absent the fallback yields"missing", producing the same misleading error for a different reason. Worth distinguishing "parser unavailable" from "field absent".