Skip to content

Conversation

@quexten
Copy link
Contributor

@quexten quexten commented Oct 28, 2025

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-27518

Fixes:
bitwarden/clients#17028
bitwarden/clients#14076

📔 Objective

Updates the bitwarden-ssh dependencies to rc releases from RustCrypto. This allows us to:

  • Drop our PKCS5 patch crate
  • Fix import of putty keys
  • Fix import of various other broken keys (linewidth issues and others)

It also replaces the RSA crate that has a vulnerability (timing attack) - though, it is unlikely that this actually affects import / was abusable.

RSA key generation test vectors are broken because the underlying RSA generation algorithm changed with rustcrypto's massive re-implementation of RSA, hence new test keys are provided.

Note: This pins the dependencies to be different from the workspace crates, as those are not yet ready to be updated. Eventually we will update those bit-by-bit too and then drop the dependency pinning.

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation
    team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed
    issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@github-actions
Copy link
Contributor

github-actions bot commented Oct 28, 2025

Logo
Checkmarx One – Scan Summary & Detailsaf4cd2b2-87e5-4427-95ad-e983a190d64f

Great job! No new security vulnerabilities introduced in this pull request

@quexten quexten marked this pull request as ready for review October 29, 2025 18:41
@quexten quexten requested a review from a team as a code owner October 29, 2025 18:41
@quexten quexten requested a review from addisonbeck October 29, 2025 18:41
@quexten quexten changed the title [BEEEP] Update ssh dependencies and fix imports of various SSH keys [BEEEP] Update bitwarden-ssh RustCrypto dependencies, fixing imports of various SSH keys Oct 29, 2025
@claude
Copy link

claude bot commented Oct 29, 2025

Claude finished @quexten's task —— View job


Code Review Completed

I've completed a thorough review of PR #536. This PR updates the bitwarden-ssh crate to use RustCrypto RC releases, fixing several SSH key import issues.


Summary of Changes

This PR makes significant dependency upgrades to the bitwarden-ssh crate:

Dependency Updates:

  • ssh-key: >=0.6.7, <0.70.7.0-rc.3
  • ed25519: >=2.2.3, <3.03.0.0-rc.1
  • ed25519-dalek: workspace → =3.0.0-pre.1 (pinned)
  • rsa: >=0.9.2, <0.100.10.0-rc.9
  • pkcs8: >=0.10.2, <0.11=0.11.0-rc.7
  • pem-rfc7468: 0.7.01.0.0-rc.3
  • rand: >=0.8.5, <0.90.9.2
  • rand_chacha: 0.3.10.9.0 (dev dependency)
  • Added block-padding =0.4.0-rc.4 and getrandom =0.3.3

Key Improvements:

  • Drops the PKCS5 patch crate (no longer needed)
  • Fixes import of PuTTY-exported keys
  • Fixes import of keys with line width issues (addresses #17028)
  • Replaces RSA crate with version that addresses timing attack vulnerability
  • RSA test vectors regenerated due to algorithm changes in RustCrypto

Critical Issues

None found. The changes are well-implemented and appropriately scoped.


Suggested Improvements

1. Documentation of Backward Compatibility ⚠️

Location: PR description and/or code comments

The CLAUDE.md guidelines emphasize that "Existing encrypted data must remain decryptable." While this PR updates cryptographic library versions, there's no explicit documentation confirming backward compatibility testing.

Recommendation: Add a note in the PR description or commit message confirming that:

  • Existing SSH keys encrypted/exported with the old library versions can still be imported
  • The export format remains compatible with previous versions
  • Any testing performed to verify this
Why this matters

Per repository guidelines:

Encryption/decryption modifications

  • Verify backward compatibility. Existing encrypted data must remain decryptable.

While the changes appear to maintain compatibility (same formats, just library updates), explicit documentation would provide confidence for reviewers and future maintainers.

2. Dependency Version Pinning Strategy 📝

Location: crates/bitwarden-ssh/Cargo.toml:30-37

The PR pins several dependencies to exact RC versions (using =), diverging from workspace dependencies. The PR description mentions this is temporary, but there's no tracking issue or TODO comment.

block-padding = { version = "=0.4.0-rc.4" }
ed25519-dalek = { version = "=3.0.0-pre.1", features = ["alloc", "pkcs8"] }
pkcs8 = { version = "=0.11.0-rc.7", features = ["encryption"] }
rsa =  "0.10.0-rc.9"

Recommendation: Add a comment referencing a tracking issue for updating workspace dependencies:

# TODO(PM-XXXXX): Align with workspace dependencies once RustCrypto stable releases are available

3. WASM Build Configuration 🤔

Location: crates/bitwarden-wasm-internal/build.sh:49

The change adds a new getrandom_backend cfg flag:

-RUSTFLAGS=-Ctarget-cpu=mvp
+RUSTFLAGS='-Ctarget-cpu=mvp --cfg getrandom_backend="wasm_js"'

This is related to adding getrandom/wasm_js feature in Cargo.toml. However, the interaction between:

  • The Cargo feature: getrandom/wasm_js
  • The cfg flag: --cfg getrandom_backend="wasm_js"

...could be clearer.

Recommendation: Add a comment in build.sh explaining why both the feature flag and the cfg are needed, or if one is redundant.

Technical context

The newer getrandom versions changed how WASM backends are configured. Both approaches might be defensive programming to ensure compatibility, but documentation would clarify intent.

4. Error Context Loss 📝

Location: crates/bitwarden-ssh/src/import.rs:67,75

The code converts detailed keypair construction errors into generic SshKeyImportError::Parsing:

ssh_key::private::PrivateKey::from(Ed25519Keypair::from(&private_key.secret_key.into()))
// vs
ssh_key::private::PrivateKey::from(
    RsaKeypair::try_from(private_key).map_err(|_| SshKeyImportError::Parsing)?,
)

Observation: The RSA path uses try_from which could fail, but the error is discarded. The Ed25519 path uses infallible conversions.

Recommendation: Consider if the RSA error should be logged (at debug level) before being converted to Parsing, to aid future debugging. However, this may be fine as-is per the "no secrets in logs" policy.

5. Type Annotations Cleanup 🎨

Location: crates/bitwarden-ssh/src/import.rs:62-67

The Ed25519 import path has evolved to have verbose intermediate conversions:

let private_key: ed25519::KeypairBytes = private_key_info
    .try_into()
    .map_err(|_| SshKeyImportError::Parsing)?;

ssh_key::private::PrivateKey::from(Ed25519Keypair::from(&private_key.secret_key.into()))

The .into() on secret_key and then from seems like it could be simplified, but this might be required by the updated library types.

Recommendation: Verify if the double conversion is necessary or if there's a more direct path. If necessary, a comment explaining the type dance would help.


Good Practices Observed

  • ✅ Comprehensive test coverage for new functionality (PuTTY keys, regression tests)
  • ✅ Test vectors properly updated after RSA algorithm changes
  • ✅ No unsafe code introduced
  • ✅ No secrets exposed in error paths
  • ✅ All unit tests passing
  • ✅ Clean removal of workaround code (manual RSA conversion function)
  • ✅ Proper use of .map_err() to maintain error context boundaries

Action Items for Author

  1. Optional but Recommended: Add backward compatibility verification notes to PR description
  2. Optional: Add TODO comment with tracking issue for workspace dependency alignment
  3. Optional: Clarify WASM build configuration in comments
  4. Consider: Adding debug logging for RSA conversion errors (if it doesn't violate secret logging policy)

Testing Notes

✅ CI Status: All tests passed (the one failure was unrelated - coverage tool installation issue)

  • WASM build: ✅ Success
  • Windows tests: ✅ Success
  • Ubuntu tests: ✅ Success
  • macOS tests: ✅ Success

The test failure in "Coverage" job was due to cargo-llvm-cov installation issues, not code problems.


Security Assessment

No security concerns identified:

  • RSA timing attack vulnerability is addressed (upgraded to 0.10.0-rc.9)
  • No new unsafe code
  • No secrets in error paths
  • Cryptographic library changes are from reputable source (RustCrypto)
  • Test coverage validates functionality

Conclusion

This is a solid, well-tested PR that addresses real user pain points (PuTTY key imports, line width issues) while also addressing a security concern in the RSA crate. The code changes are clean and the dependency updates are appropriate.

The main suggestions are documentation improvements and minor clarifications - the core implementation is sound. Recommend approval with optional follow-ups on documentation.


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.

2 participants