feat(policy): distinguish single- and multi-segment path wildcards
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8.7k
- Forks
- 1.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 253
Description
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/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/prefixitself 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.rsusesglob::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/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/.- No open duplicate issue was found. Closed issue #1840 concerns broader policy-envelope and narrowness checks rather than wildcard semantics.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with crates/openshell-core/src/endpoint_path.rs and its existing wildcard tests, then read crates/openshell-policy/src/ambiguity.rs to compare validation with runtime behavior. Review the policy documentation and inventory repository policies and tests that rely on * crossing /. Done means all listed consumers, validation, prover representation, docs, examples, and tests share the proposed semantics, with release notes covering the breaking change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- authorization, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 35/100