Skip to content

🛡️ Sentinel: [HIGH] Fix symlink attack vulnerability in atomic file writes#58

Closed
himattm wants to merge 1 commit intomainfrom
sentinel/fix-symlink-attack-atomic-writes-8487149965762085523
Closed

🛡️ Sentinel: [HIGH] Fix symlink attack vulnerability in atomic file writes#58
himattm wants to merge 1 commit intomainfrom
sentinel/fix-symlink-attack-atomic-writes-8487149965762085523

Conversation

@himattm
Copy link
Copy Markdown
Owner

@himattm himattm commented Apr 21, 2026

🚨 Severity: HIGH
💡 Vulnerability: Symlink attack during atomic file writes in shared directories. The code used predictable temporary file names (e.g., path + ".tmp") with os.WriteFile before calling os.Rename.
🎯 Impact: An attacker could pre-create a symlink at the predictable path pointing to a sensitive file. When the application performs the atomic write, it would follow the symlink and overwrite the sensitive file with the new data.
🔧 Fix: Used os.CreateTemp to generate an unpredictable temporary file name. Replicated the original permissions by explicitly calling f.Chmod(0644). Explicitly closed the file using f.Close() before renaming to avoid Windows locking issues. Used defer os.Remove(tmp) for cleanup if the process fails.
✅ Verification: go test ./... and go fmt ./... completed successfully. Modifications in .jules/sentinel.md properly document the vulnerability and its prevention.


PR created automatically by Jules for task 8487149965762085523 started by @himattm

…rites

This commit fixes a symlink attack vulnerability in `internal/sparkline/sparkline.go` and `internal/burnrate/burnrate.go`. The previous implementation used a predictable temporary file name (`path + ".tmp"`) with `os.WriteFile` before calling `os.Rename`. This could allow an attacker to pre-create a symlink at the predictable path in a shared directory (like `os.TempDir()`), causing the application to overwrite an arbitrary sensitive file when performing the atomic write.

The issue has been resolved by replacing `os.WriteFile` with `os.CreateTemp` to generate an unpredictable temporary file name. Additional care was taken to explicitly set permissions using `f.Chmod(0644)` to match the original behavior (since `os.CreateTemp` defaults to `0600`) and to explicitly close the file handle (`f.Close()`) before calling `os.Rename` to prevent lock issues on Windows. A deferred `os.Remove(tmp)` ensures cleanup of the temporary file in case the rename operation fails.

Co-authored-by: himattm <6266621+himattm@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request addresses symlink attack vulnerabilities in internal/burnrate/burnrate.go and internal/sparkline/sparkline.go by implementing os.CreateTemp for atomic file writes. The review feedback highlights a security concern where file permissions are relaxed before data is written, potentially leading to information disclosure in shared directories, and recommends adding f.Sync() for better data durability.

Comment on lines +75 to +84
// Match original permissions (os.CreateTemp defaults to 0600)
if err := f.Chmod(0644); err != nil {
f.Close()
return nil, false, err
}

if _, err := f.Write(data); err != nil {
f.Close()
return nil, false, err
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

In shared directories like /tmp, calling f.Chmod(0644) before writing data allows other users to read the file's contents while they are being written. It is more secure to keep the default 0600 permissions during the write and only change them to 0644 after the data is successfully written and synced. Additionally, calling f.Sync() ensures that the data is persisted to disk before the rename, which is a best practice for atomic file writes to prevent data loss or corruption during a system crash.

Comment on lines +150 to +159
// Match original permissions (os.CreateTemp defaults to 0600)
if err := f.Chmod(0644); err != nil {
f.Close()
return
}

if _, err := f.Write(data); err != nil {
f.Close()
return
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Similar to the change in burnrate.go, the file permissions should be updated only after the data has been written and synced. This prevents other users in a shared directory from reading the file while it is in an incomplete state. Adding f.Sync() is also recommended to ensure durability before the atomic rename.

@himattm
Copy link
Copy Markdown
Owner Author

himattm commented May 7, 2026

Closing as superseded by direct commit 42f3149 on main, which consolidated the burnrate/sparkline predictable-temp-file fixes and also preserved PR #82's updater temp-file hardening without the generated .jules note.

@himattm himattm closed this May 7, 2026
@himattm himattm deleted the sentinel/fix-symlink-attack-atomic-writes-8487149965762085523 branch May 7, 2026 15:36
@google-labs-jules
Copy link
Copy Markdown
Contributor

Closing as superseded by direct commit 42f3149 on main, which consolidated the burnrate/sparkline predictable-temp-file fixes and also preserved PR #82's updater temp-file hardening without the generated .jules note.

Understood. Acknowledging that this work is now obsolete as it has been superseded by a direct commit on main, and stopping work on this task.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant