Skip to content

Vulnerabilities#21

Merged
colinmoynes merged 2 commits intomainfrom
vulnerabilities
Mar 20, 2026
Merged

Vulnerabilities#21
colinmoynes merged 2 commits intomainfrom
vulnerabilities

Conversation

@colinmoynes
Copy link
Collaborator

@colinmoynes colinmoynes commented Mar 20, 2026

📄 Summary

[Sonar] [v1.3]

Added

  • Added vulnerabilities flag — When set, fetches and displays vulnerability scan status and CVE severity summary (Critical, High, Medium, Low) for each package in the output.
  • Rolls up child image vulnerability data into the parent manifest list.
  • Rich-formatted display for scan status (Scanned, Not Supported, Scanning, etc.).
  • Vulnerability fields included in all output formats.

🔍 Related Issues

Link to any related GitHub issues (e.g., Fixes #12, Closes #34):

🧪 Type of Change

Please check the relevant type tag for this PR title:

  • [FIX] Bug fix
  • [NEW] New thing
  • [REFACTOR] Internal changes such as code restructuring or optimization that does not alter functionality
  • [DOC] Documentation-only changes
  • [CHORE] Maintenance, cleanup, or CI configuration

🧪 How Has This Been Tested?

Describe how you tested your changes. Include CI runs, local tests, manual verification, or screenshots if applicable.

📸 Screenshots (if applicable)

If UI or logs are affected, include before/after screenshots or output.

✅ Checklist

  • I’ve read and followed the CONTRIBUTING.md.
  • I’ve added or updated documentation as needed.
  • I’ve verified the change is tested and works as intended.
  • CI/CD checks pass and do not break existing functionality.
  • My code follows the style guidelines of this project.

@colinmoynes colinmoynes self-assigned this Mar 20, 2026
Copilot AI review requested due to automatic review settings March 20, 2026 15:05
@colinmoynes colinmoynes merged commit b1b28c3 into main Mar 20, 2026
2 checks passed
Copy link

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

Adds optional vulnerability reporting to the Docker Sonar utility, allowing users to fetch and display vulnerability scan status plus CVE severity counts alongside existing image/tag analysis.

Changes:

  • Introduces --vulnerabilities flag and plumbing (fetch_vulns) through the analysis pipeline.
  • Fetches vulnerability scan data per package (and rolls up child image data into manifest-list parents).
  • Extends table/CSV outputs (and underlying row structures) to include vulnerability fields.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
Docker/Sonar/sonar.py Adds vulnerability fetching/rollups and output formatting; updates function signatures to pass fetch_vulns.
CHANGELOG.md Documents Sonar v1.3 vulnerability flag and related enhancements.

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

Comment on lines 456 to 458
uploaded_at = find_key_recursive(pkg_details, 'uploaded_at')
if uploaded_at:
uploaded = uploaded_at
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

uploaded_at = find_key_recursive(...) returns a list, but the code assigns uploaded = uploaded_at and later returns uploaded in the result. This makes uploaded a list (not a timestamp/string) and also leaves uploaded undefined when uploaded_at is empty or pkg_details is falsy (raising UnboundLocalError). Initialize uploaded up-front and set it to a single value (e.g., uploaded_at[0]) when present.

Copilot uses AI. Check for mistakes.
Comment on lines +289 to +292
# Fallback: use top-level fields from list response if available
summary["vuln_status"] = "Scanned"
if latest_scan.get("num_vulnerabilities"):
_extract_severity_from_scans(latest_scan.get("scans", []), summary)
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

When scan_detail is missing, severity extraction is gated on latest_scan.get("num_vulnerabilities"), which skips extraction when that field is absent or zero. If latest_scan["scans"] is present, aggregate from it regardless of num_vulnerabilities (and still compute totals as 0 when there are none).

Suggested change
# Fallback: use top-level fields from list response if available
summary["vuln_status"] = "Scanned"
if latest_scan.get("num_vulnerabilities"):
_extract_severity_from_scans(latest_scan.get("scans", []), summary)
# Fallback: use fields from the latest_scan response if available
summary["vuln_status"] = "Scanned"
scan_entries = latest_scan.get("scans")
if scan_entries:
# Prefer aggregating from scans if they are present
_extract_severity_from_scans(scan_entries, summary)
else:
# Fallback: try top-level num_* fields or a vulnerabilities list on latest_scan
for sev in ("critical", "high", "medium", "low", "unknown"):
count = (
latest_scan.get(f"num_{sev}")
or latest_scan.get(f"{sev}_count")
or latest_scan.get(sev)
)
if count is not None:
summary[sev] = int(count)
summary["total"] = sum(
summary[s] for s in ("critical", "high", "medium", "low", "unknown")
)

Copilot uses AI. Check for mistakes.
if isinstance(row, dict):
row['action'] = action_str
# Remove internal slug
if 'slug' in row: del row['slug']
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

Rows from fetch_untagged_data now include slug_perm, but the cleanup step only deletes row['slug']. This leaves an internal identifier in the returned output structures. If slug is considered internal-only here, slug_perm should also be stripped (or both should be kept consistently).

Suggested change
if 'slug' in row: del row['slug']
if 'slug' in row:
del row['slug']
if 'slug_perm' in row:
del row['slug_perm']

Copilot uses AI. Check for mistakes.
Comment on lines 1509 to +1513
for img_name, groups in collected_results:
for group in groups:
if group == "SECTION":
continue
# Flat CSV row
csv_lines.append([
row = [
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

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

The CSV export loop treats each group as a dict (group.get(...)), but collected_results stores groups as a list of group-lists (each group is a list of row dicts + optional "SECTION" markers). As written, --output csv will fail with an AttributeError. Flatten the structure for CSV (iterate group -> row, skipping "SECTION") or change what gets stored in collected_results for CSV output.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants