Skip to content

fix: close security-relevant gaps found in codebase audit - #547

Closed
PierrunoYT wants to merge 2 commits into
Gitlawb:mainfrom
PierrunoYT:fix/bug-hunt-security
Closed

fix: close security-relevant gaps found in codebase audit#547
PierrunoYT wants to merge 2 commits into
Gitlawb:mainfrom
PierrunoYT:fix/bug-hunt-security

Conversation

@PierrunoYT

@PierrunoYT PierrunoYT commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #545. Split out of #481 per review feedback, grouping the security-sensitive findings from #480 separately from the UX/robustness ones (see #546 for those).

  • sandbox: grant_scope path comparisons were case-sensitive, letting a persisted deny grant be bypassed by spelling a Windows path with different case
  • securefile/oauth: securefile.go's createSecretFile lacked the ERROR_ACCESS_DENIED handling oauth/encrypt.go already had, so concurrent zero processes on Windows could spuriously hard-fail credstore's encrypted API-key storage with "Access is denied"; both also discarded the real lock-creation error in favor of a subsequent unrelated ErrNotExist, masking genuine ACL failures behind a misleading "timed out: file does not exist" (not explicitly named in the split request, but grouped here since it's a matched pair and touches credential storage)
  • update: checksum verification didn't cross-check the archive filename it verified against the one being extracted; extractZip didn't reject symlink-mode entries like extractTarGz already did

Test plan

  • go build ./... clean
  • Regression test added for each fix
  • go test ./internal/sandbox/... ./internal/securefile/... ./internal/oauth/... ./internal/update/... passes

Summary by CodeRabbit

  • Bug Fixes
    • Improved encrypted secret-file creation retries when lock acquisition fails, including Windows permission contention, and ensured the final timeout reports the correct secret path.
    • Fixed persisted grant scope matching for more reliable file/directory coverage across platforms, with correct case-insensitive handling on Windows.
    • Strengthened standalone update validation by rejecting checksum/archive name mismatches.
    • Hardened ZIP extraction by refusing unsupported entry types (such as symlinks) so unsafe files aren’t written.

Split out of Gitlawb#481 per review feedback, grouping the security-sensitive
findings from issue Gitlawb#480 (a multi-agent codebase audit) separately
from the UX/robustness ones:

- sandbox: grant_scope path comparisons were case-sensitive, letting a
  persisted deny grant (e.g. `deny --path C:\Users\me\project\Secrets`)
  be silently bypassed by spelling a Windows path with different case
- securefile/oauth: securefile.go's createSecretFile lacked the
  ERROR_ACCESS_DENIED handling oauth/encrypt.go's already had, so
  concurrent zero processes on Windows could spuriously hard-fail
  credstore's encrypted API-key storage with "Access is denied"; both
  also discarded the real lock-creation error in favor of a subsequent
  unrelated ErrNotExist, masking genuine ACL failures behind a
  misleading "timed out: file does not exist"
- update: checksum verification didn't cross-check the archive
  filename it verified against the one being extracted, so a checksum
  file naming a different (but validly-hashed) archive could vouch for
  the wrong bytes before extraction; extractZip didn't reject
  symlink-mode entries like extractTarGz already did

All three fixes ship with regression tests. Refs Gitlawb#480.
@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b2aa155b-ae50-48be-8502-02e392c67d9e

📥 Commits

Reviewing files that changed from the base of the PR and between 6812f23 and 49c7505.

📒 Files selected for processing (1)
  • internal/update/apply.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/update/apply.go

Walkthrough

This PR updates secret-file retry handling, sandbox scope path matching, archive checksum validation, and ZIP extraction entry checks.

Changes

Bug fixes and validation improvements

Layer / File(s) Summary
Secret-file lock retry and timeout error tracking
internal/securefile/securefile.go, internal/securefile/securefile_test.go, internal/oauth/encrypt.go
createSecretFile retains the lock-creation error as lastErr, retries on contention via openSecretLockFile, and consistently reports the timeout against the secret path; a new test verifies retry-on-permission-contention.
Sandbox grant scope path matching
internal/sandbox/grant_scope.go, internal/sandbox/grant_scope_test.go
grantCovers now uses scopePathEqual and pathWithinRoot for file and directory scope matching, with tool-wide/empty scopes explicitly rejected; a Windows-only test verifies case-insensitive matching.
Archive checksum filename validation
internal/update/apply.go, internal/update/apply_test.go
verifyArchiveChecksum validates the checksum and checks the referenced ArchiveName against the expected archive name; a test verifies mismatch rejection.
ZIP extraction rejects non-regular entries
internal/update/extract.go, internal/update/extract_test.go
extractZip now rejects entries whose mode is not a regular file, and a test verifies symlink-mode entries are rejected and not written.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

Possibly related PRs

  • Gitlawb/zero#170: Modifies grantCovers scope matching semantics in internal/sandbox/grant_scope.go.
  • Gitlawb/zero#445: Modifies createSecretFile in internal/oauth/encrypt.go for Windows lock-retry handling.
  • Gitlawb/zero#461: Touches createSecretFile and ZIP extraction validation in the same areas.

Suggested reviewers: Vasanthdev2004, kevincodex1, gnanam1990, anandh8x

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the PR as a security-focused audit fix and matches the main intent of the changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses security-sensitive findings from the codebase audit by hardening update-archive verification/extraction, fixing Windows lock-contention behavior in secret-file creation, and ensuring sandbox persisted grants can’t be bypassed via Windows path casing differences.

Changes:

  • Update: enforce checksum filename cross-checking and reject non-regular ZIP entries (e.g., symlink-mode) during extraction.
  • Secure storage: retry secret lock creation on Windows ERROR_ACCESS_DENIED-style contention and preserve the underlying lock error instead of masking it.
  • Sandbox: make file/dir scope matching case-insensitive on Windows by routing comparisons through filepath.Rel.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
internal/update/extract.go Rejects non-regular ZIP entries to prevent symlink/special-entry extraction.
internal/update/extract_test.go Adds regression coverage for rejecting symlink-mode ZIP entries.
internal/update/apply.go Adds verifyArchiveChecksum to cross-check checksum target name vs expected archive.
internal/update/apply_test.go Adds regression test ensuring filename mismatches are rejected even if the checksum line is otherwise valid.
internal/securefile/securefile.go Treats Windows os.ErrPermission from lock creation as contention and preserves the lock creation error for timeouts.
internal/securefile/securefile_test.go Adds a regression test verifying retry behavior when lock creation returns os.ErrPermission.
internal/sandbox/grant_scope.go Uses filepath.Rel-based helpers for scope path equality/containment to avoid case-based bypass on Windows.
internal/sandbox/grant_scope_test.go Adds a Windows-only regression test for case-insensitive scope matching.
internal/oauth/encrypt.go Aligns OAuth token secret creation timeout error preservation with securefile behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +135 to 138
lastErr = err
if data, rerr := readSecretFileRetry(path); rerr == nil {
return data, nil
} else {
lastErr = rerr
}
Comment thread internal/oauth/encrypt.go
Comment on lines +129 to 132
lastErr = err
if data, rerr := readSecretFileRetry(path); rerr == nil {
return data, nil
} else {
lastErr = rerr
}
Comment thread internal/update/apply.go
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@PierrunoYT PierrunoYT closed this Jul 6, 2026
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.

Security-sensitive fixes from the codebase audit (#480): sandbox path-casing, credential lock handling, update checksum/symlink

2 participants