Summary
On POSIX, scan output directories are required to be mode 0700 and owned by the current user, and shared parents are checked for sticky/trusted ancestry (#118). Credential homes on Windows get an equivalent current-user-only ACL via secureWindowsCredentialHome.
Scan output on Windows has no equivalent. requirePrivateOutputDirectory and requireSecureOutputAncestry both early-return on win32, so prepared scan trees keep inherited ACLs. On a shared Windows directory (e.g. C:\Users\Public\... or a folder with inherited Allow rules for other users), another local principal can read or replace scan artifacts between prepare and complete-scan / contract load.
Evidence (current main @ 3bf2621, @openai/codex-security@0.1.5)
sdk/typescript/src/runtime.ts:
requirePrivateOutputDirectory — if (process.platform === "win32") return;
requireSecureOutputAncestry — same early return
secureWindowsCredentialHome / private ACL apply+verify exists for credential homes only
validatePreparedOutputDir / validateOutputDir / contract requireScanRoot call the no-op Windows helpers
- Multiscan
ensureOutputDirectory previously only mkdir'd without any private check
Workbench Python require_canonical_scan_directory also skips privacy on nt.
Steps to reproduce (Windows)
- Create a scan output path under a directory that inherits Allow ACEs for other local users (e.g. a Public or shared folder).
- Run
codex-security scan (or bulk-scan) with that --output-dir.
- Observe the created scan directory does not have access-rule protection restricted to the current user (contrast with
…/codex-home after login, which does).
- Another local user who inherits Allow on the parent can read findings/reports or replace sealed artifacts before completion.
Why in scope (SECURITY.md)
- Credentials, private source, and scan results must stay out of other security principals
- File-replacement races that forge completed scans or leak results
- Same boundary already enforced for Windows credential homes and POSIX scan output
Suggested fix
Reuse the credential-home Windows ACL helper for scan output:
- Apply + verify a current-user-only ACL when preparing scan output
- Re-verify on contract load / scan-root checks
- Apply the same private-output gate to multiscan / bulk-scan campaign roots
Affected version
@openai/codex-security@0.1.5
- Confirmed on
main at 3bf2621
Summary
On POSIX, scan output directories are required to be mode
0700and owned by the current user, and shared parents are checked for sticky/trusted ancestry (#118). Credential homes on Windows get an equivalent current-user-only ACL viasecureWindowsCredentialHome.Scan output on Windows has no equivalent.
requirePrivateOutputDirectoryandrequireSecureOutputAncestryboth early-return onwin32, so prepared scan trees keep inherited ACLs. On a shared Windows directory (e.g.C:\Users\Public\...or a folder with inherited Allow rules for other users), another local principal can read or replace scan artifacts between prepare andcomplete-scan/ contract load.Evidence (current
main@3bf2621,@openai/codex-security@0.1.5)sdk/typescript/src/runtime.ts:requirePrivateOutputDirectory—if (process.platform === "win32") return;requireSecureOutputAncestry— same early returnsecureWindowsCredentialHome/ private ACL apply+verify exists for credential homes onlyvalidatePreparedOutputDir/validateOutputDir/ contractrequireScanRootcall the no-op Windows helpersensureOutputDirectorypreviously only mkdir'd without any private checkWorkbench Python
require_canonical_scan_directoryalso skips privacy onnt.Steps to reproduce (Windows)
codex-security scan(or bulk-scan) with that--output-dir.…/codex-homeafter login, which does).Why in scope (SECURITY.md)
Suggested fix
Reuse the credential-home Windows ACL helper for scan output:
Affected version
@openai/codex-security@0.1.5mainat3bf2621