You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tooling.apache.org by ak...@apache.org on 2026/07/08 19:59:31 UTC
(tooling-agents) branch main updated: Removing codeowners findings and sorting review by severity
This is an automated email from the ASF dual-hosted git repository.
andrewmusselman pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-agents.git
The following commit(s) were added to refs/heads/main by this push:
new 9f884c8 Removing codeowners findings and sorting review by severity
9f884c8 is described below
commit 9f884c89fd892f187ad4d254cccf4d45ae5b3ddb
Author: Andrew Musselman <ak...@apache.org>
AuthorDate: Wed Jul 8 12:59:21 2026 -0700
Removing codeowners findings and sorting review by severity
---
gha-review/agents/gha_review.py | 41 +++++++++++++++++------------------------
1 file changed, 17 insertions(+), 24 deletions(-)
diff --git a/gha-review/agents/gha_review.py b/gha-review/agents/gha_review.py
index 35e3cce..8b9ff48 100644
--- a/gha-review/agents/gha_review.py
+++ b/gha-review/agents/gha_review.py
@@ -402,18 +402,6 @@ async def run(input_dict, tools):
"3. Cache is populated with attacker's dependencies\n"
"4. Next main-branch build restores the poisoned cache"),
},
- "missing_codeowners": {
- "label": "No CODEOWNERS File",
- "severity": "LOW",
- "description": "Repository has no CODEOWNERS file for workflow change review.",
- "attack": ("Without CODEOWNERS requiring security team review of `.github/` changes, "
- "any committer can modify workflow files, add new triggers, weaken permissions, "
- "or introduce injection patterns without mandatory security review."),
- "example": ("1. Committer adds `pull_request_target` trigger to an existing workflow\n"
- "2. No CODEOWNERS rule requires security review for `.github/` changes\n"
- "3. PR is merged with standard code review (reviewer may miss security implication)\n"
- "4. Workflow is now vulnerable to external PRs"),
- },
"third_party_actions": {
"label": "Third-Party Actions",
"severity": "INFO",
@@ -456,7 +444,18 @@ async def run(input_dict, tools):
lines.append("| Vulnerability | Count | Severity | Description |")
lines.append("|--------------|-------|----------|-------------|")
- for check, count in sorted(vuln_checks.items(), key=lambda x: -x[1]):
+ sev_sort = {"CRITICAL": 0, "CRITICAL–LOW": 0, "HIGH–LOW": 1, "HIGH": 1,
+ "MEDIUM": 2, "LOW–CRITICAL": 0, "LOW–MEDIUM": 2, "LOW": 3, "INFO": 4, "—": 5}
+
+ def check_sort_key(item):
+ check, count = item
+ scenario = ATTACK_SCENARIOS.get(check, {})
+ sev = scenario.get("severity", "—")
+ return (sev_sort.get(sev, 5), -count)
+
+ for check, count in sorted(vuln_checks.items(), key=check_sort_key):
+ if check == "missing_codeowners":
+ continue
scenario = ATTACK_SCENARIOS.get(check, {})
label = scenario.get("label", check)
sev_label = scenario.get("severity", "—")
@@ -469,7 +468,9 @@ async def run(input_dict, tools):
lines.append("## Attack Scenarios\n")
lines.append("For each vulnerability type found, here is how an attacker could exploit it.\n")
- for check, count in sorted(vuln_checks.items(), key=lambda x: -x[1]):
+ for check, count in sorted(vuln_checks.items(), key=check_sort_key):
+ if check == "missing_codeowners":
+ continue
scenario = ATTACK_SCENARIOS.get(check)
if not scenario:
continue
@@ -566,7 +567,7 @@ async def run(input_dict, tools):
n_low = len(low_repos)
lines.append("## Low Risk: Publishing Repos\n")
lines.append(f"{n_low} {plural(n_low, 'repo')} {plural(n_low, 'publishes', 'publish')} packages with only LOW/INFO-level "
- f"security findings (missing CODEOWNERS, no dependabot config).\n")
+ f"security findings (no dependabot config, broad permissions).\n")
lines.append(f"<details>\n<summary>Show {n_low} {plural(n_low, 'repo')}</summary>\n")
for r in low_repos:
repo = r["repo"]
@@ -611,7 +612,7 @@ async def run(input_dict, tools):
lines.append("## Summary\n")
lines.append(f"None of the {pub_stats.get('repos_scanned', '?')} scanned repos publish packages to "
f"registries. Security findings are limited to general CI hygiene "
- f"(unpinned actions, missing CODEOWNERS). See the "
+ f"(unpinned actions, broad permissions). See the "
f"[security report]({SEC}) for details.\n")
# --- Key recommendations (only include items with nonzero counts) ---
@@ -665,14 +666,6 @@ async def run(input_dict, tools):
f"{'The scanned repo uses' if n_repos == 1 else f'All {n_repos} repos use'} "
f"mutable tag refs. "
f"See the [unpinned actions findings]({SEC}#medium-findings) for per-repo counts.")
- rec_num += 1
-
- codeowners_missing = sec_stats.get("check_counts", {}).get("missing_codeowners", 0)
- if codeowners_missing:
- lines.append(f"{rec_num}. **Add CODEOWNERS with `.github/` coverage.** "
- f"{codeowners_missing} {plural(codeowners_missing, 'repo')} "
- f"{plural(codeowners_missing, 'has', 'have')} no CODEOWNERS file. "
- f"Workflow changes can bypass security review.")
lines.append("")
lines.append("---\n")
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@tooling.apache.org
For additional commands, e-mail: commits-help@tooling.apache.org