fix: permissions wildcarding so that for ex: 'ls *' includes ls * AND 'ls' to prevent having to double state commands or use 'ls*'

This commit is contained in:
Aiden Cline
2026-01-12 13:02:29 -06:00
parent 22c68a6992
commit 62702fbd11
2 changed files with 32 additions and 10 deletions

View File

@@ -2,16 +2,18 @@ import { sortBy, pipe } from "remeda"
export namespace Wildcard { export namespace Wildcard {
export function match(str: string, pattern: string) { export function match(str: string, pattern: string) {
const regex = new RegExp( let escaped = pattern
"^" + .replace(/[.+^${}()|[\]\\]/g, "\\$&") // escape special regex chars
pattern .replace(/\*/g, ".*") // * becomes .*
.replace(/[.+^${}()|[\]\\]/g, "\\$&") // escape special regex chars .replace(/\?/g, ".") // ? becomes .
.replace(/\*/g, ".*") // * becomes .*
.replace(/\?/g, ".") + // ? becomes . // If pattern ends with " *" (space + wildcard), make the trailing part optional
"$", // This allows "ls *" to match both "ls" and "ls -la"
"s", // s flag enables multiline matching if (escaped.endsWith(" .*")) {
) escaped = escaped.slice(0, -3) + "( .*)?"
return regex.test(str) }
return new RegExp("^" + escaped + "$", "s").test(str)
} }
export function all(input: string, patterns: Record<string, any>) { export function all(input: string, patterns: Record<string, any>) {

View File

@@ -7,6 +7,26 @@ test("match handles glob tokens", () => {
expect(Wildcard.match("foo+bar", "foo+bar")).toBe(true) expect(Wildcard.match("foo+bar", "foo+bar")).toBe(true)
}) })
test("match with trailing space+wildcard matches command with or without args", () => {
// "ls *" should match "ls" (no args) and "ls -la" (with args)
expect(Wildcard.match("ls", "ls *")).toBe(true)
expect(Wildcard.match("ls -la", "ls *")).toBe(true)
expect(Wildcard.match("ls foo bar", "ls *")).toBe(true)
// "ls*" (no space) should NOT match "ls" alone — wait, it should because .* matches empty
// but it WILL match "lstmeval" which is the dangerous case users should avoid
expect(Wildcard.match("ls", "ls*")).toBe(true)
expect(Wildcard.match("lstmeval", "ls*")).toBe(true)
// "ls *" (with space) should NOT match "lstmeval"
expect(Wildcard.match("lstmeval", "ls *")).toBe(false)
// multi-word commands
expect(Wildcard.match("git status", "git *")).toBe(true)
expect(Wildcard.match("git", "git *")).toBe(true)
expect(Wildcard.match("git commit -m foo", "git *")).toBe(true)
})
test("all picks the most specific pattern", () => { test("all picks the most specific pattern", () => {
const rules = { const rules = {
"*": "deny", "*": "deny",