Skip to content

feat(dgw): encrypt in-memory credentials with optional mlock protection#1689

Open
Benoît Cortier (CBenoit) wants to merge 5 commits intomasterfrom
DGW-326
Open

feat(dgw): encrypt in-memory credentials with optional mlock protection#1689
Benoît Cortier (CBenoit) wants to merge 5 commits intomasterfrom
DGW-326

Conversation

@CBenoit
Copy link
Member

@CBenoit Benoît Cortier (CBenoit) commented Feb 26, 2026

Add ChaCha20-Poly1305 encryption for credentials stored in the
credential store. Passwords are encrypted at rest with a randomly
generated 256-bit master key that is zeroized on drop.

When built with the mlock cargo feature, the master key is
additionally protected via libsodium's mlock/mprotect facilities,
preventing exposure in memory dumps or swap. A startup warning is
emitted in release builds when mlock is not enabled.

In concrete terms: this protects users from leaking important
secrets in the event of capturing a memory dump for, e.g.: debugging purposes.

Issue: DGW-326

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds in-memory encryption for credentials stored by Devolutions Gateway to reduce plaintext exposure in dumps/swap, aligning with DGW-326.

Changes:

  • Introduces ChaCha20-Poly1305 encryption for stored passwords with a lazily initialized process-wide master key.
  • Updates credential ingestion to accept cleartext (API-only) types and encrypt on insert; decrypts on-demand for CredSSP flows.
  • Switches various password-like fields to secrecy::SecretString and updates serialization/usage accordingly.

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
devolutions-gateway/src/rdp_proxy.rs Decrypts stored credentials on-demand before CredSSP; updates Kerberos injection to use ExposeSecret.
devolutions-gateway/src/rd_clean_path.rs Updates Kerberos credential injection to pass password via ExposeSecret.
devolutions-gateway/src/credential/mod.rs Adds encrypted vs cleartext credential types; encrypts on insert and provides decrypt_password().
devolutions-gateway/src/credential/crypto.rs New module implementing ChaCha20-Poly1305 encryption and master-key handling (mlock/mprotect via secrets).
devolutions-gateway/src/config.rs Replaces several password fields with SecretString and adjusts (de)serialization and default checks.
devolutions-gateway/src/api/webapp.rs Uses ExposeSecret when verifying stored password hashes.
devolutions-gateway/src/api/preflight.rs Updates provisioning DTO to cleartext mapping type; changes error mapping for insert failures.
devolutions-gateway/Cargo.toml Adds crypto/secret-handling dependencies (chacha20poly1305, secrets, secrecy, rand).
Cargo.lock Locks new transitive dependencies for added crypto/secret crates.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@CBenoit
Copy link
Member Author

Copilot open a new pull request to apply changes based on the comments in this thread

We accept the panic in the LazyLock though. It’s not really expected to fail under normal conditions. Put the comment about libsodium in the README.md instead.

Copy link
Contributor

Copilot AI commented Feb 26, 2026

Benoît Cortier (@CBenoit) I've opened a new pull request, #1690, to work on those changes. Once the pull request is ready, I'll request review from you.

@CBenoit
Copy link
Member Author

Copilot Please make secrets (libsodium) an optional dependency with a feature flag. When secrets is not available, use secrecy for similar features (minus mlock). Ensure secrets is enabled for production builds. Log a warning on startup when a release build does not include the mlock security with libsodium. Ensure we build with secrets in the CI production builds.

Copy link
Contributor

Copilot AI commented Feb 26, 2026

Benoît Cortier (@CBenoit) I've opened a new pull request, #1691, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Feb 26, 2026

Benoît Cortier (@CBenoit) I've opened a new pull request, #1692, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Copilot AI commented Feb 26, 2026

Benoît Cortier (@CBenoit) I've opened a new pull request, #1693, to work on those changes. Once the pull request is ready, I'll request review from you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me 👍

Add ChaCha20-Poly1305 encryption for credentials stored in the
credential store. Passwords are encrypted at rest with a randomly
generated 256-bit master key that is zeroized on drop.

When built with the `mlock` cargo feature, the master key is
additionally protected via libsodium's mlock/mprotect facilities,
preventing exposure in memory dumps or swap. A startup warning is
emitted in release builds when mlock is not enabled.

Issue: DGW-326
@CBenoit Benoît Cortier (CBenoit) changed the title feat(dgw): encrypt in-memory credentials feat(dgw): encrypt in-memory credentials with optional mlock protection Feb 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants