@@ -143,12 +143,15 @@ function getBlockedReasonForSourcePath(
143143 if ( sourceNormalized === "/" ) {
144144 return { kind : "covers" , blockedPath : "/" } ;
145145 }
146- const sourceKey = getSandboxHostPathPolicyKey ( sourceNormalized ) ;
147146 for ( const blocked of blockedHostPaths ) {
148- const blockedKey = getSandboxHostPathPolicyKey ( blocked ) ;
149- if ( sourceKey === blockedKey || sourceKey . startsWith ( `${ blockedKey } /` ) ) {
147+ if ( isPathInsidePolicyPath ( blocked , sourceNormalized ) ) {
150148 return { kind : "targets" , blockedPath : blocked } ;
151149 }
150+ // Parent mounts can expose blocked descendants such as HOME credentials or
151+ // the Docker socket directory even when the source root itself is allowed.
152+ if ( isPathInsidePolicyPath ( sourceNormalized , blocked ) ) {
153+ return { kind : "covers" , blockedPath : blocked } ;
154+ }
152155 }
153156
154157 return null ;
@@ -217,13 +220,14 @@ function normalizeAllowedRoots(roots: string[] | undefined): string[] {
217220 return [ ...expanded ] ;
218221}
219222
220- function isPathInsidePosix ( root : string , target : string ) : boolean {
221- if ( root === "/" ) {
222- return true ;
223- }
223+ function isPathInsidePolicyPath ( root : string , target : string ) : boolean {
224224 const rootKey = getSandboxHostPathPolicyKey ( root ) ;
225225 const targetKey = getSandboxHostPathPolicyKey ( target ) ;
226- return targetKey === rootKey || targetKey . startsWith ( `${ rootKey } /` ) ;
226+ if ( rootKey === "/" ) {
227+ return true ;
228+ }
229+ const rootPrefix = rootKey . endsWith ( "/" ) ? rootKey : `${ rootKey } /` ;
230+ return targetKey === rootKey || targetKey . startsWith ( rootPrefix ) ;
227231}
228232
229233function getOutsideAllowedRootsReason (
@@ -234,7 +238,7 @@ function getOutsideAllowedRootsReason(
234238 return null ;
235239 }
236240 for ( const root of allowedRoots ) {
237- if ( isPathInsidePosix ( root , sourceNormalized ) ) {
241+ if ( isPathInsidePolicyPath ( root , sourceNormalized ) ) {
238242 return null ;
239243 }
240244 }
@@ -252,7 +256,7 @@ function getReservedTargetReason(bind: string): BlockedBindReason | null {
252256 }
253257 const target = normalizeHostPath ( targetRaw ) ;
254258 for ( const reserved of RESERVED_CONTAINER_TARGET_PATHS ) {
255- if ( isPathInsidePosix ( reserved , target ) ) {
259+ if ( isPathInsidePolicyPath ( reserved , target ) ) {
256260 return {
257261 kind : "reserved_target" ,
258262 targetPath : target ,
0 commit comments