Skip to content

fix(permissions): enforce deny rules over the allow list (fixes #313)#314

Open
glitch-ux wants to merge 1 commit into
HKUDS:mainfrom
glitch-ux:fix/deny-precedence-over-allowlist
Open

fix(permissions): enforce deny rules over the allow list (fixes #313)#314
glitch-ux wants to merge 1 commit into
HKUDS:mainfrom
glitch-ux:fix/deny-precedence-over-allowlist

Conversation

@glitch-ux

@glitch-ux glitch-ux commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Problem: PermissionChecker.evaluate() returned allow for any tool in allowed_tools before it evaluated the user-configured path_rules deny-rules and denied_commands patterns. Allow-listing a broad tool such as bash or write_file therefore silently disabled the user's own deny policy — a configured denied_commands: ["*rm -rf /*"] or a /etc/* path deny-rule provided no protection once the tool was allow-listed. This is inconsistent with the rest of the checker, where deny already wins: denied_tools and the built-in sensitive-path patterns are both evaluated before the allow-list (and test_allowed_tools_does_not_bypass_sensitive_paths asserts exactly that for sensitive paths).

  • Change: Move the path deny-rule check and the denied_commands check ahead of the allowed_tools short-circuit in evaluate(), so deny consistently takes precedence over allow. Behavior is otherwise unchanged: an allow-listed tool still runs when no deny rule matches.

  • Added regression tests covering both deny paths and a control asserting the allow-list still grants a tool when no deny rule applies.

Fixes #313.

Before / after

from openharness.config.settings import PathRuleConfig, PermissionSettings
from openharness.permissions import PermissionChecker, PermissionMode

s = PermissionSettings.model_construct(
    mode=PermissionMode.DEFAULT, allowed_tools=["bash"], denied_tools=[],
    denied_commands=["*rm -rf /*"], path_rules=[],
)
PermissionChecker(s).evaluate("bash", is_read_only=False,
    command="rm -rf / --no-preserve-root").allowed
# before: True   after: False

Validation

  • uv run ruff check src tests scripts — passes
  • uv run pytest -q tests/test_permissions — 35 passed (3 new)
  • uv run pytest -q — full suite passes except two pre-existing failures unrelated to this change (test_bundled_user_invocable_skill_registers_as_slash_command, test_load_skill_registry_includes_bundled); both fail identically on a clean main.
  • cd frontend/terminal && npx tsc --noEmit — not applicable (no frontend changes)

Notes

allowed_tools short-circuited evaluate() before the path deny-rules and
denied_commands checks, so allow-listing a broad tool (e.g. bash or
write_file) silently bypassed the user's own deny policy -- a configured
denied_commands pattern or path deny-rule provided no protection once the
tool was allow-listed.

Move the path deny-rule and denied_commands checks ahead of the
allowed_tools short-circuit so deny takes precedence over allow,
consistent with denied_tools and the built-in sensitive-path patterns
(which are already evaluated before the allow list).

Add regression tests covering both deny paths plus a control that the
allow list still grants a tool when no deny rule matches.

Fixes HKUDS#313
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: allowed_tools bypasses denied_commands and path deny-rules (deny should take precedence)

1 participant