@@ -373,44 +373,62 @@ export async function runSecurityTests() {
373373 const tempDir = path . join ( os . tmpdir ( ) , `opencode-sec-test-${ Date . now ( ) } ` ) ;
374374 ensureSecureDirectory ( tempDir ) ;
375375
376- const dirStat = fs . statSync ( tempDir ) ;
377- assert . strictEqual ( dirStat . mode & 0o777 , 0o700 , 'Parent directory must have restricted permissions (0700)' ) ;
376+ const isWindows = process . platform === 'win32' ;
377+
378+ if ( ! isWindows ) {
379+ const dirStat = fs . statSync ( tempDir ) ;
380+ assert . strictEqual ( dirStat . mode & 0o777 , 0o700 , 'Parent directory must have restricted permissions (0700)' ) ;
381+ }
378382
379383 // Subtest 8A: Newly created sensitive file has mode 0600
380384 const sensitiveFile = path . join ( tempDir , 'active-xray-config.json' ) ;
381385 safeWriteSensitiveFile ( sensitiveFile , JSON . stringify ( { secret : 'password123' } ) ) ;
382- const fileStat = fs . statSync ( sensitiveFile ) ;
383- assert . strictEqual ( fileStat . mode & 0o777 , 0o600 , 'Newly created sensitive file must have mode 0600' ) ;
386+ if ( ! isWindows ) {
387+ const fileStat = fs . statSync ( sensitiveFile ) ;
388+ assert . strictEqual ( fileStat . mode & 0o777 , 0o600 , 'Newly created sensitive file must have mode 0600' ) ;
389+ }
384390 assert . strictEqual ( fs . readFileSync ( sensitiveFile , 'utf-8' ) , JSON . stringify ( { secret : 'password123' } ) ) ;
385391 console . log ( ' ✔ Newly created sensitive file enforced mode 0600.' ) ;
386392
387393 // Subtest 8B: Overwriting pre-existing file with permissive mode (0664) is corrected to 0600
388- fs . chmodSync ( sensitiveFile , 0o664 ) ;
389- assert . strictEqual ( fs . statSync ( sensitiveFile ) . mode & 0o777 , 0o664 , 'Setup: file made permissive 0664' ) ;
390- safeWriteSensitiveFile ( sensitiveFile , JSON . stringify ( { secret : 'updatedPassword' } ) ) ;
391- const updatedStat = fs . statSync ( sensitiveFile ) ;
392- assert . strictEqual ( updatedStat . mode & 0o777 , 0o600 , 'Overwritten file must have permissions corrected to 0600' ) ;
394+ if ( ! isWindows ) {
395+ fs . chmodSync ( sensitiveFile , 0o664 ) ;
396+ assert . strictEqual ( fs . statSync ( sensitiveFile ) . mode & 0o777 , 0o664 , 'Setup: file made permissive 0664' ) ;
397+ safeWriteSensitiveFile ( sensitiveFile , JSON . stringify ( { secret : 'updatedPassword' } ) ) ;
398+ const updatedStat = fs . statSync ( sensitiveFile ) ;
399+ assert . strictEqual ( updatedStat . mode & 0o777 , 0o600 , 'Overwritten file must have permissions corrected to 0600' ) ;
400+ } else {
401+ safeWriteSensitiveFile ( sensitiveFile , JSON . stringify ( { secret : 'updatedPassword' } ) ) ;
402+ }
403+ assert . strictEqual ( fs . readFileSync ( sensitiveFile , 'utf-8' ) , JSON . stringify ( { secret : 'updatedPassword' } ) ) ;
393404 console . log ( ' ✔ Overwrite of pre-existing permissive file explicitly corrected to 0600.' ) ;
394405
395406 // Subtest 8C: Symlink overwrite attack blocked
396407 const targetFile = path . join ( tempDir , 'critical-target.txt' ) ;
397- fs . writeFileSync ( targetFile , 'PROTECTED_SYSTEM_DATA' , { mode : 0o600 } ) ;
408+ fs . writeFileSync ( targetFile , 'PROTECTED_SYSTEM_DATA' ) ;
398409 const symlinkPath = path . join ( tempDir , 'symlink-attack-file.json' ) ;
399- fs . symlinkSync ( targetFile , symlinkPath ) ;
400-
401- assert . throws (
402- ( ) => safeWriteSensitiveFile ( symlinkPath , 'MALICIOUS_OVERWRITE' ) ,
403- / R e f u s i n g t o w r i t e t h r o u g h s y m b o l i c l i n k / ,
404- 'Attempt to write through symlink must throw security error'
405- ) ;
406- assert . strictEqual ( fs . readFileSync ( targetFile , 'utf-8' ) , 'PROTECTED_SYSTEM_DATA' , 'Target file must not be modified through symlink' ) ;
407- console . log ( ' ✔ Symlink overwrite attack strictly blocked; target preserved.' ) ;
410+ try {
411+ fs . symlinkSync ( targetFile , symlinkPath ) ;
412+ assert . throws (
413+ ( ) => safeWriteSensitiveFile ( symlinkPath , 'MALICIOUS_OVERWRITE' ) ,
414+ / R e f u s i n g t o w r i t e t h r o u g h s y m b o l i c l i n k / ,
415+ 'Attempt to write through symlink must throw security error'
416+ ) ;
417+ assert . strictEqual ( fs . readFileSync ( targetFile , 'utf-8' ) , 'PROTECTED_SYSTEM_DATA' , 'Target file must not be modified through symlink' ) ;
418+ console . log ( ' ✔ Symlink overwrite attack strictly blocked; target preserved.' ) ;
419+ } catch ( symErr : any ) {
420+ if ( isWindows && symErr . code === 'EPERM' ) {
421+ console . log ( ' ✔ Symlink creation requires SeCreateSymbolicLinkPrivilege on Windows (skipped non-admin symlink test).' ) ;
422+ } else {
423+ throw symErr ;
424+ }
425+ }
408426
409427 // Cleanup
410428 try {
411- fs . unlinkSync ( symlinkPath ) ;
412- fs . unlinkSync ( sensitiveFile ) ;
413- fs . unlinkSync ( targetFile ) ;
429+ if ( fs . existsSync ( symlinkPath ) ) fs . unlinkSync ( symlinkPath ) ;
430+ if ( fs . existsSync ( sensitiveFile ) ) fs . unlinkSync ( sensitiveFile ) ;
431+ if ( fs . existsSync ( targetFile ) ) fs . unlinkSync ( targetFile ) ;
414432 fs . rmdirSync ( tempDir ) ;
415433 } catch { }
416434 console . log ( ' ✔ Temporary test files and directory cleaned up.\n' ) ;
0 commit comments