From 2431342277e3f01c52299a7c69bb3dd8857ff475 Mon Sep 17 00:00:00 2001 From: Michiel Degezelle Date: Wed, 22 Jul 2026 16:58:21 +0200 Subject: [PATCH] fix: validate token shape before treating post-run config as rotated AFTER_TOKEN was compared to BEFORE_TOKEN without checking it's actually a non-empty string first, unlike the "Load PARTNER_CONFIG_JSON" step, which does validate shape. If config.json ends up missing partnerCredentials[partner].token after the run (e.g. a partial/crashed write by the CLI), `jq -r` prints the literal string "null", which differs from BEFORE_TOKEN and reads as "rotated" - triggering an unconditional gh secret set that overwrites the good secret with a broken config. Since this secret has no other writer, that's unrecoverable for the partner until someone manually re-authorizes. Fail closed instead. Found via CodeRabbit review on lu_market#765 and nl_market#893, which had temporarily inlined this job (unrelated experiment); this is the actual upstream source both copies inherited the bug from. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/run_sampler.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/run_sampler.yml b/.github/workflows/run_sampler.yml index baf16f9..94faabf 100644 --- a/.github/workflows/run_sampler.yml +++ b/.github/workflows/run_sampler.yml @@ -266,6 +266,10 @@ jobs: fi AFTER_TOKEN=$(jq -r --arg p "${PARTNER}" '.partnerCredentials[$p].token' "$HOME/.silverfin/config.json") echo "::add-mask::${AFTER_TOKEN}" + if ! jq -e --arg p "${PARTNER}" '(.partnerCredentials[$p].token | type == "string" and length > 0)' "$HOME/.silverfin/config.json" > /dev/null 2>&1; then + echo "::error::Partner ${PARTNER} config.json has no valid token after the run — refusing to write back a possibly broken config." + exit 1 + fi if [[ "${AFTER_TOKEN}" == "${BEFORE_TOKEN}" ]]; then echo "Partner token unchanged — no write-back needed (sole-writer secret stays untouched)." exit 0