Generative AI

NVIDIA SkillSpector Guide: Scans AI Skills for Security Risks with static analysis and SARIF reports

print("Batch scanning the whole corpus (static-only)...n")
summary_rows = []
all_findings = []
for skill in SKILLS:
   res = scan(skill, use_llm=False, output_format="json")
   fnds = findings_of(res)
   summary_rows.append({
       "skill": skill.name,
       "risk_score": res.get("risk_score"),
       "severity": res.get("risk_severity"),
       "recommendation": res.get("risk_recommendation"),
       "num_findings": len(fnds),
       "has_executable": res.get("has_executable_scripts"),
   })
   for f in fnds:
       all_findings.append({
           "skill": skill.name,
           "rule_id": f.get("rule_id"),
           "severity": str(f.get("severity")),
           "category": f.get("category"),
           "message": f.get("message"),
           "file": f.get("file"),
           "line": f.get("start_line"),
           "confidence": f.get("confidence"),
       })
summary_df = pd.DataFrame(summary_rows).sort_values("risk_score", ascending=False)
findings_df = pd.DataFrame(all_findings)
print("──── Risk summary ────")
print(summary_df.to_string(index=False))
print(f"nTotal findings across corpus: {len(findings_df)}n")
if not findings_df.empty:
   print("──── Findings by category ────")
   print(findings_df["category"].value_counts().to_string())
   print("n──── Findings by severity ────")
   print(findings_df["severity"].value_counts().to_string())
   print()
def _normalize_sev(s: str) -> str:
   s = str(s).upper()
   for level in ("CRITICAL", "HIGH", "MEDIUM", "LOW"):
       if level in s:
           return level
   return s
if not summary_df.empty:
   fig, axes = plt.subplots(1, 3, figsize=(16, 4.5))
   colors = {"CRITICAL": "#7f1d1d", "HIGH": "#dc2626",
             "MEDIUM": "#f59e0b", "LOW": "#16a34a"}
   sev_norm = summary_df["severity"].map(_normalize_sev)
   axes[0].barh(summary_df["skill"], summary_df["risk_score"],
                color=[colors.get(s, "#3b82f6") for s in sev_norm])
   axes[0].set_title("Risk score per skill (0–100)")
   axes[0].set_xlim(0, 100)
   axes[0].invert_yaxis()
   for y, v in zip(summary_df["skill"], summary_df["risk_score"]):
       axes[0].text((v or 0) + 1, y, str(v), va="center", fontsize=9)
   if not findings_df.empty:
       sev_counts = (findings_df["severity"].map(_normalize_sev)
                     .value_counts()
                     .reindex(["CRITICAL", "HIGH", "MEDIUM", "LOW"]).dropna())
       axes[1].bar(sev_counts.index, sev_counts.values,
                   color=[colors.get(s, "#3b82f6") for s in sev_counts.index])
       axes[1].set_title("Findings by severity")
   else:
       axes[1].set_visible(False)
   if not findings_df.empty:
       cat_counts = findings_df["category"].value_counts().head(10)
       axes[2].barh(cat_counts.index[::-1], cat_counts.values[::-1], color="#3b82f6")
       axes[2].set_title("Top finding categories")
   else:
       axes[2].set_visible(False)
   plt.tight_layout()
   out_png = WORKDIR / "skillspector_dashboard.png"
   plt.savefig(out_png, dpi=120, bbox_inches="tight")
   print(f"📊 Saved dashboard -> {out_png}")
   plt.show()

Source link

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button