|
ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
|
Which protocol features are exercised against something other than ourselves, and by what.
A round-trip through our own codec proves self-consistency, not conformance. This matrix tracks the ways a feature is judged by something other than itself:
test/servers/peers/, driven by test/servers/interop.py), so the wire format is validated by something that did not read our source. This is the strongest evidence a wire format is right, and the reason the matrix exists./bench CCOUNT harness).pentesting/pc_pentest.py), with the determinism and liveness oracles.native_pentest env, run separately from the main suite because it is heavy.Attack and fuzz are not interchangeable: one proves the device survives a knowledgeable opponent on the wire, the other proves the parsers survive malformed input at all. A feature is fully covered when it has all four.
Rows without a peer are not untested - they have host tests with pinned spec vectors. They are untested by a third party, which is precisely the gap this tracks.
Related: AUDIT.md records the per-standard conformance verdicts this evidence backs; STANDARDS.md maps each feature to its authoritative spec.
| Dimension | Count | Source of truth |
|---|---|---|
| Interop peers | 39 | test/servers/peers/*_peer.py |
| Throughput benches | 207 | performance_benching/**/platformio.ini |
| Advanced attacks | 79 | @attack(...) in pentesting/pc_pentest.py |
| Adversarial fuzz | 78 | native_pentest (test/test_pentest/) |
| Service modules | 197 | src/services/<group>/<module>/ |
Interop peers cover 39 of 197 service modules. Not every module needs a third-party peer - many are pure codecs with pinned spec vectors, and some need hardware the project does not have - but the ratio is the honest measure of how much is judged by something other than ourselves.
Peers: amqp, coap, dns, euromap77, fanuc_j519, focas, ftp, graphql, grpcweb, h2, h3, http, jwt, modbus, mqtt, mtconnect, nats, ntp, opcua, openadr, redis, robotics, sep2, simatic, smb, smtp, snmp, sparkplug, sse, ssh, statsd, stomp, sunspec, syslog, tls, wamp, webdav, ws, xmpp
OK covered · ~ partial/basic · - gap · n/a no external peer (device-internal or sensor)
| Protocol / feature | Interop | Bench | Adv. attack | Next / notes |
|---|---|---|---|---|
| HTTP/1.1 | OK | OK | OK | desync matrix, chunk abuse, obs-fold, CRLF, oversized, slowloris |
| WebSocket | OK | OK | OK | RFC 6455 peer; permessage-deflate host+device bench (inflate 196us); frame-abuse + ping-flood + deflate-bomb (1014x defused) - all held |
| Server-Sent Events | OK | OK | OK | WHATWG EventSource peer; pc_sse_format host+device bench; exhaustion+churn attacks (found+fixed a real DoS: SSE slot leak) |
| HTTP/2 | OK | OK | OK | DONE (device-as-server on PSRAM). Interop http2 peer 7/7 via httpx/h2 (ALPN h2, HEADERS/DATA+HPACK, multiplexed streams). Bench: cold ~452 ms, warm ~51 ms/req (19.5/s), ~1-2 concurrent streams (FEATURE_PERFORMANCE.md). Attack pc_h2_abuse HELD (rapid-reset CVE-2023-44487 + CONTINUATION-flood/HPACK-bomb/PING-flood, 0 findings). Bring-up fixed a core-locking tcp_write HW bug (BUGS.md). Pools in PSRAM (s_h2@0x3c0e0000 + s_pool@0x3c0fcf30, DRAM 18%) |
| HTTP/3 / QUIC | OK | OK | OK | DONE end-to-end on the PSRAM board (Ed25519 cert + pc_h3_cert() + begin, s_qpool@0x3c0e0000, UDP:443). Interop http3 peer 5/5 via aioquic (QUIC handshake X25519+Ed25519+AES-128-GCM, GET / -> 200 over QPACK+DATA, multiplexed 2nd stream). Bench cold ~940 ms, ~2 req/conn. Attack pc_quic_abuse HELD (raw-UDP: Initial-flood 300, malformed long/short-header fuzz, anti-amplification/reflection 0.00x - the server never answers a forged Initial; 0 findings). Bring-up fixed two HW bugs (Ed25519 stack v5.95.11, frame parser v5.95.12, BUGS.md) |
| TLS | OK | OK | OK | device-as-server on a slim HTTP+TLS rig (DRAM, 48 KB static arena, no PSRAM/no malloc). tls_peer 7/7 (TLS 1.2 ECDHE-ECDSA-AES256-GCM-SHA384, cert CN esp32-pc, GET-over-TLS 200); tls_server_abuse held (downgrade refused, weak/NULL/EXPORT/RC4 refused, 7 malformed handshakes survived); handshake ~913 ms median. Found+fixed 2 HW bugs: tcpip_thread self-deadlock on close_notify, and RX ring < 1.5 KB ClientHello. tls_session_abuse HELD (session/record layer: resumption OFF - full handshakes only, so no ticket-replay surface; malformed/duplicate ALPN offer handled without a crash; 24 half-open handshakes survived; engine recovers). 0-RTT n/a (device is TLS 1.2, not 1.3) |
| Basic/Digest auth | n/a | OK | OK | auth_bypass (null-trunc fixed) + **digest_nonce_replay** (RFC 7616 SHA-256): forged nonce (bad MAC), tampered response digest, and wrong password all rejected (3/3 held on HW); the stateless keyed-MAC nonce lets an identical captured response replay within the ~5 min lifetime - reported INFO (CWE-294, bounded tradeoff, keep the lifetime short + use TLS). Targets /secure-digest on the rig; sets alive_override (invalid attempts perturb the throttle) |
| JWT (HS256 bearer) | OK | OK | OK | real PyJWT peer (6/6 HW: valid accepted, wrong-secret rejected, expired rejected by exp) via rig /jwt/verify (Authorization: Bearer, not query - MAX_QUERY_LEN truncates); pc_jwt_verify_hs256 host+device bench (141us, HMAC-SHA256, heaviest auth op); pc_jwt_forgery (14/14 forgeries rejected: alg=none/HS384/RS256/None-confusion, wrong-secret, sig strip/bitflip/truncate, extra dots, oversized) - a positive alg-confusion-immunity proof |
| CoAP | OK | OK | OK | aiocoap peer (3/3 HW on rig); pc_coap_server_process host+device bench; 3 advanced attacks (option-abuse, block bomb, observe flood) + fuzz - all held |
| MQTT | OK | OK | OK | broker peer; mqtt codec host+device bench; mqtt_malicious_broker attack (8/8 HW: bad CONNACK, topic-len lie, remlen 268MB, 5-byte remlen, truncated, giant topic - all held) via the rig /mqtt/probe device-as-client trigger |
| Modbus | OK | OK | OK | pymodbus peer (6/6 HW on rig); pc_modbus_process_adu host+device bench; 2 advanced attacks (illegal-requests -> 6/6 proper exceptions, MBAP abuse) + fuzz - all held |
| SNMP | OK | OK | OK | net-snmp peer (3/3 HW on rig); pc_snmp_agent_process host+device bench; 3 advanced attacks (GETBULK amplification x9.7 bounded, BER abuse, varbind flood) + fuzz - all held |
| OPC-UA | OK | OK | OK | asyncua peer (2/2 HW on rig: connect/session/browse); handshake+DataValue host bench + device op; 3 advanced attacks (HELLO buffer abuse->8192 bounded, UACP abuse, chunk flood) + fuzz - all held |
| SMB2 client | OK | OK | OK | ALL THREE DONE (2026-07-11). Slim rig_s3_smb env + main_smb.cpp /smb/probe device-as-SMB2-client endpoint (NEGOTIATE -> NTLMv2 SESSION_SETUP -> TREE_CONNECT -> CREATE -> READ -> CLOSE via pc_client_*, DRAM 26.8%). Interop smb_peer.py 7/7 HW vs real samba (dperson/samba :4445): the device read content FNV-1a matches an independent smbclient read exactly. Attack pc_smb2_malicious_server 10/10 HELD (fake server: 16 MB / 4 GB / zero direct-TCP frame, truncated + slow-drip, bad ProtocolId, < 64 B header, NT-status error, OOB SecurityBuffer, accept-then-close) - the de-framer + NEGOTIATE parser survived, heap stable, 0 findings (auto-selected via --diag: /diag now advertises the protocol flags) |
| SSH | OK | OK | OK | All three DONE (2026-07-11). Interop: ssh peer 6/6 vs the reference OpenSSH client (curve25519-sha256 KEX, ssh-ed25519 host key, chacha20-poly1305, NEWKEYS, RFC 4252 password auth, RFC 4254 channel echo; aes256-ctr E&M + ETM also verified). Bench: performance_benching/bench_ssh.cpp host + S3 CCOUNT (FEATURE_PERFORMANCE.md) - X25519 ~150.8 ms, ed25519_sign ~547.9 ms, chacha 1 KB 705 us / 1.5 MB/s; handshake ~0.85 s of crypto (software field arithmetic). Attacks: 5 stdlib-only raw-socket SSH-2 attacks (ssh_banner_abuse, ssh_kexinit_abuse, ssh_packet_abuse, ssh_kexdh_abuse, ssh_msgtype_abuse) covering the whole pre-encryption handshake (banner/version, KEXINIT limits + no-mutual-alg + length-lie, packet-length/padding underflow, wrong-length Q_C, out-of-order message types) with an SSH-native liveness oracle - all HELD. **ssh_msgtype_abuse FOUND + FIXED a real bug (BUGS.md):** SERVICE_REQUEST had no phase guard, so a client could jump DH_INIT -> AUTH in cleartext, skipping KEX; guarded to SSH_PHASE_SERVICE + regression test. Two HW bugs total found on SSH bring-up (emit-wiring v5.95.13 + this). Rig rig_s3_ssh |
| FTP client | OK | OK | OK | pyftpdlib peer (11/11 HW: USER/PASS/TYPE/PASV/STOR + SIZE, upload verified server-side) via rig /ftp/probe device-as-client; pc_ftp_parse_reply host+device bench; pc_ftp_malicious_server (9 personalities: oversized/unterminated reply, infinite multiline, malformed 227, PASV bounce, code confusion - all held) |
| WebDAV | OK | OK | OK | stdlib RFC 4918 client peer (17/17 HW); ms_entry host+device bench; 5 attacks (Depth:inf, XXE, traversal, PROPPATCH bomb, LOCK flood) |
| Redis (RESP) | OK | OK | OK | redis_peer device-as-client vs a real redis-server (6/6 HW: PING/SET/GET + the SET verified server-side) via rig /redis/probe; RESP codec host+device bench; redis_resp_fuzz (10/11 malformed replies bounded) |
| NATS | OK | OK | OK | stdlib client peer vs a real nats-server (7/7 HW: INFO/CONNECT/SUB/PUB + the PUB delivered to an independent subscriber through the broker) via rig /nats/probe device-as-client; pc_nats_build_pub + pc_nats_parse host+device bench (6.55us); pc_nats_malicious_server (10 personalities: unterminated INFO, MSG len-lie, truncated, bad tokens, neg size, over-buffer line, -ERR flood, unknown verb, no-CRLF, mid-close) - held |
| STOMP | OK | OK | OK | stdlib spec STOMP 1.2 broker peer (7/7 HW: CONNECT/SUBSCRIBE/SEND + the SEND captured server-side) via rig /stomp/probe device-as-client; pc_stomp_build_frame + pc_stomp_parse_frame host+device bench (9.64us); pc_stomp_malicious_broker (10 personalities: content-length lie/overflow/nondigit/mismatch, header flood, no-colon, over-buffer frame, no-NUL body, unterminated CONNECTED, heartbeat flood) - held |
| StatsD | OK | OK | OK | stdlib UDP collector peer (5/5 HW: name:value | type validated) via rig /statsd/probe device-as-client; pc_statsd_format host+device bench (4.38us); pc_statsd_injection (newline metric-forging, :/| confusion, control bytes, 2KB oversized -> bounded 51B) - held; newline forging noted INFO (CWE-117, StatsD packs
-separated metrics) | | XMPP | OK | - | - | Interop DONE (2026-07-12, device-as-client). xmpp peer 11/11 HW: the rig GET /xmpp/probe dials a self-contained RFC 6120 c2s server and runs the full client dialogue with the xmpp.h stanza codec - stream open (‘version='1.0’,to=domain), SASL PLAIN<auth>(the server b64-decodes + verifies the credentials), stream restart, resource-bind<iq>(the server replies the full JID),<presence>, and a<message><body>the server captures + validates. Independent-impl proof of the stream/message/presence/iq builders. (prosody / ejabberd are the production references.) Bench + attack next. | | AMQP | OK | - | - | **Interop DONE (2026-07-12, device-as-client).**amqppeer **12/12 HW**: the rigGET /amqp/probedials a self-contained AMQP 0-9-1 broker and runs the full client dialogue with the amqp.h frame/method codec - protocol header, Connection.Start-Ok (SASL PLAIN, the broker decodes + verifies the credentials), Tune-Ok, Connection.Open, Channel.Open, and a Basic.Publish + content-header + body the broker captures + validates (routing key pc.q). Independent-impl proof of the frame builder + method encoder/parser; the method-arg encoders live in the rig (per amqp.h). (RabbitMQ is the production reference.) Bench + attack next. | | WAMP | OK | - | - | **Interop DONE (2026-07-12, device-as-client over WebSocket).**wamppeer **12/12 HW**: the rigGET /wamp/probedoes a WS client handshake offering thewamp.2.jsonsubprotocol (needed a small library feature - asubprotocolarg onws_client_build_handshake, v-bump, native-tested), then runs the WAMP client dialogue with the wamp.h codec against a stdlib WAMP-over-WebSocket router - HELLO/WELCOME, SUBSCRIBE/SUBSCRIBED, PUBLISH (acknowledge+exclude_me=false)/PUBLISHED + the routed EVENT, CALL/RESULT. Independent-impl proof of the client builders + the router-reply parser over a real WebSocket. (crossbar / autobahn are the production references.) Bench + attack next. | | DDS | - | - | - | RTPS; a real DDS peer (CycloneDDS) | | DNP3 / IEC-60870 / MMS+GOOSE / S7comm | - | ~ | - | industrial SCADA - **all implemented codecs** (src/services + native tests), NOT roadmap. **DNP3 bench DONE host+device** (performance_benching/bench_dnp3.cppcrc16 215 ns / build/parse ~550 ns host; rig/benchpc_dnp3_parse_frame**~15.6 us / 3753 cyc device** - the table-less CRC dominates). **DNP3 attack DONE:**pc_dnp3_frame_fuzzHELD (rig/dnp3/parseendpoint; 12 malformed frames - bad start word, LEN under/over-run, header + block CRC corruption, truncated header/block, all-0xFF, 2 KB blob - all rejected, a valid frame still accepted, deterministic). So DNP3 is **bench OK + attack OK**; interop needs the DNP3 **application layer** (function codes/objects) built on the data-link codec to exchange with opendnp3/lib60870/etc - feature work, not just wiring. **S7comm bench DONE host+device** (performance_benching/bench_s7comm.cpp+ rig/benchpc_s7_parse_header**~0.54 us / 129 cyc**) **+ attack DONE** (s7comm_frame_fuzzHELD: 11 malformed PDUs - bad proto-id/ROSCTR, length lies, truncation - rejected, valid parses; deterministic warm). DNP3+BACnet+S7comm+IEC-60870 now all bench+attack. **IEC-60870-5-104 bench DONE host+device** (performance_benching/bench_iec60870.cpp: build_i 8.3 ns / parse 5.8 ns / asdu_parse_header 5.0 ns host; rig/benchpc_iec104_parse**~0.47 us / 112 cyc device**) **+ attack DONE** (pc_iec104_frame_fuzzHELD on HW via rig/iec104/parse: 14/15 malformed APDUs - bad start octet, length under/over-run, truncated APCI, degenerate I/S/U control, short chained ASDU, all-0xFF - rejected/sliced without over-read, valid I-frame still parses; 15th oversized blob refused by the 256 B body cap; heap flat after warmup). **MMS (IEC 61850) host bench added** (performance_benching/bench_mms.cpp: read_request build 101 ns / read_response build 53 ns / parse 8.5 ns - the nested-BER ObjectName encode dominates the request; parse is a trivial TLV walk). **GOOSE (IEC 61850) host bench added** (performance_benching/bench_goose.cpp: goose_pdu build 131 ns / goose_frame build 135 ns) - GOOSE is publish-only (no parser -> NO fuzz-attack surface, bench-only like NTS; interop needs raw-L2 multicast + an Ethernet PHY). **EtherNet/IP host bench added** (performance_benching/bench_enip.cpp: pc_eip_build 7.5 ns / pc_eip_parse 4.9 ns / register_session 2.9 ns - fixed 24-octet encapsulation header, fast fixed-field class; has a real parser so device bench + enip_frame_fuzz are the next increments). **PROFINET DCP host bench added** (performance_benching/bench_profinet.cpp: dcp_header 4.9 ns / parse_header 4.0 ns / dcp_walk 7.5 ns - fixed 10-octet header + TLV blocks; dcp_walk is the fuzz target, device bench + profinet_dcp_fuzz next; interop needs raw-L2 + a PHY). Same shape for the rest of the family (codec + parser-fuzz coverable now; full interop needs the app/role layer) | | EtherNet/IP / Profinet / Profibus / CANopen / DeviceNet / CC-Link / Sercos / Powerlink / Interbus / FINS / Melsec | - | ~(some) | - | industrial fieldbus family; large interop gap | | BACnet | - | - | - | building automation (ASHRAE 135, BVLC+NPDU codec). **Bench DONE host+device** (performance_benching/bench_bacnet.cpp+ rig/benchbacnet_npdu_parse**~0.42 us / 101 cyc** - no CRC, ~37x lighter than DNP3). **Attack DONE:**bacnet_frame_fuzzHELD (rig/bacnet/parse; 12 malformed BVLC/NPDU datagrams - bad type/version, length lies, DLEN/SLEN over-runs, truncation - all rejected, a valid one still parses; deterministic warm). BACnet is bench OK + attack OK; interop needs the APDU/application layer (bacnet-stack peer) | | Sparkplug B | OK | - | - | **Interop DONE (2026-07-12, device-as-client over a real MQTT broker).**sparkplugpeer **9/9 HW**: starts mosquitto, subscribesspBv1.0/#, triggers the rigGET /sparkplug/probe(the device dials the broker and publishes an NBIRTH tospBv1.0/pc/NBIRTH/rig, built by the sparkplug + protobuf codecs), and decodes the TahuPayloadprotobuf with an INDEPENDENT stdlib decoder - asserting the topic + the metric names/datatypes/values (float 23.5, uint32, string). A genuine broker hop (mosquitto logspc-rig-spbconnecting + publishing). Bench + attack next. | | SunSpec | OK | - | - | **Interop DONE (2026-07-12, device-as-server over Modbus TCP).**sunspecpeer **6/6 HW**: the rig seeds a SunSpec device-information map (SunS marker + Common model ID 1, 66-reg body + end model) into its Modbus holding registers at base 100 (clear of the plain-Modbus interop's low regs, PC_MODBUS_HOLDING_REGS=192), and **pysunspec2** (the reference SunSpec Alliance client) scans the model chain over Modbus TCP and reads the Common model - asserting Mn/Md/SN/Vr. Validates the SunSpec codec + register layout against the reference client, reusing the Modbus slave. Bench + attack next. | | SEP2 (IEEE 2030.5) | OK | - | - | **Interop DONE (2026-07-12, device-as-server).**sep2peer **18/18 HW**: the rig serves the sep2.h resource documents asapplication/sep+xml- DeviceCapability at /dcap, EndDevice at /edev, DERControl at /derc. An independent spec consumer (stdlib XML) walks DeviceCapability -> the linked resources and validates theurn:ieee:std:2030.5:nsnamespace, the resource vocabulary, the href graph (EndDeviceListLink resolves), and the values (sFDI/lFDI, the DER interval, opModFixedW=-1500 W). Served over plain HTTP; production 2030.5 mandates TLS + client certs (the official sep.xsd / certified 2030.5 clients are the references). Bench + attack next. | | OpenADR 3.0 | OK | - | - | **Interop DONE (2026-07-12, device-as-server / VEN).**openadrpeer **17/17 HW**: the rig serves the openadr.h JSON objects over HTTP - an EVENT at /openadr/event (programID + eventName + an intervals array of typed payload points) and a REPORT at /openadr/report (a resource READING answering an event). An independent OpenADR 3.0 consumer (stdlib json) validates the 3.0 object model - objectType, programID, the intervals/interval/payloads/values nesting, the resources array - and the numeric values. Served over plain HTTP; production 3.0 rides HTTPS + OAuth2 (the OpenADR 3.0 OpenAPI / openleadr are the references). Bench + attack next. | | GraphQL | OK | - | - | **Interop DONE (2026-07-12, device-as-server).**graphqlpeer **10/10 HW** on the full rigPOST /graphql(pc_graphql_execute+ a device resolver): the reference **graphql-core** parses/validates each query and derives the requested field shape, and the device's{"data":...}response mirrors it exactly (the subset property:{ device { name } }returns onlyname), resolves live scalars (uptime/heap), flows an argument to the leaf (sensor(id: 7) { value }-> 71), handles a named operation, and fails closed on a malformed query (errors + 400). Bench + attack (query-complexity bomb) next. | | gRPC-web | - | - | - | web-API; grpcurl / a gRPC-web client (HTTP/1.1 length-prefixed frames + protobuf body) | | SMTP client | OK | OK | OK | aiosmtpd peer (6/6 HW: EHLO/MAIL/RCPT/DATA + message verified server-side) via rig /smtp/probe device-as-client; smtp_run full-dialogue host+device bench (56.5us); smtp_malicious_server (10 personalities: oversized/unterminated greeting, multiline flood, huge continuation, wrong codes per stage, mid-dialog close - all held) | | syslog | OK | OK | OK | stdlib UDP collector peer (7/7 HW: PRI/VERSION/HOSTNAME/APP-NAME/MSG validated as RFC 5424) via rig /syslog/probe device-as-client; pc_syslog_format host+device bench (15.4us); pc_syslog_injection (CRLF/LF forging, NUL truncate, control bytes, 2KB oversized -> bounded 80B) - held; CR/LF passthrough noted INFO (CWE-117, spec-permitted over UDP) | | NTP server | OK | OK | OK | real ntplib client peer (6/6 HW: mode-4, origin echo, stratum 2, LOCL ref-id, plausible epoch) on UDP/123; pc_ntp_server_build_response host+device bench (1.37us); pc_ntp_server_abuse (amplification matrix -> max 1.00x = NOT a reflector, 64/64 mode/version combos, malformed/oversized) - held. Rig seeds a synthetic time source. NTP _client_ = esp-idf SNTP wrapper (no library codec). **NTS (RFC 8915) framing bench added, host + device** (performance_benching/bench_nts.cpp+ rig/benchnts_ke_parse: host ke_parse 18.9 ns, **device ~1.1 us / 270 cyc**). NTS is **codec-only** (record/EF build + parse helpers; no running NTS-KE endpoint - zero callers outsideservices/timing_position/nts/, not in the session dispatcher), so interop + attack are **n/a** like the other pure codecs; parser robustness against truncated/malformed records is covered bynative_nts. **NTS coverage COMPLETE for what applies.** | | DNS server | OK | OK | OK | real dnspython client peer (11/11 HW: 3 A records + AA flag + NXDOMAIN) on UDP/53; pc_dns_server_build_response host+device bench (1.75us); pc_dns_server_abuse (open-resolver check -> False, amplification matrix -> max 1.64x, compression-pointer loop + 14 malformed/opcode cases) - held. Authoritative-only, NOT an open reflector | | mDNS | n/a | n/a | n/a | **esp-idf wrapper, not a library wire codec.**mdns_service.cppis a thin shim over the ESP-IDFmdnscomponent (mdns_init/mdns_hostname_set/mdns_service_add) - the multicast responder + wire protocol are esp-idf's, so interop/attack/bench of the wire would test esp-idf, not this library (same status as the NTP _client_ = esp-idf SNTP wrapper). The library's OWN mDNS code is the adaptive-beacon backoff (mdns_adaptive: contention-driven interval doubling/halving), a control-plane timing calc (not a per-packet hot op) covered bynative_mdns_adaptive`. Covered for what applies. | | MTConnect | OK | OK | OK | stdlib probe/current/sample peer (9/9 HW on rig); streams-doc bench; mtconnect_param_abuse (from/count max-u64/u32, malformed, oversized -> bounded 793B, held) | | Zigbee / Z-Wave / LoRa / Sigfox / Wi-SUN / Thread / ESP-NOW | - | - | - | RF; needs radios (HW plan) - interop is device-to-device |
pc_sse_format host+device bench, exhaustion+churn attacks. The exhaustion attack found a real permanent-DoS bug (SSE pc_sse_pool slot leak wedging the whole server), root-caused over JTAG and fixed (http_release_upgrade_bindings); see docs/BUGS.md. 1b. pc_webdav_ms_entry host+device bench, 5 advanced attacks (Depth:infinity amplification, XXE + billion-laughs, Destination/URI traversal, PROPPATCH bomb, LOCK flood) - all held on the rig (WEBDAV+LittleFS enabled on the rig firmware). Audited clean. 1c. redis-server (6/6 HW, SET verified server-side), RESP host+device bench, redis_resp_fuzz. 1d. pyftpdlib server (11/11 HW, USER/PASS/TYPE/PASV/STOR + SIZE, upload verified server-side), pc_ftp_parse_reply host+device bench, pc_ftp_malicious_server (9 personalities: oversized/unterminated reply, infinite multiline, malformed 227, PASV bounce, reply-code confusion) - all held. Rig RAM 56.5% (FTP codec is tiny). 1e. aiosmtpd server (6/6 HW, EHLO/MAIL/RCPT/DATA, the alert email verified server-side), smtp_run full-dialogue host+device bench (56.5us), smtp_malicious_server (10 personalities: oversized/unterminated greeting, multiline flood, huge continuation, wrong codes at each stage, mid-dialog close) - all held. 1f. pc_syslog_format host+device bench (15.4us), pc_syslog_injection (CRLF/LF log-forging, NUL truncate, control bytes, 2 KB oversized -> bounded)ntplib client (6/6 HW: mode-4, origin echo, stratum, LOCL, plausible epoch), pc_ntp_server_build_response host+device bench (1.37us), pc_ntp_server_abuse (amplification matrix -> max 1.00x = NOT a reflector, 64/64 mode/version combos, malformed/oversized) - held. Rig seeds a synthetic time source; needed -DPC_MAX_UDP_LISTENERS=4 (the default 2 was full with CoAP + SNMP). 1h. dnspython client (11/11 HW: 3 A records + AA + NXDOMAIN), pc_dns_server_build_response host+device bench (1.75us), pc_dns_server_abuse (open-resolver=False, amplification max 1.64x, compression-pointer loop + 14 malformed/opcode cases) - held. Authoritative-only + rejects question compression pointers = no reflector, no pointer-loop DoS. Bumped -DPC_MAX_UDP_LISTENERS=6 (CoAP+SNMP+NTP+DNS). 1i. nats-server (7/7 HW: INFO/CONNECT/SUB/PUB + the PUB delivered to an independent subscriber through the broker), pc_nats_build_pub/pc_nats_parse host+device bench (6.55us), pc_nats_malicious_server (10 malformed INFO/MSG personalities) - held. First of the AMQP/STOMP/NATS/WAMP/XMPP messaging family. nats-server on the RPi at 0.0.0.0:4222 (stop the systemd unit that binds 127.0.0.1 first). 1j. pc_stomp_build_frame/ pc_stomp_parse_frame host+device bench (9.64us), pc_stomp_malicious_broker (10 malformed-frame personalities: content-length lie/overflow/mismatch, header flood, over-buffer, no-NUL, unterminated) - held. (coilmq is broken on Python 3.13 - removed pkg_resources - so the peer runs an in-thread stdlib broker.) 1k. pc_statsd_format host+device bench (4.38us), pc_statsd_injection (newline metric-forging, :/| confusion, 2 KB oversized -> bounded 51B) - held. Newline forging is INFO (CWE-117; StatsD packs \n-separated metrics, so a compliant collector forges - caller sanitizes the name). 1l. PyJWT client (6/6 HW: valid accepted, wrong-secret rejected, expired rejected by exp), pc_jwt_verify_hs256 host+device bench (141us), pc_jwt_forgery (14/14 forgeries rejected: alg=none, alg-confusion, wrong-secret, sig strip/bitflip/truncate, oversized) - a positive alg-confusion-immunity proof. The token rides the Authorization: Bearer header (the query is capped by MAX_QUERY_LEN).rig_s3_psram env (board_build with PSRAM + the PC_ENABLE_TLS/HTTP2/HTTP3 flags) - this is the highest-value remaining work.xmpp, prosody)~~ device-as-client /xmpp/probe vs a stdlib RFC 6120 c2s server (11/11 HW: stream + SASL PLAIN + bind + message); ~~AMQP (amqp, RabbitMQ)~~ /amqp/probe vs a stdlib AMQP 0-9-1 broker (12/12 HW: header + Start-Ok SASL PLAIN + Tune-Ok + Open + Channel.Open + Basic.Publish); ~~WAMP (wamp, crossbar)~~ /wamp/probe vs a stdlib WAMP-over-WebSocket router (12/12 HW: WS handshake w/ wamp.2.json subprotocol + HELLO/SUBSCRIBE/PUBLISH/CALL round trips; added a subprotocol arg to ws_client_build_handshake). Next for all three: bench + attack.test/servers/peers/, a KEX/cipher throughput bench, and advanced SSH attacks - no longer a bring-up blocker./bench endpoint.test/servers/peers/<proto>_peer.py (NAME/HELP/add_args/run), register in interop.py _MODULES; see the existing peers for the shape.performance_benching/*.cpp (host ns/op); device µs/op -> add the op to the rig /bench endpoint (pentesting/rig_firmware) and read it over HTTP; record both in FEATURE_PERFORMANCE.md.@attack(...) to pentesting/pc_pentest.py gated on the feature flag; keep the determinism + liveness oracles and --authorized; live-fire against the rig.