M17.1: anvil_ssh::algorithms module — denylist + +/-/^ parser + catalogue#25
Merged
Merged
Conversation
… FR-78, FR-79 lib side)
Adds the library-side scaffold M17 needs to honour KexAlgorithms /
Ciphers / MACs / HostKeyAlgorithms from `~/.ssh/config` (FR-76),
parse OpenSSH-format CLI overrides (FR-77), enforce the permanent
denylist (FR-78), and surface the algorithm catalogue for
`gitway list-algorithms` (FR-79).
src/algorithms.rs (new, ~470 lines + ~250 lines of tests):
- pub const DENYLIST: &[&str] — DSA, 3DES, Arcfour variants,
hmac-sha1-96, ssh-1.0. Per FR-78 the list is permanent: an
override referencing any entry is rejected with a
tips-thinking hint pointing at `gitway list-algorithms` and an
external `ssh -W` workaround.
- pub fn is_denylisted(alg) / apply_denylist(list) — case-insensitive
ASCII matching helpers.
- pub enum AlgCategory { Kex, Cipher, Mac, HostKey } with .label().
- pub fn apply_overrides(category, base, override_str) — the
OpenSSH-format `+algo` (append) / `-algo` (remove) / `^algo`
(front-load) / `algo,algo` (replace) parser. Trims whitespace,
drops empty tokens, deduplicates appends case-insensitively,
preserves ordering on front-loads, silently skips removes for
absent entries (matches OpenSSH behaviour). Calls apply_denylist
after every transformation. Errors hard on a denylisted token
in any prefix form.
- pub fn anvil_default_kex / _ciphers / _macs / _host_keys — the
curated default lists used as the base for `+/-/^` overrides.
Kex matches what build_russh_config currently hardcodes;
ciphers/macs/host-keys are the safe set Gitway will negotiate
once M17.2 plumbs them through.
- pub struct AlgEntry { name, is_default, denylisted } and
pub struct Catalogue { kex, cipher, mac, host_key } with
pub fn all_supported() — enumerates every name russh advertises
(sourced from russh::{kex,cipher,mac}::* constants) and tags
each with the two flags.
src/lib.rs:
- pub mod algorithms;
Public API: pure additive. Version bump to 0.8.0 lands in M17.3.
23 unit tests covering: denylist case-insensitivity, Arcfour
variant matching, safe-algorithm pass-through, denylist-preserving
filter, all five prefix branches (none/+/-/^/empty), case-insensitive
dedup on append, silent skip on remove of absent, OpenSSH front-load
semantics (reorder-not-add), hard error on denylisted token in
override (in both replace and append forms), error hint mentioning
`gitway list-algorithms`, empty-token drop, whitespace trim,
catalogue completeness (≥1 default per category, denylisted entries
tagged, default+denylisted disjoint), curated-defaults exclude
denylist, host-key default excludes ssh-dss / includes ssh-ed25519,
category labels stable.
Plan: M17.1 of anvil-gitway-milestone-plan.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 4, 2026
UnbreakableMJ
added a commit
that referenced
this pull request
May 4, 2026
…errides) (#27) Final Anvil-side slice of M17. Bumps anvil-ssh from 0.7.0 to 0.8.0 to publish the M17.1 + M17.2 work as a single crates.io release. The Gitway-side CLI flags + list-algorithms subcommand (M17.4 + M17.5) land against this 0.8.0; the M17.X PRD doc PR closes the milestone with Gitway v1.0.0-rc.8. Cargo.toml: - version "0.7.0" -> "0.8.0" Cargo.lock: - regenerated locally; reflects the 0.8.0 version. CHANGELOG.md: - 0.8.0 entry covering the new anvil_ssh::algorithms module, the four new AnvilConfig fields + builder setters, the apply_ssh_config algorithm-directive consumption, the build_russh_config signature change, and the FR-66 / CAT_KEX tracing event for offered algorithm preferences. Stacked after PRs #25 (M17.1, merged) and #26 (M17.2, merged). Plan: M17.3 of anvil-gitway-milestone-plan.md. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First slice of M17 (PRD §5.8.6 — algorithm overrides). Adds the library-side scaffold needed for FR-76 / FR-77 / FR-78 / FR-79 — the M17.2 PR plumbs this into
AnvilConfig+build_russh_configand the M17.4 PR wires the Gitway CLI flags +list-algorithmssubcommand on top.New
anvil_ssh::algorithmsmoduleDENYLIST+is_denylisted/apply_denylist(FR-78) — permanent block on DSA, 3DES, Arcfour variants,hmac-sha1-96, SSH-1. Override mentions surface a hard error with atips-thinkinghint pointing atgitway list-algorithmsand an externalssh -Wworkaround.AlgCategory { Kex, Cipher, Mac, HostKey }with.label().apply_overrides(category, base, override_str)(FR-77) — OpenSSH+algo/-algo/^algo/algo,algoparser. Trims whitespace, dedupes appends case-insensitively, preserves order on front-loads (reorder-not-add semantics), denylist-filters after every transformation.anvil_default_kex/_ciphers/_macs/_host_keys— curated default base for+/-/^overrides.Catalogue { kex, cipher, mac, host_key }ofAlgEntry { name, is_default, denylisted }(FR-79) — sourced from russh's named constants forgitway list-algorithms.Tests (23 unit tests)
Denylist case-insensitivity, prefix-matrix coverage, dedup, silent-skip on absent removes, denylisted-token rejection, error-hint shape, whitespace trim, empty-token drop, catalogue invariants (≥1 default per category, default+denylisted disjoint, ssh-dss tagged), category-label stability.
Public API: pure additive. Version bump to 0.8.0 lands in M17.3.
Test plan
cargo fmt --all -- --checkcargo clippy --all-targets --all-features --locked -- -D warningscargo test --lib algorithms::— 23 passed, 0 failed🤖 Generated with Claude Code