feat(policy): support * wildcards in permission function patterns#187
Conversation
Function patterns in iii-permissions.yaml may now contain `*`, which matches any substring. A pattern with no `*` still matches exactly, so existing rules are unchanged. - compileFunctionMatcher turns a pattern containing `*` into an anchored regex (`^...$`): `*` becomes `.*` and every other regex metacharacter is escaped, so `*` is the only wildcard. - matchFunctionId resolves a rule against a concrete function_id via the glob when present, else exact equality. - check() routes through matchFunctionId; arg constraints still AND-compose with globbed functions. Adversarial tests cover anchoring (no prefix/suffix injection), metacharacter escaping, suffix-position globs, deny globs over hostile args, and that a newline in a function_id fails closed to needs_approval rather than tunneling past a deny into a catch-all.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Your plan includes 1 review of capacity. Refill in 1 minute and 29 seconds. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more review capacity refills, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (6)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
skill-check — worker0 verified, 12 skipped (no docs/).
Three for three. Nicely done. |
Add a Wildcards note to the architecture Kernel deny list section covering namespace globs (shell::*, *::list, catch-all, !state::*), anchoring, and arg-constraint composition. Update the compile.ts source-layout row to mention matchFunctionId.
Summary
Permission rules in
iii-permissions.yamlcan now use*in the functionpattern to match any substring. Patterns without
*keep matching exactly,so every existing rule behaves identically.
This unlocks namespace-scoped rules:
Globs also compose with the existing constrained form:
How it works
compileFunctionMatcher(harness/src/harness/policy/compile.ts) turns apattern containing
*into an anchored regex (^...$).*becomes.*;every other regex metacharacter is escaped, so
*is the only wildcard.A pattern with no
*compiles toglob: nulland matches by===.matchFunctionIdresolves a rule against a concretefunction_idvia theglob when present, else exact equality.
Permissions.checkroutes throughmatchFunctionId; arg constraints stillAND-compose with a globbed function.
The engine remains fail-closed: anything not positively matched to an
allow/deny rule resolves to
needs_approval.Tests
harness/tests/harness/policy.test.ts— 50 passing, full harness suite 902/0.New adversarial coverage:
Xshell::exec,shellexec,shelldo notsatisfy
shell::*.*is a wildcard —.and other metacharacters match literally(
a.c::*does not matchaXc::ping).*::listrejectsmodels::listing.dodged by appending levels.
function_idfails closed toneeds_approvalinstead oftunneling past a deny glob into a catch-all allow.
Known limitation
A single pattern with multiple
*(e.g.a*b*c*) compiles to multiple.*groups. Patterns are author-controlled (not attacker input) and the common
forms (
ns::*,*::leaf) are single-*and linear, so this is a rule-authorfootgun rather than an exploitable surface.
Test plan
pnpm typecheckcleanpnpm vitest run— 902 passing, 0 failingpnpm vitest run policy— 50 passing, 0 failing