Create credential files with owner-only permissions - #945
Merged
Conversation
Contributor
Greptile SummaryThe PR centralizes sensitive-text persistence in a new owner-only atomic writer.
Confidence Score: 4/5The concurrent temporary-file race should be fixed before merging because simultaneous credential writes can fail or publish malformed data. The helper improves creation-time permissions, but all writes to a destination share an unprotected temporary pathname that concurrent viewer requests or CLI processes can delete or reuse. Files Needing Attention: strix/utils/secret_files.py, strix/viewer/auth.py Important Files Changed
Prompt To Fix All With AI### Issue 1
strix/utils/secret_files.py:24-30
**Shared temporary path races**
When two requests or processes write the same credential file concurrently, both use and unlink the same `.tmp` path, causing one write to raise `FileExistsError` or interfere with the other writer and publish malformed data. This is reachable through simultaneous OTP verification requests handled by the threaded viewer server.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Reviews (1): Last reviewed commit: "fix: create credential files with owner ..." | Re-trigger Greptile |
Three call sites wrote secrets with Path.write_text and restricted them with chmod afterwards. write_text creates using 0o666 & ~umask, so the contents were readable by other local users until the chmod landed, and permanently if it failed, since the failure was suppressed. Affected: the Codex OAuth access and refresh tokens, the env block written by the config loader, which carries API keys, and the viewer auth record. write_secret_text passes the mode to os.open so it applies at creation. The parent directory is created 0700, and a temporary left by an interrupted write is replaced rather than truncated. Measured on Linux under the default umask: 0644 holding the token before being narrowed to 0600, 0666 under umask 0.
Import ordering in codex.py, Path moved into a type-checking block where it is only used in annotations, and a noqa for the test fixture string ruff reads as a password.
lukiod
force-pushed
the
fix/secret-file-permissions
branch
from
August 1, 2026 04:25
47018c4 to
d0223c0
Compare
0xallam
approved these changes
Aug 4, 2026
0xallam
approved these changes
Aug 4, 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.
Credential files were written with
write_textand then chmod'd to 0600:Two problems. The file exists with the default umask (usually 0644) between the write and the chmod, so the token is briefly readable by any local user. And the chmod is suppressed, so if it fails the file just stays 0644 with nothing reported.
Adds
strix/utils/secret_files.pywithwrite_secret_text, which opens withO_CREAT | O_EXCLand mode 0600 so the file never exists with wider permissions, and uses it for the viewer auth file and the env block.Tests in
tests/test_secret_files.py. The permission assertions are POSIX-only and skip on Windows, which is where I ran them — 2 passed, 4 skipped locally.