- OQ-08: shell convention = assembly-supplied serve config (shell argv for shell_request; exec wrapper argv + command string for exec; no crate default; unset -> clean decline) - OQ-11: direct-streamlocal = universal compile + runtime Unix-gated decline (channel and listen flow) - OQ-10: closed as contract + upstream constraint; derivation rules formalized in mapping.md (Exit chunk -> SSH exit reporting), incl. the -1/genuine-SIGHUP fidelity tradeoff and an unmapped-negative fallback rule - OQ-01/04/09/13: resolved as fully-decided dispositions (ADR-001/ ADR-004/fixed decline postures); remainders were forecasts about consumers, not pending alkssh decisions; upstream deps now listed as watch items, not OQs - OQ-12 restored to the tracker (dropped in the rewrite) - review-agent criticals/warnings fixed: exec-unset + wrap mechanics specified, streamlocal listen gate added, stale deferred/tracked language removed, ADR-006 title fixed, 0.64.1-vs-0.65.0 crosswalk added in ADR-004, ADR frontmatter aligned to 'reviewed' All specs + ADRs 001-006 now reviewed; implementation may begin.
6.2 KiB
status, last_updated
| status | last_updated |
|---|---|
| reviewed | 2026-10-28 |
ADR-002: The russh pin — 0.65.0, aws-lc-rs, no compression, ed25519-only
Status
Accepted — 2026-10-26. A one-way door in practice (SSH negotiation
behavior crosses crate boundaries; bumps are deliberate, tested, and
recorded per the repo's wire-stability convention). Amended same day
after review: the earlier enabling of the rsa feature is reverted
(rsa off). Amended 2026-10-27 (review pass): the key-algorithm
position is ed25519-only — the family's posture is the binding
constraint, not fleet compatibility (decision 4).
Context
russh.md documents the crate inventory and the pin questions; the
2026-10-26 re-verification section carries the current facts. The POCs
validated against 0.64.1 (then-newest) with the ring backend; since
then 0.65.0 has been published (2026-10-25) with six security
fixes — three in classes an internet-facing SSH door cares about
(client EXT_INFO unbounded allocation, peer zero-max-packet-size
channel stall, pre-auth nested-certificate stack exhaustion) — and two
breaking changes confined to handler-signature shapes
(PublicKeyOffer / VerifiedPublicKey; async-trait feature
removed).
The family's crypto-posture context: alktls, alkhttp, and
alknet all standardize on rustls with the aws_lc_rs feature;
no family crate links ring. The provider choice matters only as
binary-composition hygiene — when alkforge's binary links alkssh
and the family's rustls stack, one shared primitive library is the
goal — and has nothing to do with TLS on the SSH wire.
Decision
- Pin
russh = "0.65"(caret-compatible within 0.65.x, matching the family's"0.10"-style convention; russh minors have broken API before, so the caret stops at the minor). 0.65.0 over 0.64.1: current published + the three security fixes above; the breaking changes land inside the handler surface alkssh implements anyway. POC evidence transfers (wire behavior unchanged); the implementation phase re-verifies the POC-1 decline matrix against 0.65 as contract tests. - Crypto backend:
aws-lc-rs. Family-confirmed (alktls/alkhttp/alknetallrustls(aws_lc_rs); nothing in-family linksring) and it is russh's own default. Verified in-scratch: builds clean in ~50 s with no external provisioning (prebuilt bindings), treeaws-lc-rs 1.18.2/aws-lc-sys 0.46.0. The POCs'ringbuild is recorded as the fallback if a target platform ever fails to provision aws-lc — a deliberate, recorded deviation, never drift. flate2off — no compression. The POCs already ran compression-free and vanilla OpenSSH was untroubled; SSH compression is largely pointless at modern link layers and is the CRIME-adjacent attack surface OpenSSH itself defaults off. Bounded-resources and surface-reduction posture agree.- ed25519-only —
rsaoff, and no other scheme is supported. Amended 2026-10-27 from the earlier "ed25519-first" wording after review: the position is ed25519-only. One key algorithm carries the family's identity: the same ed25519 keys serve alktls's self-signed TLS certificates and iroh, and the downstream alknet rewrite rides ssh + ed25519, tcp + tls, quic + tls, and iroh — the same ed25519 identity. The legacy/alternative SSH key schemes (rsa, dsa; ecdsa variants and hardware-token sk variants share the defect) are issued, stored, or derived nowhere in the family — supporting them here would be a wart backed by nothing else. Enablingrsawould additionally have pulled two RC-pinned deps and made alkssh the family's only RSA-holding crate. Concretely: the tree dropsrsa =0.10.0-rc.18andpkcs1 =0.8.0-rc.4entirely (verified: the["aws-lc-rs"]-only build is clean and RC-free exceptssh-key =0.7.0-rc.11, which russh exact-pins on therussh::keyspath). Wire behavior is honest and fail-closed: a client presenting a non-ed25519 key gets a cleanUSERAUTH_FAILURE— never a half-open session. Operational shape: alkssh implements no other scheme; an assembly registers ed25519 fingerprints only; andauth_publickeydeclines non-ed25519 keys explicitly (ADR-004's explicit-over-inherited pattern applied to the algorithm position, so the posture survives a pin bump that might otherwise accept more schemes). If a scheme ever matters, the amendment is one feature flag plus this ADR. des/dsanever. russh's own "Danger: insecure" features — no alkssh configuration may enable them.- Manifest lands with the dependency:
rust-version = "1.89"(russh's MSRV; supersedes the current 1.88) and, with it, the edition-2024 bump the POCs compiled under.
Consequences
- Positive: the pin is current, carries the security fixes, and
matches the family crypto posture; the tree is fully inventoried —
with
rsaoff it is RC-free exceptssh-key =0.7.0-rc.11(unavoidable: russh exact-pins it on therussh::keyspath); MSRV/licensing are explicit. - Negative: clients presenting non-ed25519 keys (RSA among them)
decline outright (clean
USERAUTH_FAILURE) — recorded as intentional;ssh-key's RC pin rides the russh keys path until russh moves off it; aws-lc-rs is the heavier build (proven acceptable here, withringas the recorded fallback). - Neutral: at 0.65.0 the key arrives as
VerifiedPublicKey.public_keywith the client's signature.algorithmexposed; the ed25519-only posture (decision 4) acts on the key-algorithm fact atauth_publickey, and the.algorithmfield remains available for further hardening if ever wanted. ADR-004 carries the matching amendment note; its other dispositions are unchanged.
References
docs/research/russh.md(inventory + the 2026-10-26 re-verification section with the scratch-build record)docs/research/poc-1-auth-bridge.md(the 0.64.1 wire evidence; backend note),docs/research/poc-2-vault-keys.md,docs/research/poc-3-mapping-bakeoff.md(0.64.1 runtime facts)- ADR-001 (the pin context), ADR-003 (feature graph the russh features compose under), ADR-004 (auth dispositions on this surface)
- Family:
alktls/alkhttp/alknetmanifests (the aws-lc-rs posture), family ADR-002 decision 5