Skip to content

[Repo Assist] refactor(rust-guard): extract is_any_trusted_actor helper and collapse URL fallback loop#4260

Merged
lpcox merged 2 commits intomainfrom
repo-assist/fix-issue-4252-rust-guard-trusted-actor-url-loop-be9d08bbcb5c1877
Apr 21, 2026
Merged

[Repo Assist] refactor(rust-guard): extract is_any_trusted_actor helper and collapse URL fallback loop#4260
lpcox merged 2 commits intomainfrom
repo-assist/fix-issue-4252-rust-guard-trusted-actor-url-loop-be9d08bbcb5c1877

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This is an automated pull request from Repo Assist.

Closes #4252

Root Cause

Two minor duplication issues in guards/github-guard/rust-guard/src/labels/:

  1. The three-predicate trust check is_trusted_first_party_bot(x) || is_configured_trusted_bot(x, ctx) || is_trusted_user(x, ctx) was copy-pasted verbatim at three call sites (helpers.rs:1282–1284, helpers.rs:1479–1481, tool_rules.rs:98–100). Adding a fourth trust tier would require three matching edits.

  2. extract_repo_from_item had three structurally identical if let blocks differing only in the JSON field name (repository_url, html_url, url). The same for-loop idiom is already used in extract_number_from_url in the same file.

Fix

helpers.rs

  • Added is_any_trusted_actor(username, ctx) — a single helper that combines the three predicates with a docstring explaining its semantics.
  • Replaced both call sites in helpers.rs with one-liner is_any_trusted_actor calls.
  • Collapsed the three repeated if let URL-field blocks in extract_repo_from_item into a for field in &[...] loop (same pattern as extract_number_from_url).

tool_rules.rs

  • Replaced the third call site with is_any_trusted_actor.
  • Updated the import to use is_any_trusted_actor instead of the three individual functions.

Trade-offs

  • Purely mechanical refactor; zero semantic change.
  • is_any_trusted_actor is pub(crate) — callable within the crate but not exported.

Test Status

  • cargo build — compiles without warnings
  • cargo test317 / 317 tests pass
  • ⚠️ Go build/test skipped — proxy.golang.org blocked by network firewall (pre-existing infrastructure limitation, unrelated to this change)

Warning

⚠️ Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • proxy.golang.org

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "proxy.golang.org"

See Network Configuration for more information.

Generated by Repo Assist · ● 4.8M ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@851905c06e905bf362a9f6cc54f912e3df747d55

…e URL fallback loop

- Add is_any_trusted_actor(username, ctx) helper combining the three
  constituent trust predicates (first-party bot, configured bot,
  trusted user); replaces copy-pasted triple-OR at three call sites in
  helpers.rs and tool_rules.rs
- Replace three structurally identical if-let blocks in
  extract_repo_from_item with a for-field loop over
  ["repository_url", "html_url", "url"], matching the idiom already
  used in extract_number_from_url

All 317 Rust guard tests pass.

Closes #4252

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lpcox lpcox marked this pull request as ready for review April 21, 2026 14:22
Copilot AI review requested due to automatic review settings April 21, 2026 14:22
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors the Rust GitHub guard labeling logic to reduce duplication by centralizing the “trusted actor” predicate and simplifying repeated URL-field fallback extraction.

Changes:

  • Adds is_any_trusted_actor(username, ctx) helper and replaces repeated three-way OR checks with a single call.
  • Collapses repeated URL-field parsing in extract_repo_from_item into a loop over candidate fields.
  • Updates tool_rules.rs imports/call site to use the new helper.
Show a summary per file
File Description
guards/github-guard/rust-guard/src/labels/helpers.rs Introduces is_any_trusted_actor and deduplicates URL fallback logic in extract_repo_from_item.
guards/github-guard/rust-guard/src/labels/tool_rules.rs Switches trusted-actor elevation logic to the new helper and updates imports accordingly.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

Comment on lines +976 to 983
// URL field fallback (repository_url for search results, html_url / url as generic fallbacks)
for field in &["repository_url", "html_url", "url"] {
if let Some(url) = item.get(*field).and_then(|v| v.as_str()) {
if let Some(repo_id) = extract_repo_from_github_url(url) {
return repo_id;
}
}
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

extract_repo_from_item now clearly falls back across repository_url, html_url, and url, but the function-level doc comment above still describes only html_url parsing. Please update the doc comment to match the actual fallback fields/order (and consider matching the existing extract_number_from_url loop style by avoiding the unnecessary *field deref for consistency).

Copilot uses AI. Check for mistakes.
Comment on lines +1757 to +1763
/// Returns `true` if `username` belongs to any trusted actor tier:
/// first-party bots, gateway-configured bots, or trusted users.
pub(crate) fn is_any_trusted_actor(username: &str, ctx: &PolicyContext) -> bool {
is_trusted_first_party_bot(username)
|| is_configured_trusted_bot(username, ctx)
|| is_trusted_user(username, ctx)
}
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

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

is_any_trusted_actor is a new helper that centralizes a security-relevant trust decision and is now used at multiple call sites. Please add a small unit test covering the three tiers (first-party bot, configured trusted bot, trusted user) and a negative case to lock in the intended semantics and catch future omissions when new trust tiers are added.

Copilot uses AI. Check for mistakes.
@lpcox
Copy link
Copy Markdown
Collaborator

lpcox commented Apr 21, 2026

@copilot address the review feedback #4260 (review)

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

@copilot address the review feedback #4260 (review)

Addressed in 761545c. I updated the extract_repo_from_item doc comment to reflect repository_url -> html_url -> url fallback order, removed the unnecessary *field deref for loop consistency, and added test_is_any_trusted_actor_tiers_and_negative covering first-party bot, configured trusted bot, trusted user, and a negative case. No UI changes in this PR.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • example.com
    • Triggering command: /tmp/go-build2438555630/b509/launcher.test /tmp/go-build2438555630/b509/launcher.test -test.testlogfile=/tmp/go-build2438555630/b509/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true rotocol/go-sdk@v1.5.0/oauthex/auth_meta.go rotocol/go-sdk@v1.5.0/oauthex/client.go x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet -E g_.a -quiet x_amd64/vet /opt/hostedtoolc/opt/hostedtoolcache/go/1.25.9/x64/pkg/tool/linux_amd64/vet go-sdk/auth /tmp/go-build409-bool x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build3466621193/b513/launcher.test /tmp/go-build3466621193/b513/launcher.test -test.testlogfile=/tmp/go-build3466621193/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s -uns�� /tmp/go-build409--error-format=json 64/pkg/include x_amd64/vet 0/clients.go 437e.build_scrippush 437e.f3itfh70g07-v 6tSWDqXY8YrZ (dns block)
  • invalid-host-that-does-not-exist-12345.com
    • Triggering command: /tmp/go-build2438555630/b491/config.test /tmp/go-build2438555630/b491/config.test -test.testlogfile=/tmp/go-build2438555630/b491/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true /http/httpguts/g-errorsas /http/httpguts/h-ifaceassert x_amd64/vet --gdwarf-5 ing/prototext lcache/go/1.25.9-unreachable=false x_amd64/vet 7423�� g_.a -I x_amd64/vet --gdwarf-5 mmon -o x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build3466621193/b495/config.test /tmp/go-build3466621193/b495/config.test -test.testlogfile=/tmp/go-build3466621193/b495/testlog.txt -test.paniconexit0 -test.timeout=10m0s 7423�� /tmp/go-build409/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/degit -goversion -guard/target/debug/build/quote-e2b702800175437e/build-script-build -c=4 -nolocalimports -importcfg -guard/target/de-plugin /tmp�� /home/REDACTED/go/-plugin-opt=/usr/libexec/gcc/x86_64-linux-gnu/13/lto-wrapper .cfg x_amd64/link 64/src/runtime/cgit 437e.build_scrippush 437e.f3itfh70g07-v x_amd64/link (dns block)
  • nonexistent.local
    • Triggering command: /tmp/go-build2438555630/b509/launcher.test /tmp/go-build2438555630/b509/launcher.test -test.testlogfile=/tmp/go-build2438555630/b509/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true rotocol/go-sdk@v1.5.0/oauthex/auth_meta.go rotocol/go-sdk@v1.5.0/oauthex/client.go x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet -E g_.a -quiet x_amd64/vet /opt/hostedtoolc/opt/hostedtoolcache/go/1.25.9/x64/pkg/tool/linux_amd64/vet go-sdk/auth /tmp/go-build409-bool x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build3466621193/b513/launcher.test /tmp/go-build3466621193/b513/launcher.test -test.testlogfile=/tmp/go-build3466621193/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s -uns�� /tmp/go-build409--error-format=json 64/pkg/include x_amd64/vet 0/clients.go 437e.build_scrippush 437e.f3itfh70g07-v 6tSWDqXY8YrZ (dns block)
  • slow.example.com
    • Triggering command: /tmp/go-build2438555630/b509/launcher.test /tmp/go-build2438555630/b509/launcher.test -test.testlogfile=/tmp/go-build2438555630/b509/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true rotocol/go-sdk@v1.5.0/oauthex/auth_meta.go rotocol/go-sdk@v1.5.0/oauthex/client.go x_amd64/vet --gdwarf-5 --64 -o x_amd64/vet -E g_.a -quiet x_amd64/vet /opt/hostedtoolc/opt/hostedtoolcache/go/1.25.9/x64/pkg/tool/linux_amd64/vet go-sdk/auth /tmp/go-build409-bool x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build3466621193/b513/launcher.test /tmp/go-build3466621193/b513/launcher.test -test.testlogfile=/tmp/go-build3466621193/b513/testlog.txt -test.paniconexit0 -test.timeout=10m0s -uns�� /tmp/go-build409--error-format=json 64/pkg/include x_amd64/vet 0/clients.go 437e.build_scrippush 437e.f3itfh70g07-v 6tSWDqXY8YrZ (dns block)
  • this-host-does-not-exist-12345.com
    • Triggering command: /tmp/go-build2438555630/b518/mcp.test /tmp/go-build2438555630/b518/mcp.test -test.testlogfile=/tmp/go-build2438555630/b518/testlog.txt -test.paniconexit0 -test.timeout=10m0s -test.v=true om/modelcontextp-errorsas om/modelcontextp-ifaceassert x_amd64/vet --gdwarf-5 .io/proto/otlp/r--version -o x_amd64/vet .cfg�� 7423812/b464/_pkg_.a -I x_amd64/vet --gdwarf-5 th2/internal -o x_amd64/vet (dns block)
    • Triggering command: /tmp/go-build3466621193/b522/mcp.test /tmp/go-build3466621193/b522/mcp.test -test.testlogfile=/tmp/go-build3466621193/b522/testlog.txt -test.paniconexit0 -test.timeout=10m0s lib/�� lib/rustlib/x86_/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/de/usr/libexec/docker/docker-init lib/rustlib/x86_/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/de--version lib/rustlib/x86_/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/debug/deps/github_guard-57d41235e07a5585.3ky4jndxwogptk4p3m4cqblia.0un6r9c.rcgu.o lib/rustlib/x86_/usr/libexec/docker/cli-plugins/docker-compose lib/rustlib/x86_docker-cli-plugin-metadata lib/rustlib/x86_/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/debug/deps/github_guard-57d41235e07a5585.3r7b32ab9hw1mmy6a1aekmmsh.0un6r9c.rcgu.o lib/rustlib/x86_/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/debug/deps/github_guard-57d41235e07a5585.485oswk5h4p2kq4dabhq5b2ke.0un6r9c.rcgu.o lib/�� lib/rustlib/x86_64-REDACTED-linux-gnu/lib/libminiz_oxide-2b6a8d2f6e1dc71b.rlib lib/rustlib/x86_64-REDACTED-linux-gnu/lib/libadler2-39ffdbc27c978ccc.rlib ache/go/1.25.9/x64/pkg/tool/linu/home/REDACTED/.rustup/toolchains/stable-x86_64-REDACTED-linux-gnu/--version c1063f.rlib cd07254-bbdd-493--version x_amd64/compile ache/go/1.25.9/x64/pkg/tool/linu/home/REDACTED/work/gh-aw-mcpg/gh-aw-mcpg/guards/github-guard/rust-guard/target/debug/deps/github_guard-57d41235e07a5585.0r6f2y9pmz8tylr32cgwnziux.0un6r9c.rcgu.o (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Copilot AI requested a review from lpcox April 21, 2026 18:20
@lpcox lpcox merged commit 6b4e51d into main Apr 21, 2026
16 checks passed
@lpcox lpcox deleted the repo-assist/fix-issue-4252-rust-guard-trusted-actor-url-loop-be9d08bbcb5c1877 branch April 21, 2026 18:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[rust-guard] Rust Guard: Extract is_any_trusted_actor helper and collapse URL fallback loop

3 participants