
Cloud Vulnerability DB
A community-led vulnerabilities database
Several kyberlib types that hold secret material derived Debug, so
formatting one with {:?} or {:#?} writes the secret bytes to the
output:
| Type | Secret printed | Scope of the secret |
|---|---|---|
kyberlib::Keypair (legacy API) | the full decapsulation (secret) key | long-term |
kyberlib::Uake, kyberlib::Ake (kex module) | shared_secret, the ephemeral KDF key temp_key, the ephemeral secret key eska | one key exchange |
kyberlib_wasm::Keys (and kyberlib::wasm::Keys with the wasm feature, 0.0.2 to 0.0.6) | the secret key | long-term |
kyberlib_wasm::Kex (and kyberlib::wasm::Kex, 0.0.2 to 0.0.6) | the shared secret | one encapsulation |
kyberlib::symmetric::KeccakState | the sponge lanes, which hold the absorbed input verbatim until the first permutation | whatever the caller absorbed |
kyberlib::symmetric::XofState with the 90s feature (Aes256CtrCtx) | the expanded AES-256 key schedule, which yields the absorbed key | whatever the caller absorbed |
| An application that passes one of these values to a logger, a panic | ||
or error message, dbg!, or a tracing span records the secret | ||
| wherever that output goes (log files, log aggregation, crash | ||
| reporters, CI output). Anyone who can read that output can: | ||
- with a leaked Keypair or wasm Keys, decapsulate every | ||
| ciphertext sent to the matching public key, including recorded | ||
| past traffic, until the key is replaced; | ||
- with a leaked Uake, Ake or wasm Kex, recover the shared | ||
| secret of that one exchange and decrypt the traffic protected by | ||
| it; | ||
- with a leaked KeccakState or 90s XofState, recover data the | ||
| caller absorbed into it. kyberlib itself only builds these states | ||
| internally and never formats them; only callers that create and | ||
| log their own states are exposed. | ||
The typed ML-KEM API (MlKem512/MlKem768/MlKem1024 decapsulation | ||
keys and SharedSecret) and the kyberlib-hybrid types are not | ||
affected: they already print [REDACTED <n> bytes]. | ||
| kyberlib never logs these values itself. An application is affected | ||
only if it formats one of them with Debug, directly or as a field of | ||
a type that derives Debug. | ||
wasm-bindgen does not expose Debug to JavaScript, so JavaScript | ||
callers of kyberlib-wasm are not affected; only Rust code that | ||
| formats the wrapper types is. |
Checked by downloading every published .crate from crates.io and
reading the derive on each type, and by git grep on the tags.
| Package | Types | Affected versions |
|---|---|---|
kyberlib | Keypair, Uake, Ake | >= 0.0.2, < 0.0.11 (0.0.2, 0.0.3, 0.0.4, 0.0.5, 0.0.6, 0.0.7, 0.0.10) |
kyberlib | symmetric::KeccakState | >= 0.0.4, < 0.0.11 (crate-private before 0.0.4) |
kyberlib with feature 90s | symmetric::XofState (Aes256CtrCtx) | >= 0.0.2, < 0.0.11 |
kyberlib with feature wasm | wasm::Keys, wasm::Kex | >= 0.0.2, <= 0.0.6 (the module moved to kyberlib-wasm in 0.0.7) |
kyberlib-wasm | Keys, Kex | >= 0.0.7, < 0.0.11 (0.0.7, 0.0.10) |
| kyberlib 0.0.1 contains none of these types. 0.0.8 and 0.0.9 were | ||
| never published. |
use kyberlib::{keypair, Uake};
fn main() {
let mut rng = rand::thread_rng();
let keys = keypair(&mut rng).unwrap();
// Prints every secret key byte.
println!("{keys:?}");
let mut alice = Uake::new();
alice.client_init(&keys.public, &mut rng).unwrap();
// Prints the ephemeral secret key (eska) and temp_key.
println!("{alice:?}");
}Fixed in kyberlib 0.0.11 and kyberlib-wasm 0.0.11. Each type now
implements Debug by hand and prints secret buffers by length only,
for example:
Keypair { public: [1184 bytes; not secret], secret: [REDACTED 2400 bytes] }
Uake { shared_secret: [REDACTED 32 bytes], send_a: [2272 bytes; not secret], send_b: [1088 bytes; not secret], temp_key: [REDACTED 32 bytes], eska: [REDACTED 2400 bytes] }(sizes shown for ML-KEM-768). 0.0.11 also derives Zeroize and
ZeroizeOnDrop on Uake and Ake, so their secrets are cleared
when the value is dropped.
Upgrade with cargo update -p kyberlib -p kyberlib-wasm.
If you cannot upgrade yet:
Debug, and do not put
one inside a type that derives Debug and is logged.Debug that omits the
secret fields.Keypair to the typed API (MlKem768::generate,
MlKem768DecapKey), whose Debug output is already redacted.Keypair {, Keys {, Uake {, Ake {,
Kex {, KeccakState { and Aes256CtrCtx {. Treat any long-term
key that appears there as compromised: generate a new keypair and
retire the old one. A leaked session secret cannot be revoked;
treat the traffic of that session as disclosed.Found during an internal review of the kyberlib.com rebuild.
CVSS 3.1 for the advisory (the highest of the affected types):
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N (4.7, Medium)
Keypair, wasm Keys (long-term secret key): 4.7, the vector
above. The key is exposed only if the application logs the value
and the attacker can read those logs (local access, high
complexity, low privileges); the result is full loss of
confidentiality for everything sent to that key, and no integrity
or availability impact.Uake, Ake, wasm Kex (one exchange's secrets):
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N (2.5, Low). Same
preconditions, but the secrets are ephemeral, so a leak discloses
one session and no long-term key.KeccakState, 90s XofState: CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
(2.5, Low). kyberlib never exposes its own internal states, so only
data a caller absorbs into a state it created and then logs is at
risk.Source: NVD
Free Vulnerability Assessment
Evaluate your cloud security practices across 9 security domains to benchmark your risk level and identify gaps in your defenses.
Get a personalized demo
"Best User Experience I have ever seen, provides full visibility to cloud workloads."
"Wiz provides a single pane of glass to see what is going on in our cloud environments."
"We know that if Wiz identifies something as critical, it actually is."