You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
OpenShell currently evaluates path globs with separator-insensitive matching. Both * and ** may consume /, so patterns such as /v1/* and /v1/** overlap more than operators commonly expect. A trailing /** has a special subtree behavior—it also matches the named path itself—but otherwise the two wildcard forms are largely redundant.
This is surprising for profile and policy authors. Common routing conventions treat * as a wildcard within one path component and ** as a recursive wildcard across components. The current behavior makes it easy for /v1/* to authorize /v1/admin/secrets unintentionally.
This came up while reviewing static credential endpoint binding in PR #2510, particularly this discussion. It should be addressed as a deliberate policy-language change rather than changing credential bindings alone.
Proposed Design
Define one shared path-glob contract across all network-policy consumers:
* matches zero or more characters within one path component and never consumes /.
** matches zero or more characters across path components.
? and bracket classes remain component-local and retain their documented character-matching behavior.
A trailing /prefix/** continues to match /prefix itself as well as all descendants.
Request paths remain canonicalized before any policy or credential-binding match.
Apply the contract consistently to:
L7 endpoint selection
REST and WebSocket allow/deny rules
Static credential endpoint bindings
Ambiguity and overlap validation
Any policy prover representation of path globs
The runtime matcher, ambiguity validator, documentation, examples, and tests must all use the same semantics. Because OpenShell is currently alpha, treat this as an intentional breaking policy-language correction and call it out in release notes. Before implementation, inventory repository policies and tests that rely on * crossing / and rewrite them to use ** where recursive matching is intended.
Representative acceptance cases:
Pattern
Path
Result
/v1/*
/v1/chat
match
/v1/*
/v1/chat/messages
no match
/v1/**
/v1
match
/v1/**
/v1/chat/messages
match
/repos/*/issues
/repos/acme/issues
match
/repos/*/issues
/repos/acme/private/issues
no match
/**/info/refs*
/org/repo/info/refs
match
Alternatives Considered
Keep the current semantics. This preserves compatibility but leaves * and ** mostly redundant and retains a surprising authorization boundary.
Change only static credential bindings. This would make credential paths safer in isolation, but operators would have to understand two incompatible path languages in the same policy/profile workflow.
Introduce a new wildcard token. This avoids changing existing patterns but adds more syntax when the conventional */** distinction already expresses the intended model.
Agent Investigation
crates/openshell-core/src/endpoint_path.rs uses glob::Pattern::matches, where separators are not treated specially, and explicitly tests that /v1/* matches /v1/chat/messages.
The same matcher special-cases trailing /** so /v1/** matches both /v1 and its descendants.
crates/openshell-policy/src/ambiguity.rs models both * and ** as delimiter-crossing wildcard tokens to mirror runtime behavior.
docs/sandboxes/policies.mdx and docs/reference/policy-schema.mdx explicitly document that both wildcard forms may cross /.
Problem Statement
OpenShell currently evaluates path globs with separator-insensitive matching. Both
*and**may consume/, so patterns such as/v1/*and/v1/**overlap more than operators commonly expect. A trailing/**has a special subtree behavior—it also matches the named path itself—but otherwise the two wildcard forms are largely redundant.This is surprising for profile and policy authors. Common routing conventions treat
*as a wildcard within one path component and**as a recursive wildcard across components. The current behavior makes it easy for/v1/*to authorize/v1/admin/secretsunintentionally.This came up while reviewing static credential endpoint binding in PR #2510, particularly this discussion. It should be addressed as a deliberate policy-language change rather than changing credential bindings alone.
Proposed Design
Define one shared path-glob contract across all network-policy consumers:
*matches zero or more characters within one path component and never consumes/.**matches zero or more characters across path components.?and bracket classes remain component-local and retain their documented character-matching behavior./prefix/**continues to match/prefixitself as well as all descendants.Apply the contract consistently to:
The runtime matcher, ambiguity validator, documentation, examples, and tests must all use the same semantics. Because OpenShell is currently alpha, treat this as an intentional breaking policy-language correction and call it out in release notes. Before implementation, inventory repository policies and tests that rely on
*crossing/and rewrite them to use**where recursive matching is intended.Representative acceptance cases:
/v1/*/v1/chat/v1/*/v1/chat/messages/v1/**/v1/v1/**/v1/chat/messages/repos/*/issues/repos/acme/issues/repos/*/issues/repos/acme/private/issues/**/info/refs*/org/repo/info/refsAlternatives Considered
*and**mostly redundant and retains a surprising authorization boundary.*/**distinction already expresses the intended model.Agent Investigation
crates/openshell-core/src/endpoint_path.rsusesglob::Pattern::matches, where separators are not treated specially, and explicitly tests that/v1/*matches/v1/chat/messages./**so/v1/**matches both/v1and its descendants.crates/openshell-policy/src/ambiguity.rsmodels both*and**as delimiter-crossing wildcard tokens to mirror runtime behavior.docs/sandboxes/policies.mdxanddocs/reference/policy-schema.mdxexplicitly document that both wildcard forms may cross/.