fix(#2911): stop putting the minted forge token in an error string

mint_token interpolated forgejo's raw stdout into its anyhow context on
the parse-failure path, and on that call stdout carries the access token
that was just created. The happy path below it is careful to log only
the user and token names; the error path handed the secret over whole.

It fires exactly when forgejo's output format drifts, which is the same
drift that breaks extract_token in the first place -- so the "help me
debug this" context printed the secret it had failed to find.

Report the shape of the output (bytes, lines) instead of its contents.
That is what diagnoses a version drift anyway: you want to know forgejo
printed something with no token-shaped word in it, not the bytes.

Redaction at a logging call site does not cover the error path.
with_context and bail! are output channels too.
This commit is contained in:
atlas 2026-08-02 04:44:22 +02:00
commit 1f8cfdabd9

View file

@ -304,8 +304,18 @@ async fn mint_token(name: &str, scopes: &str) -> Result<String> {
scopes,
])
.await?;
let token = extract_token(&stdout)
.with_context(|| format!("parse token from forgejo output: {stdout:?}"))?;
// Deliberately does NOT include `stdout`: on this path forgejo has
// already minted a live token and printed it, and an error string
// propagates into logs the same way any other message does. The
// shape of the output is enough to diagnose a version drift.
let token = extract_token(&stdout).with_context(|| {
format!(
"no token-shaped word (>= 32 hex chars) in forgejo output \
({} bytes, {} lines); output withheld, it carries the token",
stdout.len(),
stdout.lines().count()
)
})?;
tracing::debug!(%name, %token_name, "forge: minted access token");
Ok(token)
}