From 135400fa268a1d433e15bd8a33ce88767ec86f9c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:42:13 +0000 Subject: [PATCH 1/3] Initial plan From f0b9f67b531b955f5cf9b552edad885fc409fda8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:46:54 +0000 Subject: [PATCH 2/3] rust-guard: add create_agent_task test and use Cow::Owned in project arms --- .../github-guard/rust-guard/src/labels/mod.rs | 24 +++++++++++++++++++ .../rust-guard/src/labels/tool_rules.rs | 4 ++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/guards/github-guard/rust-guard/src/labels/mod.rs b/guards/github-guard/rust-guard/src/labels/mod.rs index 8a4508680..a1eef9e78 100644 --- a/guards/github-guard/rust-guard/src/labels/mod.rs +++ b/guards/github-guard/rust-guard/src/labels/mod.rs @@ -5877,6 +5877,30 @@ mod tests { ); } + #[test] + fn test_apply_tool_labels_create_agent_task_secrecy_is_repo_scoped() { + // create_agent_task is blocked via is_blocked_tool(), so integrity will be overridden + // to blocked_integrity in label_resource. This test verifies the secrecy assignment + // before that override: for no owner/repo it should stay empty. + let ctx = default_ctx(); + let tool_args = json!({ "owner": "", "repo": "" }); + + let (secrecy, _integrity, _desc) = apply_tool_labels( + "create_agent_task", + &tool_args, + "", + vec![], + vec![], + String::new(), + &ctx, + ); + + assert!( + secrecy.is_empty(), + "create_agent_task without owner/repo should have empty secrecy (no repo-visibility lookup possible)" + ); + } + #[test] fn test_apply_tool_labels_enable_toolset_public_secrecy_writer_integrity() { let ctx = default_ctx(); diff --git a/guards/github-guard/rust-guard/src/labels/tool_rules.rs b/guards/github-guard/rust-guard/src/labels/tool_rules.rs index 2c4743daf..c938f137c 100644 --- a/guards/github-guard/rust-guard/src/labels/tool_rules.rs +++ b/guards/github-guard/rust-guard/src/labels/tool_rules.rs @@ -536,7 +536,7 @@ pub fn apply_tool_labels( // S = empty by default (public project); per-item secrecy for items is refined in // label_response_paths for list_project_items if !owner.is_empty() { - baseline_scope = Cow::Borrowed(owner.as_str()); + baseline_scope = Cow::Owned(owner); integrity = writer_integrity(&baseline_scope, ctx); } } @@ -740,7 +740,7 @@ pub fn apply_tool_labels( // Projects are org-scoped; write responses carry the same labels as reads. // I = approved: if !owner.is_empty() { - baseline_scope = Cow::Borrowed(owner.as_str()); + baseline_scope = Cow::Owned(owner); integrity = writer_integrity(&baseline_scope, ctx); } } From 966fda5c916ca4d65475c17e4a6158f15aeb6c68 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Jul 2026 15:05:46 +0000 Subject: [PATCH 3/3] rust-guard: strengthen create_agent_task test with deterministic private-repo visibility --- .../github-guard/rust-guard/src/labels/mod.rs | 46 +++++++++++++++---- 1 file changed, 38 insertions(+), 8 deletions(-) diff --git a/guards/github-guard/rust-guard/src/labels/mod.rs b/guards/github-guard/rust-guard/src/labels/mod.rs index a1eef9e78..f71dc116c 100644 --- a/guards/github-guard/rust-guard/src/labels/mod.rs +++ b/guards/github-guard/rust-guard/src/labels/mod.rs @@ -5879,25 +5879,55 @@ mod tests { #[test] fn test_apply_tool_labels_create_agent_task_secrecy_is_repo_scoped() { - // create_agent_task is blocked via is_blocked_tool(), so integrity will be overridden - // to blocked_integrity in label_resource. This test verifies the secrecy assignment - // before that override: for no owner/repo it should stay empty. + // create_agent_task is blocked via is_blocked_tool(); integrity is overridden to + // blocked_integrity in label_resource. This test verifies the secrecy assignment + // that occurs before that override: with a known-private repo the arm must produce + // the private scope label, distinguishing it from the no-op default path. + // + // Use an owner/repo that no other test references to avoid polluting the shared + // visibility cache. + let owner = "create-agent-task-owner"; + let repo = "create-agent-task-repo"; + let repo_id = "create-agent-task-owner/create-agent-task-repo"; + + // Pre-populate the repo visibility cache so apply_repo_visibility_secrecy receives + // Some(true) (private) without needing a live backend. + fn private_repo_callback( + tool: &str, + _args: &str, + buffer: &mut [u8], + ) -> Result { + if tool != "search_repositories" { + return Err(-1); + } + let payload = serde_json::json!({ + "items": [{"full_name": "create-agent-task-owner/create-agent-task-repo", "private": true}] + }) + .to_string(); + let bytes = payload.as_bytes(); + buffer[..bytes.len()].copy_from_slice(bytes); + Ok(bytes.len()) + } + let _ = super::backend::is_repo_private_with_callback(private_repo_callback, owner, repo); + let ctx = default_ctx(); - let tool_args = json!({ "owner": "", "repo": "" }); + let tool_args = json!({ "owner": owner, "repo": repo }); let (secrecy, _integrity, _desc) = apply_tool_labels( "create_agent_task", &tool_args, - "", + repo_id, vec![], vec![], String::new(), &ctx, ); - assert!( - secrecy.is_empty(), - "create_agent_task without owner/repo should have empty secrecy (no repo-visibility lookup possible)" + let expected = super::helpers::policy_private_scope_label(owner, repo, repo_id, &ctx); + assert_eq!( + secrecy, + expected, + "create_agent_task with a private repo must carry the private repo secrecy label" ); }