Security: harden local key file writes, use SFTP for remote file access - #40
Merged
Merged
Conversation
Local: - KeyFileWriterService: truncate on overwrite (FileMode.Create), CreateNew otherwise, FileShare.None, and enforce 0600 on overwritten files since UnixCreateMode only applies on creation. - Create the backup directory (holds private key copies) and ~/.ssh with 0700. Remote: - Read/write authorized_keys and known_hosts via SFTP instead of shell command lines built from server-provided paths and file contents (broken quoting on Windows for entries containing '"', e.g. command="..."). - No more eager file creation on connect; missing files read as empty and are created with 0600 (dir 0700) on Unix hosts when written. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XSUJwZ17AWMdDvYXboJAbQ
This was referenced Sep 28, 2026
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
Fixes two security findings in how the app reads and writes files.
Local (
KeyFileWriterService,KeyFileBackupService,SshConfigFilesExtension)FileMode.OpenOrCreate, which does not truncate it. If the new key was shorter (for example, the passphrase was removed), bytes of the old key stayed at the end of the file and the key was corrupt. The writer now usesFileMode.Createto overwrite andFileMode.CreateNewotherwise;CreateNewalso closes the race between the existence check and the open.UnixCreateModeonly applies when a file is created. An existing file with 0644 kept those permissions even after a private key was written into it. The writer now sets 0600 explicitly on the file handle.FileShare.ReadWriteis nowFileShare.None.~/.ssh/<App>, which holds copies of the private keys, and a newly created~/.sshare now created with 0700.Remote (
ServerConnection)echo $HOME, unquoted incat/touch) and from file contents. On Windows, the content ended up insidepowershell -Command "...", so a"inauthorized_keys(for example,command="..."options) broke the quoting. That corrupts the file or lets an entry inject commands.authorized_keysandknown_hostsare now read and written viaSftpClient, using paths relative to the SFTP home directory. No file path or file content goes through a shell anymore, and the command-line length limit no longer applies.Set-Content -Encoding UTF8in PowerShell 5.1 wrote a BOM; the file is now written as UTF-8 without BOM.ServerConnection.Disposenow also disposes the SSH and SFTP clients.Changes Made
Testing Performed
Test Evidence
KeyFileWriterServiceTestswith 4 tests: truncation on overwrite, no overwrite without the flag, 0600 on an existing 0644 file, 0600 on a new file.Checklist
dotnet build,dotnet test)Questions for Reviewers
Notes for Reviewers:
🤖 Generated with Claude Code
https://claude.ai/code/session_01XSUJwZ17AWMdDvYXboJAbQ
Generated by Claude Code