@@ -4,6 +4,8 @@ import type { WindowsAclEntry, WindowsAclSummary } from "./windows-acl.js";
44const MOCK_USERNAME = "MockUser" ;
55const mockUserInfo = ( ) => ( { username : MOCK_USERNAME } ) ;
66const emptyUserInfo = ( ) => ( { username : "" } ) ;
7+ const DEFAULT_ICACLS = "C:\\Windows\\System32\\icacls.exe" ;
8+ const DEFAULT_WHOAMI = "C:\\Windows\\System32\\whoami.exe" ;
79
810let createIcaclsResetCommand : typeof import ( "./windows-acl.js" ) . createIcaclsResetCommand ;
911let formatIcaclsResetCommand : typeof import ( "./windows-acl.js" ) . formatIcaclsResetCommand ;
@@ -424,7 +426,7 @@ Successfully processed 1 files`;
424426 expectInspectSuccess ( result , 2 ) ;
425427 // /sid is passed so that account names are printed as SIDs, making the
426428 // audit locale-independent (fixes #35834).
427- expect ( mockExec ) . toHaveBeenCalledWith ( "icacls.exe" , [ "C:\\test\\file.txt" , "/sid" ] ) ;
429+ expect ( mockExec ) . toHaveBeenCalledWith ( DEFAULT_ICACLS , [ "C:\\test\\file.txt" , "/sid" ] ) ;
428430 } ) ;
429431
430432 it ( "classifies *S-1-5-18 (SID form of SYSTEM from /sid) as trusted" , async ( ) => {
@@ -469,8 +471,8 @@ Successfully processed 1 files`;
469471 expectInspectSuccess ( result , 2 ) ;
470472 expect ( result . trusted ) . toHaveLength ( 2 ) ;
471473 expect ( result . untrustedGroup ) . toHaveLength ( 0 ) ;
472- expect ( mockExec ) . toHaveBeenNthCalledWith ( 1 , "icacls.exe" , [ "C:\\test\\file.txt" , "/sid" ] ) ;
473- expect ( mockExec ) . toHaveBeenNthCalledWith ( 2 , "whoami.exe" , [ "/user" , "/fo" , "csv" , "/nh" ] ) ;
474+ expect ( mockExec ) . toHaveBeenNthCalledWith ( 1 , DEFAULT_ICACLS , [ "C:\\test\\file.txt" , "/sid" ] ) ;
475+ expect ( mockExec ) . toHaveBeenNthCalledWith ( 2 , DEFAULT_WHOAMI , [ "/user" , "/fo" , "csv" , "/nh" ] ) ;
474476 } ) ;
475477
476478 it ( "returns error state on exec failure" , async ( ) => {
@@ -533,21 +535,61 @@ Successfully processed 1 files`;
533535
534536 const result = await inspectWindowsAcl ( "C:\\test\\file.txt" , {
535537 exec : mockExec ,
536- env : { SystemRoot : "C :\\Windows" } ,
538+ env : { SystemRoot : "D :\\Windows" } ,
537539 } ) ;
538540
539541 expectInspectSuccess ( result , 1 ) ;
540- expect ( mockExec ) . toHaveBeenNthCalledWith ( 1 , "C :\\Windows\\System32\\icacls.exe" , [
542+ expect ( mockExec ) . toHaveBeenNthCalledWith ( 1 , "D :\\Windows\\System32\\icacls.exe" , [
541543 "C:\\test\\file.txt" ,
542544 "/sid" ,
543545 ] ) ;
544- expect ( mockExec ) . toHaveBeenNthCalledWith ( 2 , "C :\\Windows\\System32\\whoami.exe" , [
546+ expect ( mockExec ) . toHaveBeenNthCalledWith ( 2 , "D :\\Windows\\System32\\whoami.exe" , [
545547 "/user" ,
546548 "/fo" ,
547549 "csv" ,
548550 "/nh" ,
549551 ] ) ;
550552 } ) ;
553+
554+ it ( "does not resolve Windows system commands through a relative SystemRoot" , async ( ) => {
555+ const mockExec = vi
556+ . fn ( )
557+ . mockResolvedValueOnce ( {
558+ stdout : "C:\\test\\file.txt *S-1-5-21-111-222-333-1001:(F)" ,
559+ stderr : "" ,
560+ } )
561+ . mockResolvedValueOnce ( {
562+ stdout : '"mock-host\\\\MockUser","S-1-5-21-111-222-333-1001"\r\n' ,
563+ stderr : "" ,
564+ } ) ;
565+
566+ const result = await inspectWindowsAcl ( "C:\\test\\file.txt" , {
567+ exec : mockExec ,
568+ env : { SystemRoot : ".\\fake-root" } ,
569+ } ) ;
570+
571+ expectInspectSuccess ( result , 1 ) ;
572+ expect ( mockExec ) . toHaveBeenNthCalledWith ( 1 , DEFAULT_ICACLS , [ "C:\\test\\file.txt" , "/sid" ] ) ;
573+ expect ( mockExec ) . toHaveBeenNthCalledWith ( 2 , DEFAULT_WHOAMI , [ "/user" , "/fo" , "csv" , "/nh" ] ) ;
574+ } ) ;
575+
576+ it ( "uses a valid WINDIR when SystemRoot is invalid" , async ( ) => {
577+ const mockExec = vi . fn ( ) . mockResolvedValueOnce ( {
578+ stdout : "C:\\test\\file.txt *S-1-5-18:(F)" ,
579+ stderr : "" ,
580+ } ) ;
581+
582+ const result = await inspectWindowsAcl ( "C:\\test\\file.txt" , {
583+ exec : mockExec ,
584+ env : { SystemRoot : ".\\fake-root" , WINDIR : "E:\\Windows" } ,
585+ } ) ;
586+
587+ expectInspectSuccess ( result , 1 ) ;
588+ expect ( mockExec ) . toHaveBeenCalledWith ( "E:\\Windows\\System32\\icacls.exe" , [
589+ "C:\\test\\file.txt" ,
590+ "/sid" ,
591+ ] ) ;
592+ } ) ;
551593 } ) ;
552594
553595 describe ( "formatWindowsAclSummary" , ( ) => {
@@ -653,11 +695,20 @@ Successfully processed 1 files`;
653695 env,
654696 } ) ;
655697 expect ( result ) . not . toBeNull ( ) ;
656- expect ( result ?. command ) . toBe ( "icacls" ) ;
698+ expect ( result ?. command ) . toBe ( DEFAULT_ICACLS ) ;
657699 expect ( result ?. args ) . toContain ( "C:\\test\\file.txt" ) ;
658700 expect ( result ?. args ) . toContain ( "/inheritance:r" ) ;
659701 } ) ;
660702
703+ it ( "uses a validated SystemRoot for the structured command executable" , ( ) => {
704+ const result = createIcaclsResetCommand ( "C:\\test\\file.txt" , {
705+ isDir : false ,
706+ env : { SystemRoot : "D:\\Windows" , USERNAME : "TestUser" } ,
707+ } ) ;
708+
709+ expect ( result ?. command ) . toBe ( "D:\\Windows\\System32\\icacls.exe" ) ;
710+ } ) ;
711+
661712 it ( "returns command with system username when env is empty (falls back to os.userInfo)" , ( ) => {
662713 // When env is empty, resolveWindowsUserPrincipal falls back to os.userInfo().username
663714 const result = createIcaclsResetCommand ( "C:\\test\\file.txt" , {
@@ -667,7 +718,7 @@ Successfully processed 1 files`;
667718 } ) ;
668719 // Should return a valid command using the system username
669720 expect ( result ) . not . toBeNull ( ) ;
670- expect ( result ?. command ) . toBe ( "icacls" ) ;
721+ expect ( result ?. command ) . toBe ( DEFAULT_ICACLS ) ;
671722 expect ( result ?. args ) . toContain ( `${ MOCK_USERNAME } :F` ) ;
672723 } ) ;
673724
0 commit comments