Skip to content

feat(ssh): warn when SSH and rsync compression both enabled#3637

Merged
oferchen merged 3 commits into
masterfrom
feat/ssh-cipher-compression-warn-2046
May 5, 2026
Merged

feat(ssh): warn when SSH and rsync compression both enabled#3637
oferchen merged 3 commits into
masterfrom
feat/ssh-cipher-compression-warn-2046

Conversation

@oferchen
Copy link
Copy Markdown
Owner

@oferchen oferchen commented May 5, 2026

Summary

Detect when SSH built-in compression (-C / -o Compression=yes) and rsync --compress are both active and emit one stderr warning per process. Compressing twice wastes CPU and may expand already-compressed data.

Changes

  • SshCommand::has_ssh_compression() - new public inspector that scans the explicit SSH argv for compression flags. Detection is conservative; it does not parse ~/.ssh/config since that file is merged at spawn time and we cannot reliably read it.
  • arg_enables_ssh_compression() - private helper recognising:
    • bare -C
    • -oCompression=<truthy> (combined)
    • -o Compression=<truthy> (split across two argv entries)
    • case-insensitive key match (Compression/compression)
    • truthy values: yes, true, 1, all case-insensitive
  • build_ssh_connection (crates/core/src/client/remote/ssh_transfer.rs) checks config.compress() && ssh.has_ssh_compression() after building the SshCommand and before spawn, calling a new warn_double_compression_once helper.
  • warn_double_compression_once uses OnceLock<()> to emit at most one rsync warning: line per process, then proceeds unchanged. No auto-disable, no CLI flag.

Tests

Seven unit tests in crates/rsync_io/src/ssh/tests.rs:

  • has_ssh_compression_detects_dash_c
  • has_ssh_compression_detects_combined_option_yes
  • has_ssh_compression_detects_split_option_yes
  • has_ssh_compression_truthy_aliases (yes/YES/Yes/true/TRUE/1)
  • has_ssh_compression_case_insensitive_key
  • has_ssh_compression_rejects_falsey_and_unrelated (no/NO/false/0/off plus unrelated -o BatchMode=yes, -c aes128-gcm@openssh.com)
  • has_ssh_compression_default_is_false

Wire compatibility

No protocol or wire-format change. The warning is the only user-visible effect.

Compressing twice on the same byte stream wastes CPU and can expand
already-compressed data. Detect the case and emit one stderr warning
per process.

- New `SshCommand::has_ssh_compression()` inspects the explicit SSH
  argv for `-C` and case-insensitive `-o Compression={yes,true,1}`,
  in both combined `-oCompression=...` and split `-o Compression=...`
  forms.
- `build_ssh_connection` checks the rsync `--compress` setting against
  the SshCommand and emits one `rsync warning:` line via OnceLock-gated
  helper, then proceeds unchanged.
- Detection is conservative: it does not parse `~/.ssh/config`, since
  that file is merged at spawn time and we cannot reliably read it.

Upstream rsync does not detect this; this is a usability enhancement.
No CLI flag, no protocol behavior change, no auto-disable.
@github-actions github-actions Bot added the enhancement New feature or request label May 5, 2026
@oferchen oferchen merged commit 4d951fe into master May 5, 2026
39 checks passed
@oferchen oferchen deleted the feat/ssh-cipher-compression-warn-2046 branch May 5, 2026 09:41
oferchen added a commit that referenced this pull request May 5, 2026
…3697)

Re-checks the thirteen testable claims in
docs/audits/ssh-socketpair-vs-pipes.md against current
crates/rsync_io/src/ssh/ source. All claims confirmed; two file:LINE
citations drifted because of intervening commits (#3637 added the
SSH/rsync compression warning, growing builder.rs by ~60 lines).
Behaviour is unchanged: anonymous pipes on the wire, socketpair on
stderr, no socketpair anywhere on the SSH wire path. Reaffirms the
prior recommendation that #1687 (socketpair-prototype) stays closed.
oferchen added a commit that referenced this pull request May 18, 2026
Compressing twice on the same byte stream wastes CPU and can expand
already-compressed data. Detect the case and emit one stderr warning
per process.

- New `SshCommand::has_ssh_compression()` inspects the explicit SSH
  argv for `-C` and case-insensitive `-o Compression={yes,true,1}`,
  in both combined `-oCompression=...` and split `-o Compression=...`
  forms.
- `build_ssh_connection` checks the rsync `--compress` setting against
  the SshCommand and emits one `rsync warning:` line via OnceLock-gated
  helper, then proceeds unchanged.
- Detection is conservative: it does not parse `~/.ssh/config`, since
  that file is merged at spawn time and we cannot reliably read it.

Upstream rsync does not detect this; this is a usability enhancement.
No CLI flag, no protocol behavior change, no auto-disable.
oferchen added a commit that referenced this pull request May 18, 2026
…3697)

Re-checks the thirteen testable claims in
docs/audits/ssh-socketpair-vs-pipes.md against current
crates/rsync_io/src/ssh/ source. All claims confirmed; two file:LINE
citations drifted because of intervening commits (#3637 added the
SSH/rsync compression warning, growing builder.rs by ~60 lines).
Behaviour is unchanged: anonymous pipes on the wire, socketpair on
stderr, no socketpair anywhere on the SSH wire path. Reaffirms the
prior recommendation that #1687 (socketpair-prototype) stays closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant