Category: security Severity: major
Location: src/Arcp.Runtime/Leases/LeaseManager.cs:154-158
Spec: ARCP v1.1 §9.2, §9.3
What
GlobMatch handles a "…/**" pattern by stripping the last three characters (/**), which removes the trailing path-separator boundary, then does a bare StartsWith. A lease grant of fs.read: ["/workspace/myapp/**"] therefore authorizes any path that merely begins with the string /workspace/myapp, including sibling directories like /workspace/myapp-private/secrets or /workspace/myapp.bak. This is an over-broad authorization / path-confusion vulnerability: the enforcement boundary (§9.3 "MUST be covered by a capability") is wider than the operator intended.
Evidence
if (pattern.EndsWith("/**", StringComparison.Ordinal))
{
var prefix = pattern[..^3]; // "/workspace/myapp/**" -> "/workspace/myapp"
return input.StartsWith(prefix, StringComparison.Ordinal); // matches "/workspace/myapp-private/x"
}
For pattern "/workspace/myapp/**", prefix == "/workspace/myapp" (no trailing /), so GlobMatch("/workspace/myapp-private/secret", "/workspace/myapp/**") returns true.
Proposed fix
In LeaseManager.GlobMatch, for the "/**" case strip only ** (keep the separator) and require the boundary:
if (pattern.EndsWith("/**", StringComparison.Ordinal))
{
var dir = pattern[..^2]; // keep trailing "/": "/workspace/myapp/"
return input.StartsWith(dir, StringComparison.Ordinal)
|| input.Equals(dir[..^1], StringComparison.Ordinal); // allow the dir itself
}
Add unit tests asserting "/workspace/myapp/**" matches /workspace/myapp/a and /workspace/myapp but not /workspace/myapp-private/x.
Acceptance criteria
Category: security Severity: major
Location:
src/Arcp.Runtime/Leases/LeaseManager.cs:154-158Spec: ARCP v1.1 §9.2, §9.3
What
GlobMatchhandles a"…/**"pattern by stripping the last three characters (/**), which removes the trailing path-separator boundary, then does a bareStartsWith. A lease grant offs.read: ["/workspace/myapp/**"]therefore authorizes any path that merely begins with the string/workspace/myapp, including sibling directories like/workspace/myapp-private/secretsor/workspace/myapp.bak. This is an over-broad authorization / path-confusion vulnerability: the enforcement boundary (§9.3 "MUST be covered by a capability") is wider than the operator intended.Evidence
For pattern
"/workspace/myapp/**",prefix == "/workspace/myapp"(no trailing/), soGlobMatch("/workspace/myapp-private/secret", "/workspace/myapp/**")returnstrue.Proposed fix
In
LeaseManager.GlobMatch, for the"/**"case strip only**(keep the separator) and require the boundary:Add unit tests asserting
"/workspace/myapp/**"matches/workspace/myapp/aand/workspace/myappbut not/workspace/myapp-private/x.Acceptance criteria
GlobMatch("/workspace/myapp-private/secret", "/workspace/myapp/**")returnsfalse.GlobMatch("/workspace/myapp/src/a.cs", "/workspace/myapp/**")returnstrue.