-
Notifications
You must be signed in to change notification settings - Fork 20
[guard-coverage] Guard coverage gap: 30 write operations in tool_rules.rs lack explicit DIFC labeling rules #2867
Description
Summary
The guard's DIFC classification in tools.rs is fully up-to-date — all 80 current tools from github-mcp-server are correctly classified as read, write, or read-write. However, 30 write/mutating tools have no explicit match arm in apply_tool_labels in tool_rules.rs, meaning their responses fall through to the default handler (_ => {}). This causes the responses from these operations to inherit only the calling agent's ambient labels rather than having repo-scoped or user-scoped secrecy/integrity applied at the tool level.
The most significant concern is the asymmetry between read and write gist operations: list_gists and get_gist explicitly label responses as private:user, but create_gist and update_gist do not — so a newly-created secret gist response would not carry the private:user secrecy label. The same pattern applies to issue, PR, and repo write operations where the response (containing the newly created/modified resource) would benefit from explicit repo-visibility secrecy.
Additionally, 10 stale entries remain in WRITE_OPERATIONS / READ_WRITE_OPERATIONS — deprecated tool aliases that were consolidated into new tools. These are not security-critical (they provide harmless backward compatibility) but should be cleaned up.
- MCP tools scanned: 80 (from
github-mcp-server__toolsnaps__/) - Guard-covered write tools (tools.rs): 36 explicit + all
create_*,delete_*,update_*,merge_*,lock_*,unlock_*patterns - Tools with explicit DIFC rules (tool_rules.rs): 50+ (covering all read tools and ~6 write tools)
- Classification gaps: 0
- Labeling gaps: 30 write/mutating tools
- Stale entries: 10
MCP Tool DIFC Labeling Gaps (tool_rules.rs)
These 30 tools are correctly classified in tools.rs but have no explicit match arm in apply_tool_labels. They fall through to _ => {} and inherit only the caller's ambient labels.
High priority: Gist write operations (user-scoped secrecy gap)
list_gists / get_gist explicitly label responses as private:user with reader_integrity. But the write counterparts do not:
| Tool | Operation | Missing Label | Contrast |
|---|---|---|---|
create_gist |
Creates new gist (may be secret) | private:user |
list_gists / get_gist have this |
update_gist |
Updates existing gist | private:user |
same asymmetry |
Suggested fix for create_gist / update_gist in tool_rules.rs:
"create_gist" | "update_gist" => {
// Gist write operations create/modify user-owned content.
// S = private:user (gists may be secret); I = unapproved (user content)
secrecy = private_user_label();
baseline_scope = "user".to_string();
integrity = reader_integrity("user", ctx);
}Medium priority: Repo-scoped issue and PR write operations
Responses from these operations contain the created/updated resource (issue body, PR details, etc.) which should inherit repo-visibility secrecy when the repo is private:
| Tool | Operation | Missing Label |
|---|---|---|
create_issue |
Creates issue in repo | S(repo) |
issue_write |
Creates/edits issue | S(repo) |
sub_issue_write |
Creates/edits sub-issue | S(repo) |
add_issue_comment |
Adds comment to issue | S(repo) |
create_pull_request |
Creates PR | S(repo) |
update_pull_request |
Updates PR | S(repo) |
merge_pull_request |
Merges PR | S(repo) |
pull_request_review_write |
Creates/updates PR review | S(repo) |
add_comment_to_pending_review |
Adds to pending review | S(repo) |
add_reply_to_pull_request_comment |
Replies to PR comment | S(repo) |
Suggested fix for issue/PR write operations:
"create_issue" | "issue_write" | "sub_issue_write" | "add_issue_comment"
| "create_pull_request" | "update_pull_request" | "merge_pull_request"
| "pull_request_review_write" | "add_comment_to_pending_review"
| "add_reply_to_pull_request_comment" => {
// Issue and PR write operations return repo-scoped content.
// S = S(repo); I = writer
secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
integrity = writer_integrity(repo_id, ctx);
}Medium priority: Repo content and structure write operations
| Tool | Operation | Missing Label |
|---|---|---|
create_or_update_file |
Writes file content to repo | S(repo) |
push_files |
Pushes multiple files | S(repo) |
delete_file |
Deletes file from repo | S(repo) |
create_branch |
Creates new branch | S(repo) |
update_pull_request_branch |
Updates PR branch | S(repo) |
create_repository |
Creates new repository | repo-level |
fork_repository |
Creates fork | repo-level |
Suggested fix:
"create_or_update_file" | "push_files" | "delete_file" | "create_branch"
| "update_pull_request_branch" | "create_repository" | "fork_repository" => {
secrecy = apply_repo_visibility_secrecy(&owner, &repo, repo_id, secrecy, ctx);
integrity = writer_integrity(repo_id, ctx);
}Medium priority: Projects and labels write operations
| Tool | Operation | Missing Label |
|---|---|---|
projects_write |
Creates/updates/deletes project items | org-scoped |
label_write |
Creates/updates/deletes labels | S(repo) |
Lower priority: Notification and Copilot write operations
These operations have lower sensitivity but could benefit from consistency:
| Tool | Operation | Missing Label |
|---|---|---|
dismiss_notification |
Dismisses notification | private:user |
mark_all_notifications_read |
Marks all notifications read | private:user |
manage_notification_subscription |
Manages notification subscription | private:user |
manage_repository_notification_subscription |
Manages repo notification subscription | private:user |
actions_run_trigger |
Triggers workflow run | S(repo) |
assign_copilot_to_issue |
Assigns Copilot to issue | S(repo) |
request_copilot_review |
Requests Copilot review | S(repo) |
star_repository |
Stars repository | public |
unstar_repository |
Unstars repository | public |
Stale Guard Entries (bonus cleanup)
These entries in WRITE_OPERATIONS / READ_WRITE_OPERATIONS have been consolidated into new tool names (confirmed via deprecated_tool_aliases.go). They are not harmful — they provide backward compatibility — but should eventually be cleaned up.
In WRITE_OPERATIONS (now aliases for actions_run_trigger or projects_write):
run_workflow→actions_run_triggerrerun_workflow_run→actions_run_triggerrerun_failed_jobs→actions_run_triggercancel_workflow_run→actions_run_triggerdelete_workflow_run_logs→actions_run_triggeradd_project_item→projects_writedelete_project_item→projects_write
In READ_WRITE_OPERATIONS (stale or Insiders-only):
update_project_item→projects_writeupdate_issue→ replaced byissue_write(not in deprecated aliases; appears stale)create_pull_request_with_copilot→ not in current__toolsnaps__(may be Insiders-only; verify before removing)
References
- github-mcp-server tools (toolsnaps)
- deprecated_tool_aliases.go
- guard tools.rs
- guard tool_rules.rs
- Run: §23765169397
Generated by GitHub Guard Coverage Checker (MCP + CLI) · ◷
- expires on Apr 13, 2026, 8:16 PM UTC