Skip to content

Security: primetype/slither

Security

SECURITY.md

Security Policy

slither is a WireGuard-shaped Noise-over-UDP packet layer: an authenticated, encrypted datagram session (Noise IK over P-256 / ChaCha20-Poly1305 / BLAKE2b, via hiss) carrying a reliable frame layer inside the sealed packets. This document covers what the protocol layer does and does not defend against. For the cryptographic primitives, the per-pattern Noise properties, side-channel posture and validated test vectors, see hiss's SECURITY.md — everything Noise-level is inherited from there.

Audit status

slither has not been independently audited. The design borrows deliberately from audited and widely deployed protocols — WireGuard's handshake shape and timers, QUIC's recovery — but this implementation has received no third-party security review, and the borrowed pedigree does not transfer. Weigh that when deciding what to protect with it.

Reporting a vulnerability

Please report security issues privately. Do not open a public issue or PR for a suspected vulnerability.

Use GitHub's private vulnerability reporting:

➡️ https://github.com/primetype/slither/security/advisories/new

(Repository → Security tab → Report a vulnerability.)

Please include enough detail to reproduce — the affected packet/frame path, a proof of concept or failing test if you have one, and the version/commit.

Supported versions

Only the latest published release receives security fixes.

What a session guarantees

Within an established session, each accepted Data packet is confidential, authenticated, and accepted exactly once (the RFC 6479-shaped replay window suppresses duplicates and replays). The frame layer on top adds reliable, unordered, exactly-once message delivery; its retransmissions ride fresh packet counters, so reliability never weakens the replay rule.

Threat model highlights

  • mac1 is a DoS gate, not an authenticator. The 16-byte tag on both handshake packets is keyed by the recipient's public static — anyone who knows that public key can compute it. Its job is to make a garbage flood and mis-addressed packets droppable before any curve/DH work; the real authentication is the Noise IK handshake underneath.
  • The msg1 timestamp payload is 0-RTT. Per Noise §7.7, an IK msg1 payload is authenticated only by the static–static DH: it is replayable and KCI-forgeable in isolation. slither carries only the 12-byte initiation timestamp there and applies WireGuard's defence — a responder accepts an initiation only with a strictly greater timestamp per static — so a recorded msg1 cannot re-establish a session. Responder cost is staged (a ratified property, pinned by test): mac1 rejects before any DH, an unlisted static costs exactly one DH (es), and the timestamp is checked as soon as the msg1 payload opens, before the msg2 DHs.
  • Roaming trusts the seal, not the source address. A session's endpoint moves only when a packet from the new address authenticates and is replay-fresh. An off-path attacker cannot redirect a session; an on-path attacker who can drop and re-inject traffic can, as in WireGuard.
  • Admission is application-driven, not a slither allow-list. slither holds no list of permitted statics. The staged accept ladder (IntroClaimedProvenConnection) hands the application the claimed static after 1 DH; the application decides whether to continue (authenticate()) or reject (drop the object — no bytes sent). Revoking an established peer is the application's own job: nothing here re-checks a list once a connection is up.
  • Randomness. Handshake ephemerals are drawn from a caller-supplied CSPRNG via hiss; every handshake retransmit uses a fresh ephemeral (the WireGuard requirement). The endpoint's index/jitter CSPRNG is a ChaCha20Rng seeded from OS entropy (getrandom). The seed is not currently zeroized after use — it is a plain [u8; 32] on the stack, dropped without an explicit wipe.

Known limitations and non-goals (v1, ratified)

  • No cookies / mac2: under a spoofed-source flood, mac1 bounds the work per packet to one keyed hash, but there is no per-source cookie challenge; CPU-exhaustion resistance is weaker than WireGuard's full design.
  • Congestion control has no pacing (ratified out of v1, §14.7): NewReno backs off on loss (RFC 9002 recovery + PTO), but sends are not paced to sub-RTT smoothness — a 12 KB initial window bounds bursts, but there is no ECN and no alternate controller (CUBIC/BBR). Evaluate burstiness before pointing it at the open internet at scale.
  • Traffic analysis is out of scope: packet sizes, timing, and the cleartext header fields (type, version, indices, counter) are visible. There is no padding.
  • No persistence: reliability lives within a connection; what a dead connection had not delivered is lost.
  • No PSK / first-contact secrecy gating: slither v1 is plain IK. The initiator's static is hidden from a passive observer, with the standard IK caveats (see hiss's per-pattern table).

There aren't any published security advisories