Skip to content

🛡️ Sentinel: [HIGH] Fix path traversal / symlink attack via predictable temp files#55

Closed
himattm wants to merge 1 commit intomainfrom
sentinel-fix-symlink-attack-5391478927700929096
Closed

🛡️ Sentinel: [HIGH] Fix path traversal / symlink attack via predictable temp files#55
himattm wants to merge 1 commit intomainfrom
sentinel-fix-symlink-attack-5391478927700929096

Conversation

@himattm
Copy link
Copy Markdown
Owner

@himattm himattm commented Apr 20, 2026

🚨 Severity: HIGH
💡 Vulnerability: The application used predictable temporary filenames (e.g., path + ".tmp") in shared directories like os.TempDir() before renaming them for atomic writes. A malicious local user could pre-create a symlink pointing from the predictable .tmp file to a sensitive system file, causing the application to overwrite it with application privileges.
🎯 Impact: Local privilege escalation / arbitrary file overwrite.
🔧 Fix: Updated LoadOrCreateSnapshot and Save functions to use os.CreateTemp to generate unpredictable temporary files. The files are securely created, explicitly chmodded, and then renamed.
✅ Verification: Ran go test ./... to verify atomic writes still function correctly. Ensure no predictable .tmp files are created in os.TempDir().


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

Updated internal atomic file writes in `sparkline` and `burnrate` modules
to use `os.CreateTemp` instead of predictable `path + ".tmp"` filenames.
This prevents symlink attacks in shared temporary directories.

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 a security vulnerability involving predictable temporary filenames by implementing os.CreateTemp for atomic file writes in the burnrate and sparkline packages, along with adding relevant security documentation. Feedback suggests enhancing the reliability of these writes by incorporating Sync() calls and properly checking errors from Close(). Additionally, an ignored error from os.Rename in the sparkline package should be addressed to improve observability.

Comment on lines +73 to +83
if _, err := tmpFile.Write(data); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
if err := tmpFile.Chmod(0644); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
tmpFile.Close()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

For a robust atomic write, it is important to check the error returned by tmpFile.Close(). A failure during close can indicate that data was not successfully flushed to disk, and in such cases, the file should not be renamed to the target path. Additionally, consider calling tmpFile.Sync() before closing to ensure the data is persisted to stable storage, which is standard practice for atomic file updates.

Suggested change
if _, err := tmpFile.Write(data); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
if err := tmpFile.Chmod(0644); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
tmpFile.Close()
if _, err := tmpFile.Write(data); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
if err := tmpFile.Sync(); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
if err := tmpFile.Chmod(0644); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return nil, false, err
}
if err := tmpFile.Close(); err != nil {
os.Remove(tmpPath)
return nil, false, err
}

Comment on lines +148 to +158
if _, err := tmpFile.Write(data); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
os.Rename(tmp, path)
if err := tmpFile.Chmod(0644); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
tmpFile.Close()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Similar to the burnrate implementation, the error from tmpFile.Close() should be checked to ensure the write was successful before proceeding to the rename. Adding tmpFile.Sync() is also recommended for durability.

Suggested change
if _, err := tmpFile.Write(data); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
os.Rename(tmp, path)
if err := tmpFile.Chmod(0644); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
tmpFile.Close()
if _, err := tmpFile.Write(data); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
if err := tmpFile.Sync(); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
if err := tmpFile.Chmod(0644); err != nil {
tmpFile.Close()
os.Remove(tmpPath)
return
}
if err := tmpFile.Close(); err != nil {
os.Remove(tmpPath)
return
}

Comment on lines +160 to +162
if err := os.Rename(tmpPath, path); err != nil {
os.Remove(tmpPath)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The error from os.Rename is silently ignored. While the current function signature does not return an error, swallowing the failure makes it difficult to diagnose why sparkline data is not being updated. Consider logging the error or updating the function to return an error to the caller.

@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-5391478927700929096 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 superseded 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