You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
CheckoutFailed is exactly that shape — it carries cause: Schema.Unknown (packages/core/src/errors.ts:12-16), so the whole object is serialized, nested cause included.
Why that is a credential path
gitClone authenticates the clone URL with a GitHub App installation token before handing it to the sandbox:
If box.gitCheckout(cloneUrl, …) rejects with anything that carries the URL — and git routinely echoes the remote it failed to reach — that URL becomes CheckoutFailed.cause, and stepFailedMd stringifies it into a check-run summary, which is visible to anyone who can see the check. The token is short-lived (~1h) but live at the moment it is published.
Observed
PR #89 produced this summary for real, from a genuine checkout failure:
Here the inner cause was a benign network error, so nothing leaked. It demonstrates the path, not the leak: the same rendering with a git-originated cause is what publishes the token.
Suggested fix
Two independent changes, either of which closes it; both are worth having:
Match CheckoutFailed explicitly and render repo + sha only. Those are the whole diagnosis; the git error tail adds nothing worth carrying a credential to get.
Worth also scrubbing x-access-token:<token>@ at the summary boundary as a backstop, since the URL can reach it through causes other than CheckoutFailed.
Notes
Found while reviewing #89; unrelated to that PR's diff, which is why it is filed separately rather than fixed there.
A step failure whose
causeis neither a string nor anErroris rendered into the check-run summary withJSON.stringify:https://github.com/fractalboxdev/flare-dispatch/blob/e8a1300/apps/dispatcher/src/failure-summary.ts#L59-L67
CheckoutFailedis exactly that shape — it carriescause: Schema.Unknown(packages/core/src/errors.ts:12-16), so the whole object is serialized, nested cause included.Why that is a credential path
gitCloneauthenticates the clone URL with a GitHub App installation token before handing it to the sandbox:https://github.com/fractalboxdev/flare-dispatch/blob/e8a1300/packages/runtime-cf/src/sandbox-clone-url.ts#L21-L23
If
box.gitCheckout(cloneUrl, …)rejects with anything that carries the URL — andgitroutinely echoes the remote it failed to reach — that URL becomesCheckoutFailed.cause, andstepFailedMdstringifies it into a check-run summary, which is visible to anyone who can see the check. The token is short-lived (~1h) but live at the moment it is published.Observed
PR #89 produced this summary for real, from a genuine checkout failure:
Here the inner cause was a benign network error, so nothing leaked. It demonstrates the path, not the leak: the same rendering with a
git-originated cause is what publishes the token.Suggested fix
Two independent changes, either of which closes it; both are worth having:
stepFailedMdshould fall back to a fixed string rather thanJSON.stringify— an unrecognised cause is precisely the case where nothing is known about what its fields hold.runs/org-spec-audit.tstook this approach for its owndescribe()in org-spec-audit: the estate sweep for questions specs can't answer — and two fixes it needed to run #89.CheckoutFailedexplicitly and renderrepo+shaonly. Those are the whole diagnosis; thegiterror tail adds nothing worth carrying a credential to get.Worth also scrubbing
x-access-token:<token>@at the summary boundary as a backstop, since the URL can reach it through causes other thanCheckoutFailed.Notes
Found while reviewing #89; unrelated to that PR's diff, which is why it is filed separately rather than fixed there.