libsoliton/SECURITY.md
Kamal Tufekcic 1d99048c95
Some checks failed
CI / lint (push) Successful in 1m37s
CI / test-python (push) Successful in 1m49s
CI / test-zig (push) Successful in 1m39s
CI / test-wasm (push) Successful in 1m54s
CI / test (push) Successful in 14m44s
CI / miri (push) Successful in 14m18s
CI / build (push) Successful in 1m9s
CI / fuzz-regression (push) Successful in 9m9s
CI / publish (push) Failing after 1m10s
CI / publish-python (push) Failing after 1m46s
CI / publish-wasm (push) Has been cancelled
initial commit
Signed-off-by: Kamal Tufekcic <kamal@lo.sh>
2026-04-02 23:48:10 +03:00

5.7 KiB

Security Policy

Reporting a Vulnerability

Critical or high severity (key leakage, authentication bypass, ratchet desync that leaks plaintext, FFI memory corruption):

security@lo.sh

Use this for anything an attacker could exploit. If you have our public key, encrypt the report. We will acknowledge within 72 hours and aim to ship a fix within 14 days of confirmation.

Medium or low severity (interoperability bugs, non-exploitable logic errors, documentation issues):

Open an issue at https://git.lo.sh/lo/libsoliton

When in doubt, use the email. We would rather triage a false alarm than miss a real vulnerability.

Supported Versions

Version Supported
0.1.x Yes

Only the latest release is supported. Security fixes are not backported.

Threat Model

In scope

  • Protocol logic in LO-KEX, LO-Ratchet, KEM authentication, and storage encryption. Bugs here (wrong KDF inputs, missing domain separation, ratchet state corruption) are the primary risk.
  • Memory safety in the Rust code and the unsafe FFI boundary (libsoliton_capi). Unsound pointer handling, use-after-free in opaque state objects, buffer overflows in slice construction.
  • Wrapper binding correctness (soliton_py, soliton_wasm, soliton_zig). Incorrect type marshaling, use-after-free of opaque handles, missing zeroization at the binding layer, header serialization mismatches. The Python and WASM bindings wrap the core Rust API via PyO3 and wasm-bindgen respectively (no unsafe in the bindings themselves). The Zig wrapper consumes the C ABI directly.
  • Key management — failure to zeroize secrets, key material leaking into logs or error messages, nonce reuse.
  • Cryptographic misuse — wrong algorithm parameters, truncated hashes, clamping errors, incorrect domain separators.

Out of scope

  • Side-channel attacks in upstream Rust crates. Timing, power, or EM side channels in ML-KEM-768 (ml-kem), ML-DSA-65 (ml-dsa), X25519 (x25519-dalek), or Ed25519 (ed25519-dalek) are upstream concerns. Report those to the relevant RustCrypto or dalek-cryptography project. XChaCha20-Poly1305 and Ed25519 are constant-time by construction (ARX operations only, no table lookups).
  • WASM linear memory. Secret key material in WASM cannot be reliably zeroized — the linear memory is GC-managed by the JS engine and may be copied, paged, or retained after free(). This is inherent to the WASM execution model, not a library bug.
  • Python GC. bytes objects returned by the Python binding are GC-managed. The Rust side zeroizes its copy, but the Python object persists until collected. Context managers (with) minimize the window.
  • Compression oracle (CRIME/BREACH-style). When streaming AEAD compression is enabled and an attacker controls partial plaintext, ciphertext length may leak information about co-resident secret content. File transfer (the primary use case) does not have attacker-controlled plaintext injection, so this is not exploitable in the intended deployment. Applications mixing attacker-controlled and secret data in a single compressed stream should disable compression.
  • Hardware faults — rowhammer, fault injection, glitching.
  • Denial of service — resource exhaustion from large inputs is a bug, but not a security vulnerability in a library context.

Known limitations

  • PQ crates are pre-1.0. ML-KEM and ML-DSA are NIST FIPS 203/204 final, but the RustCrypto implementations (ml-kem, ml-dsa) have not undergone the same decades of scrutiny as, say, OpenSSL's AES. This is inherent to post-quantum cryptography in 2026.
  • X-Wing is a draft. We implement draft-connolly-cfrg-xwing-kem-09. The combiner and encoding may change before the RFC is finalized.
  • Ed25519 (RFC 8032) is used for classical signing via ed25519-dalek. Strict verification mode rejects non-canonical signatures and small-order public keys, preventing malleability attacks.
  • XChaCha20-Poly1305 is constant-time by construction (ARX operations only — no table lookups or secret-dependent branches). No hardware acceleration is required; it runs at full speed on all platforms including RISC-V.

Dependencies

All dependencies are pure Rust — no C libraries, no cmake, no system linker dependencies.

Dependency Role
ml-kem ML-KEM-768 (inside X-Wing)
ml-dsa ML-DSA-65 hybrid signatures
ed25519-dalek Ed25519 signing/verification
x25519-dalek X25519 (inside X-Wing)
chacha20poly1305 XChaCha20-Poly1305 AEAD
sha3 SHA3-256 (HMAC, HKDF, fingerprints, X-Wing combiner)
hmac HMAC-SHA3-256
hkdf HKDF-SHA3-256 key derivation
argon2 Argon2id password hashing
ruzstd Zstd decompression (storage blobs, streaming AEAD chunks)
zeroize Secret wiping

Binding-specific dependencies (not part of the core library):

Dependency Role
pyo3 Python FFI bridge (soliton_py)
wasm-bindgen WASM/JS interop (soliton_wasm)

Vulnerabilities in these dependencies may affect libsoliton. We track upstream advisories and update pins accordingly.