Skip to content

Redact KMS URI secrets from plugin error output#1669

Open
TicketWindowSeat wants to merge 1 commit into
smallstep:masterfrom
TicketWindowSeat:redact-kms-uri-secrets
Open

Redact KMS URI secrets from plugin error output#1669
TicketWindowSeat wants to merge 1 commit into
smallstep:masterfrom
TicketWindowSeat:redact-kms-uri-secrets

Conversation

@TicketWindowSeat

Copy link
Copy Markdown

Name of feature:

Redact KMS URI secrets (pin-value, management-key, client-secret) from the error
printed when a step-kms-plugin subprocess fails.

Pain or issue this feature alleviates:

When the plugin subprocess fails, step prints the full command line it ran — including
the KMS URI with any inline credential. A real ceremony on Windows (step 0.30.6,
step-kms-plugin 0.17.0, YubiKey 4) produced:

error creating certificate request: command "C:\\Users\\...\\step-kms-plugin.exe sign --format base64 --kms yubikey:serial=NNNNNNN;pin-value=<THE ACTUAL PIV PIN> yubikey:slot-id=9c" failed with:
Error: command failed: smart card error 6982: security status not satisfied

pin-value= is the documented way to supply the PIN non-interactively, so using the
feature as designed puts the secret on stderr on any failure. From there it lands in
console scrollback, session transcripts, CI logs — and GitHub issues, because pasting
exactly this error text is what users do when reporting bugs.

Why is this important to the project (if not answered above):

  1. Secret disclosure through the documented mechanism, on the error path users hit most.
  2. Error-paste amplification: the current design invites PIV PINs into public issue
    trackers and search indexes.
  3. The fix is small and non-breaking: the command echo is genuinely useful for debugging
    and is kept — only the values of the three credential-carrying attributes across all
    KMS schemes (pin-value for yubikey/pkcs11/capi, management-key for yubikey,
    client-secret for azurekms) are replaced with REDACTED. The redaction runs over
    the whole rendered command line, so it also covers a secret that reaches the plugin
    as a positional argument — --attestation-uri is passed as both the --kms value
    and the positional key argument (utils/cautils/acmeutils.go).

The plugin's own stderr is scrubbed with the same expression before being embedded,
because step-kms-plugin echoes the URI itself on some paths (e.g.
%s does not implement Attester in cmd/attest.go), and go.step.sm/crypto's
uri.Parse errors embed the raw URI as well.

Redaction stops the value at the next URI delimiter (;, &, ?), whitespace, or a
double quote, so the surrounding command line and any Go-quoted error prose stay intact.
One residual limitation, inherent to string-level redaction: a value containing a raw,
non-percent-encoded space is only redacted up to that space. Such a URI is malformed
(a well-formed URI percent-encodes the space, which redacts fully); the fix trades a
rare partial leak for keeping the rest of the command readable, rather than
over-redacting every failure message.

Is there documentation on how to use this feature? If so, where?

No behavior to document: error output now shows pin-value=REDACTED in place of the
secret; everything else is unchanged.

In what environments or workflows is this feature supported?

Redact KMS URI secrets (pin-value, management-key, client-secret) from the error
printed when a step-kms-plugin subprocess fails.

In what environments or workflows is this feature explicitly NOT supported (if any)?

All platforms and all KMS schemes; the redaction is plain string processing in
internal/cryptoutil with hardware-free unit tests (the package's first).

Supporting links/other PRs/issues:

💔Thank you!

When a step-kms-plugin subprocess fails, exitError embeds the full
command line in the returned error via cmd.String(). If the KMS URI
carries an inline credential, the secret is printed in cleartext:

  error creating certificate request: command
  ".../step-kms-plugin sign --format base64 --kms
  yubikey:serial=NNN;pin-value=<PIN> yubikey:slot-id=9c" failed with:
  Error: command failed: smart card error 6982: ...

pin-value is the documented way to supply the PIN non-interactively,
and this error text is exactly what users paste into terminals, CI
logs, and public bug reports.

Redact the values of the three KMS URI attributes that carry
credentials -- pin-value (yubikey, pkcs11, capi), management-key
(yubikey), and client-secret (azurekms) -- from both the echoed
command line and the plugin's passed-through stderr, keeping the rest
of the command intact for debugging. The stderr is scrubbed too
because step-kms-plugin echoes the URI itself on some error paths
(e.g. "%s does not implement Attester").

Fixes smallstep#1668
@CLAassistant

CLAassistant commented Jul 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@github-actions github-actions Bot added the needs triage Waiting for discussion / prioritization by team label Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs triage Waiting for discussion / prioritization by team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: step prints KMS URI secrets (pin-value, etc.) in cleartext when step-kms-plugin fails

3 participants