Skip to content

Redact AppRole's Debug output (#145) - #146

Merged
CoestPiper merged 1 commit into
mainfrom
CoestPiper/issue-145
Oct 4, 2026
Merged

CoestPiper merged 1 commit into
mainfrom
CoestPiper/issue-145

Conversation

@CoestPiper

@CoestPiper CoestPiper commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

AppRole used to derive Debug, so formatting it with {:?} printed both role_id and secret_id in clear text. The same happened for any type that derives Debug and holds an AppRole. No deploy-core code formats an AppRole today, but bootler keeps AppRoles in types that derive Debug (e.g. RegistrationSteps). Any future tracing field, expect message or error string over those types would leak the secret id. Fixing the type here protects every type that holds one.

Changes:

  • src/bootroot_cmd.rs: Debug is removed from AppRole's derive list. Clone, PartialEq, Eq, Serialize, Deserialize, the fields and their visibility are unchanged, so equality and serialized bytes are unaffected. A hand-written impl std::fmt::Debug for AppRole replaces the derive. It uses debug_struct("AppRole") with role_id then secret_id, prints each as "<redacted>", and ends with .finish(), so any field added later must be classified explicitly. Neither id ever goes through its own Debug. The output is AppRole { role_id: "<redacted>", secret_id: "<redacted>" }. This follows the in-crate precedent of GenerationFile's hand-written Debug.
  • New test app_role_debug_redacts_both_ids: it builds an AppRole with a distinct sentinel in each field. It checks that both {:?} and {:#?} output contain neither sentinel and do contain <redacted>, role_id and secret_id. It also pins the exact compact output. No secret value is compared with assert_eq!/assert_ne!.
  • CHANGELOG.md: a new ## [Unreleased] section has a ### Changed entry saying the Debug output now redacts both ids. The matching [Unreleased] compare link is added too.

role_id is redacted as well as secret_id: it is half of the AppRole login, and bootler's own redactions already treat the pair as secret.

This should merge before the bootler change that re-pins deploy-core to this commit.

Closes #145

Deviations from the issue

None

Test plan

  • app_role_debug_redacts_both_ids (src/bootroot_cmd.rs): builds an AppRole with distinct sentinels in role_id and secret_id, checks that neither {approle:?} nor {approle:#?} contains either sentinel and that both contain <redacted>, role_id and secret_id, and pins the compact output to AppRole { role_id: "<redacted>", secret_id: "<redacted>" }
  • Existing tests pass unchanged: cargo test and cargo test --features test-support
  • cargo fmt -- --check --config group_imports=StdExternalCrate
  • cargo clippy --all-targets -- -D warnings and cargo clippy --all-targets --features test-support -- -D warnings
  • Docs job: RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --document-private-items --features test-support
  • Markdown: markdownlint-cli2 "**/*.md" reports no issues in tracked files, including the new CHANGELOG.md [Unreleased] section and link reference. Locally it flags only a generated license file under target/doc/, which CI never sees
  • CI is green on the PR, including the Platform jobs

AppRole derived Debug, so formatting it -- or any downstream type that
derives Debug over one, such as bootler's registration records --
printed the role id and secret id in clear text. A hand-written Debug
prints both as "<redacted>", which fixes every container at once and
lets bootler stop redacting the pair by hand.

It ends in .finish() rather than .finish_non_exhaustive() so a field
added later has to be classified explicitly.

Closes #145
@CoestPiper

Copy link
Copy Markdown
Contributor Author

[Reviewer Round 1]

No findings. This is a focused, appropriate fix for #145.

  • src/bootroot_cmd.rs:95 formats only literal redaction strings, in the requested field order, using .finish(). Neither credential is read or formatted. Other derives, fields, and serialization behavior remain unchanged.
  • The regression test:109 meaningfully covers compact and pretty output with distinct sentinels and would fail against the previous derive. Its exact-output assertion compares rendered text, not credential values.
  • CHANGELOG.md:7 includes the requested entry and compare reference. The supplied PR body correctly declares Closes #145, includes the test plan, and accurately reports no deviations.

I recommend approval. Tests and CI were not rerun, as instructed.

@CoestPiper

Copy link
Copy Markdown
Contributor Author

[Review Verdict Round 1: APPROVED]

@CoestPiper
CoestPiper merged commit bb3f959 into main Oct 4, 2026
5 checks passed
@CoestPiper
CoestPiper deleted the CoestPiper/issue-145 branch October 4, 2026 07:28
@CoestPiper CoestPiper mentioned this pull request Oct 4, 2026
7 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Redact AppRole's Debug output

1 participant