From ce64036407f1dbe3f944951ebe878ab59ca63050 Mon Sep 17 00:00:00 2001 From: Rowan Date: Sun, 26 Jul 2026 16:05:04 -0400 Subject: [PATCH 1/2] CLAUDE.md: record that Cargo.lock is gitignored here on purpose My own board carried this as an inconsistency to settle -- "serialize.rs and reliable.rs commit one; netcode.rs does not" -- framed as if this repo were the outlier. It has it backwards. This .gitignore is hand-written and lists Cargo.lock beside the fuzz artifacts; the other two never mention it, so their locks are committed by OMISSION rather than by decision, and both are near-empty (1 and 2 packages) because those crates have essentially no dependencies. This is the only Rust port with real ones. I had already run cargo generate-lockfile here before checking, which is exactly the failure the hot blocks exist to stop, committed minutes after I finished writing them. The .gitignore is what caught me. Recording it where the next person will hit it first. Co-Authored-By: Claude Opus 5 --- CLAUDE.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index a6682a9..f65d2ea 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -40,6 +40,17 @@ mint a new one — it is the wrong machine account. Either Glenn publishes from account, or he moves the token into the mas keychain with the prompting form (`security add-generic-password -U -a rowan -s crates-io-token -w`, no value after -w). Verified 2026-07-26: crates.io has netcode-official 1.0.0 while this repo is at 1.1.0. + +CARGO.LOCK IS GITIGNORED HERE ON PURPOSE +`.gitignore` lists `Cargo.lock` and `fuzz/Cargo.lock` deliberately, hand-written beside +the fuzz artifacts. This is a library crate: dependents do not use its lock, and this is +the only one of the three Rust ports with real dependencies (57 packages via +chacha20poly1305). serialize.rs and reliable.rs DO commit a lock, but by omission rather +than decision -- neither .gitignore mentions it, and both locks are near-empty (1 and 2 +packages) because those crates have essentially no dependencies. Do not "fix" the +inconsistency by adding a lock here; the considered choice is this one. +Note the lock IS packaged into the published .crate, so if this is ever revisited it is +a version site, not just a dev-convenience question. ## Build and test From 1358100249db0ac7beb9e780895f2b8adabf3fb4 Mon Sep 17 00:00:00 2001 From: Rowan Date: Sun, 26 Jul 2026 18:41:12 -0400 Subject: [PATCH 2/2] Add SECURITY.md This repository had no security policy. It parses untrusted data off the wire and had nowhere for someone to report a vulnerability privately, and nowhere for a reader to check whether the version they have is affected by anything. Records the private reporting path, the scope, and the deliberate write/read asymmetry this family follows: on write the caller validates and assertions are a development aid; on read the library checks, because that is where untrusted data arrives. Co-Authored-By: Claude Opus 5 --- SECURITY.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..c76bd6b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,69 @@ +# Security Policy + +netcode.rs implements an encrypted, connection-oriented protocol over UDP. It parses +untrusted data straight off the wire — packets, connect tokens, and the challenge exchange +— and it holds the keys, so we take memory-safety and protocol bugs seriously. + +## Reporting a vulnerability + +**Please do not report security issues in public GitHub issues or pull requests.** + +Report privately through either channel: + +- **GitHub private vulnerability reporting** (preferred): on this repository, go to the + **Security** tab → **Report a vulnerability**. This opens a private advisory visible only + to the maintainers. +- **Email**: glenn@mas-bandwidth.com. + +Please include enough detail to reproduce: the affected version or commit, a description of +the flaw, and — where possible — a proof-of-concept input or a small patch. A failing +`cargo test` case or a fuzz artifact is ideal. + +We will acknowledge your report, keep you updated on our assessment, and coordinate +disclosure timing with you. We prefer coordinated disclosure and will credit reporters who +wish to be named. + +## Scope + +In scope — bugs in this crate: packet parsing, connect token handling, the challenge +exchange, replay protection, and the cryptographic plumbing around them. + +Especially of interest: panics or incorrect acceptance reachable from a received packet or +connect token, and protocol flaws that let a peer bypass authentication, encryption, or +replay protection. + +The crate is `#![forbid(unsafe_code)]`, enforced by the compiler, so classic memory +corruption is off the table by construction. That makes *logic* flaws the interesting +class here: a panic is a denial of service, and a wrongly-accepted packet is worse. + +The protocol itself is specified in `STANDARD.md`. **A flaw in the *specification* — as +opposed to this implementation of it — is in scope and is more valuable to us**, because it +affects every implementation of netcode rather than one. Report those the same way. + +## netcode.rs is NOT affected by the AEAD nonce reuse issue + +Stated explicitly, because the rest of the netcode family *is* and silence would invite the +wrong inference. + +The C implementation seeded its server global packet sequence only on *create* and not on +*start*, so a server stopped and restarted in the same process could reuse a `(key, nonce)` +pair — [GHSA-3x95-24j9-7448](https://github.com/mas-bandwidth/netcode/security/advisories/GHSA-3x95-24j9-7448), +affecting `netcode` ≤ 1.3.5. `yojimbo` ≤ 1.6.3 inherited it by vendoring +([GHSA-hqp3-fj6v-hrpc](https://github.com/mas-bandwidth/yojimbo/security/advisories/GHSA-hqp3-fj6v-hrpc)), +and `netcode.go` v1.0.0–v1.0.2 had the same defect independently +([GHSA-wgmm-f3w5-7c6q](https://github.com/mas-bandwidth/netcode.go/security/advisories/GHSA-wgmm-f3w5-7c6q)). + +**netcode.rs never shipped that defect.** Its 1.0.0 release already kept the global and +per-client nonce spaces disjoint. The 1.1.0 release is often mistaken for the fix because +of its timing; it was a licence change with no code change. + +The property is locked down by tests rather than left to inspection: one takes the sequence +off the wire — decrypting a real challenge packet under the connect token's key and +asserting the nonce stays in the reserved half — and another checks each entry point +restores the floor on its own. The wire-level test exists because the reseed sites are +individually redundant here, so a purely behavioural test cannot catch a single-site +regression. + +## Supported versions + +Security fixes land on the latest release. We do not backport to older release lines.