diff --git a/lib/host-permissions.ts b/lib/host-permissions.ts index 703f7318..6dc2cc78 100644 --- a/lib/host-permissions.ts +++ b/lib/host-permissions.ts @@ -15,6 +15,20 @@ type PermissionRule = { action: PermissionAction } +const findLastMatchingRule = ( + rules: PermissionRule[], + predicate: (rule: PermissionRule) => boolean, +): PermissionRule | undefined => { + for (let index = rules.length - 1; index >= 0; index -= 1) { + const rule = rules[index] + if (rule && predicate(rule)) { + return rule + } + } + + return undefined +} + const wildcardMatch = (value: string, pattern: string): boolean => { const normalizedValue = value.replaceAll("\\", "/") let escaped = pattern @@ -55,7 +69,7 @@ const getPermissionRules = (permissionConfigs: PermissionConfig[]): PermissionRu } export const compressDisabledByOpencode = (...permissionConfigs: PermissionConfig[]): boolean => { - const match = getPermissionRules(permissionConfigs).findLast((rule) => + const match = findLastMatchingRule(getPermissionRules(permissionConfigs), (rule) => wildcardMatch("compress", rule.permission), ) @@ -83,5 +97,5 @@ export const hasExplicitToolPermission = ( permissionConfig: PermissionConfig, tool: string, ): boolean => { - return permissionConfig ? Object.hasOwn(permissionConfig, tool) : false + return permissionConfig ? Object.prototype.hasOwnProperty.call(permissionConfig, tool) : false } diff --git a/tests/host-permissions.test.ts b/tests/host-permissions.test.ts index 9e704733..81b84e42 100644 --- a/tests/host-permissions.test.ts +++ b/tests/host-permissions.test.ts @@ -67,7 +67,38 @@ test("pattern-specific denies do not disable the whole tool", () => { ) }) +test("compress permission resolution works without Array.findLast", () => { + const originalFindLast = Array.prototype.findLast + + try { + delete (Array.prototype as Array & { findLast?: unknown }).findLast + + assert.equal( + compressDisabledByOpencode({ + "*": "deny", + compress: "allow", + }), + false, + ) + } finally { + Array.prototype.findLast = originalFindLast + } +}) + test("explicit compress permissions are detected", () => { assert.equal(hasExplicitToolPermission({ compress: "ask" }, "compress"), true) assert.equal(hasExplicitToolPermission({ "*": "deny" }, "compress"), false) }) + +test("explicit permission detection works without Object.hasOwn", () => { + const originalHasOwn = Object.hasOwn + + try { + delete (Object as typeof Object & { hasOwn?: unknown }).hasOwn + + assert.equal(hasExplicitToolPermission({ compress: "ask" }, "compress"), true) + assert.equal(hasExplicitToolPermission({ "*": "deny" }, "compress"), false) + } finally { + Object.hasOwn = originalHasOwn + } +})