diff --git a/src/config/atomic-write.ts b/src/config/atomic-write.ts index 0ec0831c4c..69bc112146 100644 --- a/src/config/atomic-write.ts +++ b/src/config/atomic-write.ts @@ -1,7 +1,6 @@ import { chmodSync, closeSync, - constants, fchmodSync, fstatSync, lstatSync, @@ -121,7 +120,7 @@ function writePrivateTempFile( timeoutMemoKey: string, onCreated: () => void, ): void { - const descriptor = openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600); + const descriptor = openSync(path, "wx", 0o600); onCreated(); try { if (process.platform === "win32") { @@ -142,7 +141,7 @@ async function writePrivateTempFileAsync( timeoutMemoKey: string, onCreated: () => void, ): Promise { - const descriptor = openSync(path, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL, 0o600); + const descriptor = openSync(path, "wx", 0o600); onCreated(); try { if (process.platform === "win32") { diff --git a/tests/windows/windows-secret-acl.test.ts b/tests/windows/windows-secret-acl.test.ts index aa011bb516..079e4d187d 100644 --- a/tests/windows/windows-secret-acl.test.ts +++ b/tests/windows/windows-secret-acl.test.ts @@ -632,6 +632,18 @@ describe("icacls executable authority", () => { }); }); +describe("atomic secret temp writer portability", () => { + test("sync and async secret temp writers use Bun-portable exclusive creation", async () => { + // Bun on Windows misinterpreted the equivalent numeric O_* combination as + // ENOENT, so every pid/config/oauth temp write failed during ocx start + // and on management-API config saves. Keep both writers on the portable + // exclusive-write spelling ("wx" keeps O_EXCL; 0o600 keeps the private + // mode) so the O_CREAT bit can never be dropped again. + const src = readFileSync(repoPath("src", "config", "atomic-write.ts"), "utf8"); + expect(src.match(/openSync\(path, "wx", 0o600\)/g)).toHaveLength(2); + }); +}); + describe("diagnostics sanitization contract", () => { test("HardenResult diagnostics field is a plain string when present", () => { const filePath = join(testDir, "diag-test.json");