stamparm/maltrail · warning
HMAC accepts a key of any length
Error message
HMAC accepts a key of any length
What it means
mts_sign builds an HMAC-SHA256 via SimpleHmac::new_from_slice(secret.as_bytes()).expect("HMAC accepts a key of any length"). Unlike the block-size-limited Hmac wrapper, SimpleHmac accepts arbitrary key lengths, so new_from_slice can only fail on allocation failure; the expect documents that any secret string is valid.
Solutions
- Keep SimpleHmac (arbitrary-length keys) or switch to Hmac and handle new_from_slice's Result explicitly
- If using Hmac, hash or pad the secret to a valid length before constructing the MAC
- Propagate the error instead of expect if construction can realistically fail
Example fix
// before
let mut mac = SimpleHmac::<sha2::Sha256>::new_from_slice(secret.as_bytes()).expect("HMAC accepts a key of any length");
// after (if switching to Hmac)
let mut mac = hmac::Hmac::<sha2::Sha256>::new_from_slice(secret.as_bytes())
.map_err(|e| format!("HMAC key rejected: {e}"))?; Defensive patterns
Strategy: validation
Validate before calling
assert!(!secret.is_empty(), "MTS secret must be set"); // SimpleHmac accepts any length; only allocation can fail
Try / catch
match SimpleHmac::<sha2::Sha256>::new_from_slice(secret.as_bytes()) {
Ok(mut mac) => { mac.update(payload); /* ... */ },
Err(e) => eprintln!("HMAC init failed: {e}"),
} Prevention
- Keep secrets non-empty and provisioned via secret management
- If switching MAC types, handle new_from_slice's Result explicitly
- Add a round-trip test against core/log.py vectors for any key length
When it happens
Trigger: Practically unreachable with SimpleHmac: only an allocation failure (OOM) during key processing panics. Would become reachable if someone swapped SimpleHmac for hmac::Hmac without handling the error.
Common situations: Refactoring the MAC construction and switching types; OOM on extremely constrained hosts.
Related errors
- hmac accepts any key length
- hex is ascii
- [!] no VERSION constant found in
- [!] no maltrail-sensor package entry found in
- [!] not built - cargo build --release --manifest-path…
AI-assisted analysis of stamparm/maltrail@77cfb06d76 (2026-09-13).
Data as JSON: /api/errors/dff48cfc719a1d41.
Report an issue: GitHub.
Appendix: source
Thrown at sensor/src/output.rs:43
use crate::ignore::IgnoreRules;
use crate::settings;
use crate::whitelist::Whitelist;
/// Immutable, shared output configuration.
/// `MTS1 <32 hex chars> <payload>` - the authenticated framing for a LOG_SERVER datagram.
///
/// The listener on the other end is otherwise open by protocol design: anything that can reach the
/// port can append to the log an operator reasons from. This is the sending half of closing that;
/// `core/log.py:mts_open` is the receiving half and the two are pinned together by generated
/// vectors, because a MAC that disagrees across the two implementations fails as silent data loss -
/// the server simply drops every event this sensor sends, and nothing says why.
///
/// HMAC-SHA256 truncated to 128 bits (RFC 2104 section 5), hex-encoded so the datagram stays
/// greppable text like everything else on this path.
pub fn mts_sign(secret: &str, payload: &[u8]) -> Vec<u8> {
use hmac::{Mac, SimpleHmac};
let mut mac =
SimpleHmac::<sha2::Sha256>::new_from_slice(secret.as_bytes()).expect("HMAC accepts a key of any length");
mac.update(payload);
let tag = mac.finalize().into_bytes();
let mut out = Vec::with_capacity(5 + 32 + 1 + payload.len());
out.extend_from_slice(b"MTS1 ");
for byte in &tag[..16] {
out.push(HEX[(byte >> 4) as usize]);
out.push(HEX[(byte & 0x0f) as usize]);
}
out.push(b' ');
out.extend_from_slice(payload);
out
}
const HEX: &[u8; 16] = b"0123456789abcdef";
#[cfg(test)]
mod mts_tests {View on GitHub (pinned to 77cfb06d76)