GitHub auto-redacts, but only what it knows
GitHub redacts the literal value of a secret from all log output. If a secret is sk-abc123, every appearance of that string in stdout, stderr, command output, error messages, or annotations gets replaced with ***.
But redaction is literal string match. It cannot redact:
- Encoded versions — base64'd secrets, JSON-escaped secrets, URL-encoded secrets are not the literal string and are not redacted.
- Derived values — JWT signed with the secret, hashes of the secret. These don't equal the secret but can leak it.
- Partial echoes — if your script prints the first 10 chars only, those 10 chars don't trigger redaction.
- Secrets from env in nested processes if you set
set -x(bash debug mode) — bash echoes the entire environment.
Defensive habits
- Pass secrets via
env:, never via shell command-line arguments (those show up in process listings on multi-tenant CI). - Never
echoa secret-containing variable, even for debug. - Pipe sensitive output through
--mask:echo "::add-mask::$VALUE"tells GitHub to redact. - Avoid
set -xin any block that touches secrets. - For multi-line secrets (RSA keys), prefer file-based handoff: write to a file with umask 077 and reference by path.