@@ -176,10 +176,59 @@ describe('Credential Hiding Security', () => {
176176 // Check debug logs for chroot credential hiding messages
177177 expect ( result . stderr ) . toMatch ( / C h r o o t m o d e .* [ H h ] i d i n g c r e d e n t i a l | H i d d e n .* c r e d e n t i a l .* c h r o o t / i) ;
178178 } , 120000 ) ;
179+
180+ test ( 'Test 8: Chroot mode ALSO hides credentials at direct home path (bypass prevention)' , async ( ) => {
181+ const homeDir = os . homedir ( ) ;
182+
183+ // SECURITY FIX TEST: Previously, credentials were only hidden at /host paths in chroot mode,
184+ // but the home directory was ALSO mounted directly at $HOME. An attacker could bypass
185+ // protection by reading from the direct mount instead of /host.
186+ //
187+ // This test specifically verifies that credentials are hidden at the direct home mount
188+ // (the bypass path). The /host chroot path is covered by
189+ // "Test 6: Chroot mode hides credentials at /host paths".
190+
191+ const result = await runner . runWithSudo (
192+ `cat ${ homeDir } /.docker/config.json 2>&1 | grep -v "^\\[" | head -1` ,
193+ {
194+ allowDomains : [ 'github.com' ] ,
195+ logLevel : 'debug' ,
196+ timeout : 60000 ,
197+ // Chroot is always enabled (no flag needed)
198+ }
199+ ) ;
200+
201+ // Command should succeed (file is "readable" but empty)
202+ expect ( result ) . toSucceed ( ) ;
203+ // Output should be empty (no credential data leaked via direct home mount)
204+ const output = result . stdout . trim ( ) ;
205+ expect ( output ) . toBe ( '' ) ;
206+ } , 120000 ) ;
207+
208+ test ( 'Test 9: Chroot mode hides GitHub CLI tokens at direct home path' , async ( ) => {
209+ const homeDir = os . homedir ( ) ;
210+
211+ // Verify another critical credential file is hidden at the direct home mount
212+ // (the bypass path). The /host chroot path is covered by Test 6.
213+ const result = await runner . runWithSudo (
214+ `cat ${ homeDir } /.config/gh/hosts.yml 2>&1 | grep -v "^\\[" | head -1` ,
215+ {
216+ allowDomains : [ 'github.com' ] ,
217+ logLevel : 'debug' ,
218+ timeout : 60000 ,
219+ // Chroot is always enabled (no flag needed)
220+ }
221+ ) ;
222+
223+ expect ( result ) . toSucceed ( ) ;
224+ // Output should be empty (no credential data leaked via direct home mount)
225+ const output = result . stdout . trim ( ) ;
226+ expect ( output ) . toBe ( '' ) ;
227+ } , 120000 ) ;
179228 } ) ;
180229
181230 describe ( 'Full Filesystem Access Flag (--allow-full-filesystem-access)' , ( ) => {
182- test ( 'Test 8 : Full filesystem access shows security warnings' , async ( ) => {
231+ test ( 'Test 10 : Full filesystem access shows security warnings' , async ( ) => {
183232 const result = await runner . runWithSudo (
184233 'echo "test"' ,
185234 {
@@ -197,7 +246,7 @@ describe('Credential Hiding Security', () => {
197246 expect ( result . stderr ) . toMatch ( / e n t i r e h o s t f i l e s y s t e m .* m o u n t e d | F u l l f i l e s y s t e m a c c e s s / i) ;
198247 } , 120000 ) ;
199248
200- test ( 'Test 9 : With full access, Docker config is NOT hidden' , async ( ) => {
249+ test ( 'Test 11 : With full access, Docker config is NOT hidden' , async ( ) => {
201250 const homeDir = os . homedir ( ) ;
202251 const dockerConfig = `${ homeDir } /.docker/config.json` ;
203252
@@ -227,7 +276,7 @@ describe('Credential Hiding Security', () => {
227276 } ) ;
228277
229278 describe ( 'Security Verification' , ( ) => {
230- test ( 'Test 10 : Simulated exfiltration attack gets empty data' , async ( ) => {
279+ test ( 'Test 12 : Simulated exfiltration attack gets empty data' , async ( ) => {
231280 const homeDir = os . homedir ( ) ;
232281
233282 // Simulate prompt injection attack: read credential file and encode it
@@ -249,7 +298,7 @@ describe('Credential Hiding Security', () => {
249298 expect ( output ) . toBe ( '' ) ;
250299 } , 120000 ) ;
251300
252- test ( 'Test 11 : Multiple encoding attempts still get empty data' , async ( ) => {
301+ test ( 'Test 13 : Multiple encoding attempts still get empty data' , async ( ) => {
253302 const homeDir = os . homedir ( ) ;
254303
255304 // Simulate sophisticated attack: multiple encoding layers
@@ -270,7 +319,7 @@ describe('Credential Hiding Security', () => {
270319 expect ( output ) . toBe ( '' ) ;
271320 } , 120000 ) ;
272321
273- test ( 'Test 12 : grep for tokens in hidden files finds nothing' , async ( ) => {
322+ test ( 'Test 14 : grep for tokens in hidden files finds nothing' , async ( ) => {
274323 const homeDir = os . homedir ( ) ;
275324
276325 // Try to grep for common credential patterns
@@ -294,7 +343,7 @@ describe('Credential Hiding Security', () => {
294343 } ) ;
295344
296345 describe ( 'MCP Logs Directory Hiding' , ( ) => {
297- test ( 'Test 13 : /tmp/gh-aw/mcp-logs/ is hidden in normal mode' , async ( ) => {
346+ test ( 'Test 15 : /tmp/gh-aw/mcp-logs/ is hidden in normal mode' , async ( ) => {
298347 // Try to access the mcp-logs directory
299348 const result = await runner . runWithSudo (
300349 'ls -la /tmp/gh-aw/mcp-logs/ 2>&1 | grep -v "^\\[" | head -1' ,
@@ -314,7 +363,7 @@ describe('Credential Hiding Security', () => {
314363 expect ( allOutput ) . toMatch ( / t o t a l | N o t a d i r e c t o r y | c a n n o t a c c e s s / i) ;
315364 } , 120000 ) ;
316365
317- test ( 'Test 14 : /tmp/gh-aw/mcp-logs/ is hidden in chroot mode' , async ( ) => {
366+ test ( 'Test 16 : /tmp/gh-aw/mcp-logs/ is hidden in chroot mode' , async ( ) => {
318367 // Try to access the mcp-logs directory at /host path
319368 const result = await runner . runWithSudo (
320369 'ls -la /host/tmp/gh-aw/mcp-logs/ 2>&1 | grep -v "^\\[" | head -1' ,
@@ -330,7 +379,7 @@ describe('Credential Hiding Security', () => {
330379 expect ( allOutput ) . toMatch ( / t o t a l | N o t a d i r e c t o r y | c a n n o t a c c e s s / i) ;
331380 } , 120000 ) ;
332381
333- test ( 'Test 15 : MCP logs files cannot be read in normal mode' , async ( ) => {
382+ test ( 'Test 17 : MCP logs files cannot be read in normal mode' , async ( ) => {
334383 // Try to read a typical MCP log file path
335384 const result = await runner . runWithSudo (
336385 'cat /tmp/gh-aw/mcp-logs/safeoutputs/log.txt 2>&1 | grep -v "^\\[" | head -1' ,
0 commit comments