openclaw - ✅(Solved) Fix Bug: TOCTOU race conditions in JSON file save, Matrix credentials migration, and GCP credentials loading [3 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#54295Fetched 2026-04-08 01:29:26
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
0
Timeline (top)
cross-referenced ×4closed ×1commented ×1locked ×1

Three separate TOCTOU (Time-of-Check-to-Time-of-Use) race conditions found across the codebase:

Error Message

  1. GCP: Use readFile() directly with error handling, skip the existsSync check

Root Cause

Three separate TOCTOU (Time-of-Check-to-Time-of-Use) race conditions found across the codebase:

PR fix notes

PR #60589: infra: atomically replace sync JSON writes

Description (problem / solution / changelog)

Summary

  • replace sync JSON writes with sibling-temp atomic rename semantics
  • remove the pre-read existsSync check so reads rely on direct read/parse fallback
  • add regression coverage for the temp-path replacement flow

Verification

  • pnpm format src/infra/json-file.ts src/infra/json-file.test.ts
  • direct concurrent writer/reader script against src/infra/json-file.ts (parseFailures: 0 across 835 reads)
  • pnpm test -- src/infra/json-file.test.ts hung in this environment, so I did not count it as passing

Part of #54295.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/infra/json-file.test.ts (modified, +111/-8)
  • src/infra/json-file.ts (modified, +115/-9)

PR #60591: matrix: retry credentials after legacy migration race

Description (problem / solution / changelog)

Summary

  • retry the current Matrix credentials path when the legacy file disappears during migration
  • keep the migration path returning stored credentials instead of transiently falling back to null
  • add regression coverage for the legacy-to-current rename race

Verification

  • pnpm format extensions/matrix/src/matrix/credentials-read.ts extensions/matrix/src/matrix/credentials.test.ts
  • pnpm test -- extensions/matrix/src/matrix/credentials.test.ts timed out in this environment, so I did not count it as passing

Part of #54295.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/matrix/src/matrix/credentials-read.ts (modified, +61/-16)
  • extensions/matrix/src/matrix/credentials.test.ts (modified, +129/-0)

PR #60592: vertex: read ADC files without exists preflight

Description (problem / solution / changelog)

Summary

  • remove the separate existsSync preflight from Vertex ADC discovery
  • use direct readFileSync error handling for both project-id lookup and ADC presence checks
  • add focused coverage that mocks node:fs and asserts we do not rely on existsSync

Verification

  • pnpm format extensions/anthropic-vertex/region.ts extensions/anthropic-vertex/region.test.ts
  • raw vitest run does not include extensions/** under this repo config, so I did not count it as a passing test lane here

Part of #54295.

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • extensions/anthropic-vertex/region.adc.test.ts (added, +49/-0)
  • extensions/anthropic-vertex/region.ts (modified, +18/-18)
  • src/plugin-sdk/anthropic-vertex-auth-presence.preflight.test.ts (added, +48/-0)
  • src/plugin-sdk/anthropic-vertex-auth-presence.ts (modified, +26/-16)
RAW_BUFFERClick to expand / collapse

Summary

Three separate TOCTOU (Time-of-Check-to-Time-of-Use) race conditions found across the codebase:

1. JSON File Save (dist/json-file-Dl3Z1jL1.js:13-21)

saveJsonFile does existsSync(dir)mkdirSyncwriteFileSync without atomic write. Two concurrent processes can produce corrupt/partial JSON. loadJsonFile can read a partially-written file.

2. Matrix Credentials Migration (dist/credentials-read-BLFr7diG.js:47-55)

loadMatrixCredentials checks existsSync(credPath)existsSync(legacyPath)parseMatrixCredentialsFile(legacyPath)renameSync. If another process migrated between check and read, unhandled ENOENT is thrown.

3. GCP Credentials Loading (dist/anthropic-vertex-provider-B2x4YywE.js:39-47)

existsSync(credentialsPath) check followed by readFileSync(credentialsPath) in a separate function. Between check and read, the file could be replaced with a symlink.

Impact

  • Config corruption on concurrent access, potentially causing service failure
  • Crash on concurrent startup during Matrix credential migration
  • Symlink substitution in GCP credentials could redirect API traffic

Suggested Fix

  1. JSON save: Implement atomic write (write to temp + rename())
  2. Matrix: Wrap parseMatrixCredentialsFile in try/catch for ENOENT
  3. GCP: Use readFile() directly with error handling, skip the existsSync check

extent analysis

Fix Plan

To address the TOCTOU race conditions, we will implement the following fixes:

1. JSON File Save

Implement atomic write by writing to a temporary file and then renaming it.

const fs = require('fs');
const os = require('os');
const path = require('path');

function saveJsonFile(dir, data) {
  const tmpDir = os.tmpdir();
  const tmpFile = path.join(tmpDir, `tmp-${Date.now()}.json`);
  fs.writeFileSync(tmpFile, JSON.stringify(data));
  fs.renameSync(tmpFile, dir);
}

2. Matrix Credentials Migration

Wrap parseMatrixCredentialsFile in a try/catch block to handle ENOENT errors.

function loadMatrixCredentials(credPath, legacyPath) {
  try {
    if (fs.existsSync(credPath)) return;
    if (fs.existsSync(legacyPath)) {
      const credentials = parseMatrixCredentialsFile(legacyPath);
      // Save credentials to new location
      fs.writeFileSync(credPath, JSON.stringify(credentials));
      fs.unlinkSync(legacyPath);
    }
  } catch (error) {
    if (error.code === 'ENOENT') {
      // Handle the case where the file was migrated by another process
      console.log('File already migrated');
    } else {
      throw error;
    }
  }
}

3. GCP Credentials Loading

Use readFile() directly with error handling, skipping the existsSync check.

function loadGcpCredentials(credentialsPath) {
  fs.readFile(credentialsPath, (error, data) => {
    if (error) {
      if (error.code === 'ENOENT') {
        // Handle the case where the file does not exist
        console.log('Credentials file not found');
      } else {
        throw error;
      }
    } else {
      // Parse and return the credentials
      return JSON.parse(data);
    }
  });
}

Verification

To verify that the fixes worked, test the code with concurrent access and check for:

  • Config corruption
  • Service failure
  • Crash on concurrent startup during Matrix credential migration
  • Symlink substitution in GCP credentials

Extra Tips

  • Always use atomic operations when working with files to prevent TOCTOU race conditions.
  • Use try/catch blocks to handle potential errors and exceptions.
  • Avoid using existsSync checks before reading or writing files, instead use readFile() or writeFile() with error handling.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix Bug: TOCTOU race conditions in JSON file save, Matrix credentials migration, and GCP credentials loading [3 pull requests, 1 comments, 2 participants]