Skip to content

SSH config writes are not idempotent, and tests write fixture hosts into the user's real ~/.ssh/config (164 duplicate blocks observed) #175

Description

@jeremymanning

Summary

clustrix appends entries to the user's real ~/.ssh/config without deduplicating, and it writes test-fixture hosts into that personal config. On my machine this accumulated to 164 identical placeholder blocks.

Evidence

Measured on a real user config (macOS, ~/.ssh/config):

total lines:        1202
total Host entries:  172

Frequency by host (real hostnames redacted):

164  Host my_cluster          <- test fixture, repeated 164x
  1  Host <gpu-host-alias>
  1  Host <slurm-host-alias>
  1  Host test_cli
  1  Host test_cleanup
  1  Host <slurm-host-alias-2>
  1  Host <slurm-host>
  1  Host <slurm-host-alias-3>
  1  Host <institution-domain>

Every duplicate block is byte-identical and self-labelled:

# Clustrix auto-generated entry for my_cluster
Host my_cluster
    HostName cluster.example.com
    User testuser
    IdentityFile ~/.ssh/id_ed25519_clustrix_testuser_my_cluster
    IdentitiesOnly yes

cluster.example.com / testuser is a test fixture, not a real host. After removing only the my_cluster blocks, the file went from 1202 lines / 172 Host entries to 52 lines / 8 Host entries, with every genuine entry preserved.

Two distinct bugs

  1. No deduplication on write. Each run appends a new block for a host that already has one. Nothing detects or replaces the existing entry, so the file grows without bound across runs.
  2. Tests write to the real user config. my_clustercluster.example.com / testuser is fixture data. A test suite should never mutate ~/.ssh/config; it should write to a temp file and point SSH at it via -F / ssh_config path injection.

Impact

  • The user's personal SSH config becomes unmanageable (1202 lines of which ~96% is generated noise).
  • Real entries get buried among fixtures, making the file hard to audit.
  • Functionally the duplicates are inert — OpenSSH takes the first match for a given Host pattern — so this is a hygiene and trust problem rather than a broken-connection problem. But it means clustrix silently rewrites a security-relevant file in the user's home directory.

Suggested fixes

  • Make config writes idempotent: look for an existing block for the same Host alias and replace it in place, rather than appending.
  • Delimit generated regions with explicit markers (e.g. # >>> clustrix managed >>> / # <<< clustrix managed <<<) so the tool can rewrite only its own section and users can see what it owns.
  • Consider writing to a dedicated ~/.ssh/clustrix_config and having users add a single Include clustrix_config line, so clustrix never touches the main file.
  • In the test suite, redirect all SSH-config writes to a tmp_path fixture. No test should be able to modify ~/.ssh/config.
  • Optionally ship a clustrix ssh-config --prune command to clean up configs already affected.

Environment

  • clustrix installed from source (repo master)
  • macOS, OpenSSH client

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions