Skip to content

fix(permissions): match rule patterns against url and fail closed - #563

Merged
emal-avala merged 3 commits into
mainfrom
fix/permission-url-pattern
Jul 29, 2026
Merged

fix(permissions): match rule patterns against url and fail closed#563
emal-avala merged 3 commits into
mainfrom
fix/permission-url-pattern

Conversation

@emal-avala

Copy link
Copy Markdown
Member

Summary

  • matches_input_pattern only inspected command / file_path / pattern and fell back to glob_match(pattern, ""). WebFetch (subject field url) never matched a literal pattern, so a configured deny rule loaded, evaluated, and silently failed open.
  • Match any present subject field: file_path, url, path, pattern, query, prompt.
  • When none of those fields are present, fail closed: allow does not grant; deny / ask still apply. Pure * patterns still mean any input.
  • Docs: WebFetch deny example and field list.

Fixes #554.

Test plan

  • cargo check --all-targets
  • cargo test --all-targets (only known host bwrap_* failures)
  • cargo clippy --all-targets -- -D warnings
  • cargo fmt --all -- --check
  • New tests: URL deny/allow, Grep path-or-pattern, no-comparable-field fail-closed, universal *
  • Mutation: restore original empty-string path → a_deny_rule_on_url_blocks_matching_webfetch fails with "must block a matching fetch"; drop fail-closed → no_comparable_field_fails_closed fails as expected

@mintlify

mintlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
agentcode 🟢 Ready View Preview Jul 29, 2026, 5:42 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e32ead3a00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/lib/src/permissions/mod.rs Outdated
Comment on lines +502 to +506
for key in PATTERN_INPUT_FIELDS {
if let Some(value) = input.get(*key).and_then(|v| v.as_str()) {
saw_comparable = true;
if glob_match(pattern, value) {
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict WebFetch patterns to the URL field

With a default-deny configuration and an allow rule such as WebFetch: https://docs.example.com/*, a valid call can set url to an untrusted destination and the optional prompt to https://docs.example.com/guide; because any listed field may satisfy the pattern, the prompt match returns Allow for the unrelated URL. This bypasses the destination restriction the new URL rule is meant to enforce, so comparable fields need to be selected per tool (in particular, WebFetch rules must match url, not prompt).

AGENTS.md reference: AGENTS.md:L194-L194

Useful? React with 👍 / 👎.

@emal-avala

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e32ead3a00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/lib/src/permissions/mod.rs Outdated
Comment on lines +502 to +506
for key in PATTERN_INPUT_FIELDS {
if let Some(value) = input.get(*key).and_then(|v| v.as_str()) {
saw_comparable = true;
if glob_match(pattern, value) {
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Match WebFetch allow rules only against the URL

With a patterned WebFetch allow rule and a restrictive default, this any-field match lets the optional prompt satisfy the rule even when url does not; for example, {"url":"https://evil.example/","prompt":"https://docs.example.com/guide"} is allowed by the new https://docs.example.com/* rule. WebFetchTool::call ignores prompt and fetches the disallowed URL, so auxiliary fields must not authorize the URL subject.

AGENTS.md reference: AGENTS.md:L194-L194

Useful? React with 👍 / 👎.

Comment thread crates/lib/src/permissions/mod.rs Outdated
/// branch below rather than a silent empty-string match.
const PATTERN_INPUT_FIELDS: &[&str] = &[
"file_path", // FileRead / FileWrite / FileEdit / MultiEdit / NotebookEdit
"url", // WebFetch

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Recheck WebFetch permission rules after redirects

When a permitted public URL redirects, only the original input URL is matched here, while WebFetchTool::call configures reqwest::redirect::Policy::limited(10) and follows the new target without another permission check. Consequently, an allowed host with an open redirect can bypass a restrictive default, and a public URL can redirect into a host covered by the documented deny rule; redirects must be disabled or each destination must be checked before following it.

AGENTS.md reference: AGENTS.md:L194-L194

Useful? React with 👍 / 👎.

matches_input_pattern only inspected command/file_path/pattern and fell
back to glob_match against "". WebFetch (and any other tool whose subject
is not those three keys) never matched a literal pattern, so a deny rule
on a URL loaded and evaluated but silently did nothing.

Match any present subject field (file_path, url, path, pattern, query,
prompt). When none are present, fail closed: allow does not grant, deny
and ask still apply.
WebFetch allow rules must compare url only so a crafted prompt cannot
satisfy a docs-site pattern. Scope other tools similarly and fail closed
when no comparable field exists.
@emal-avala
emal-avala force-pushed the fix/permission-url-pattern branch from f66d6b8 to 1d1b05e Compare July 29, 2026 07:49
@emal-avala
emal-avala merged commit 5da3c90 into main Jul 29, 2026
13 checks passed
@emal-avala
emal-avala deleted the fix/permission-url-pattern branch July 29, 2026 07:49
@emal-avala emal-avala mentioned this pull request Jul 29, 2026
7 tasks
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.

Permission rules targeting a URL silently never match — deny rules fail open

1 participant