fix: atomic symlink replacement in cert client #34

Merged
heiko merged 1 commit from fix/23-atomic-symlink-replace into master 2026-05-18 10:07:29 +02:00
Owner

Fixes #23.

Summary

  • Replace os.Remove+os.Symlink with a tmp-symlink+rename pattern in the cert client
  • Eliminates the TOCTOU window where a local attacker with write access to certbase could race the Remove/Symlink gap to redirect private-key writes
  • Extract replaceSymlink helper for clarity and testability

Test plan

  • TestReplaceSymlink_Fresh passes (symlink created when absent)
  • TestReplaceSymlink_ExistingSymlink passes (symlink atomically replaced)
  • TestExecute_Symlink still passes (existing integration test)
  • golangci-lint clean
Fixes #23. ## Summary - Replace os.Remove+os.Symlink with a tmp-symlink+rename pattern in the cert client - Eliminates the TOCTOU window where a local attacker with write access to certbase could race the Remove/Symlink gap to redirect private-key writes - Extract replaceSymlink helper for clarity and testability ## Test plan - [x] TestReplaceSymlink_Fresh passes (symlink created when absent) - [x] TestReplaceSymlink_ExistingSymlink passes (symlink atomically replaced) - [x] TestExecute_Symlink still passes (existing integration test) - [x] golangci-lint clean
Use a tmp symlink + rename to avoid the TOCTOU window between
os.Remove and os.Symlink, where a local attacker with write access
to certbase could redirect the next private-key write.

Fixes #23.

ius:ai:claude-sonnet-4-6
Author
Owner

Correct fix. rename(2) is atomic on POSIX so readers never see a missing symlink.

Minor (non-blocker): assert.NoFileExists(t, name+".tmp") would replace the manual Lstat+IsNotExist check in both tests.

Correct fix. `rename(2)` is atomic on POSIX so readers never see a missing symlink. Minor (non-blocker): `assert.NoFileExists(t, name+".tmp")` would replace the manual Lstat+IsNotExist check in both tests.
heiko merged commit 8e67aa9e37 into master 2026-05-18 10:07:29 +02:00
Sign in to join this conversation.
No description provided.