gitsafehub runs six checks on a repo. Five are security checks (leaked secrets, vulnerable dependencies, known OSS vulnerabilities, risky code patterns, malicious dependencies); the sixth is project health (OpenSSF Scorecard). The headline reads “N of 6 checks flagged a security issue” with a plain status — 🟢 Looks clean, 🟡 Worth a look, or 🔴 Needs attention. The rule that converts the security checks’ raw findings into that status is deterministic, published here, and does not change between scans.
Project health is shown but never sets the verdict. A low maintenance score (no branch protection, few maintainers, etc.) is a signal about the project — not a vulnerability in your code — so OpenSSF Scorecard findings are excluded from the “flagged” count and never turn the status amber or red.
“Incomplete” is not “Safe.” If none of the security checks could finish (a clone failure, timeouts, or a stale record), the page says “Scan didn’t finish” and shows no verdict. We never paint a green “clean” over a scan that produced no data.
| If the security checks report… | Status |
|---|---|
| 1 or more critical findings, OR 1 or more high findings | 🔴 Needs attention |
| 1 or more medium or low findings (no critical / high) | 🟡 Worth a look |
| Only informational findings, or nothing | 🟢 Looks clean |
| No security check could run (clone/timeout failure, or a stale record) | ⚪ Scan didn’t finish |
A single high-severity finding rolls up to 🔴 Needs attention. Because we deliberately cap dependency vulnerabilities at medium (see below), the findings that still reach high are the ones that are genuinely urgent and in your control: a leaked provider token (Gitleaks), an exploitable code pattern (Semgrep), or active malicious behaviour in a package (Guarddog). Routing those through “warning” would understate the urgency and let a real exploit read as “just a warning.”
generic-api-key, the main false-positive source) → medium.max_severity), capped (see below): 9.0+ → critical, 4.0–8.9 → medium, >0 → low. Records with no CVSS score → informational (listed, but don’t move the verdict). OSV malware advisories (MAL-*) → critical (uncapped).p/owasp-top-ten + p/malicious-packages) — ERROR → high, WARNING → medium, INFO → informational. Findings from LOW-confidence rules are demoted to informational (confidence is Semgrep’s own false-positive proxy), so they show but don’t move the verdict.Almost every modern repo pulls in dependencies that have some known advisory — a denial-of-service in a parser, a path-traversal in a build tool, usually buried deep in the transitive tree and often not even reachable from your code. If every one of those turned a repo red, two-thirds of all projects would read “Needs attention,” and the verdict would mean nothing. So a known-vulnerable dependency caps at 🟡 Worth a look — update it when you can — and only a genuinely critical-severity (CVSS 9.0+) dependency reaches red. 🔴 Needs attention is reserved for things that are actually urgent and in your control: leaked secrets, malicious packages, critical-severity RCEs, and risky code in your own files.
Not a security audit. A 🟢 Looks clean status means the five security checks above didn’t find anything they consider critical, high, medium, or low at the time of the scan. It does not mean the code is secure. Tools miss real problems. Tools flag things that aren’t real. If you need a real audit, hire a real auditor.
Not a certification. No badge, no “passed” stamp, no claim about your project’s overall security posture. The verdict is one snapshot, one git_hash, six checks, one published rule.
The verdict computation is open-source. The backend implementation lives in backend/verdict.py. The frontend mirror is in functions/lib.js as rollupVerdict(); the “N of 6” headline, the security-only roll-up (which excludes Scorecard), and the “incomplete” state are computed by headlineState() in the same file. The roll-up is covered by unit tests (tests/test_verdict.py) that fail CI if the backend and frontend drift.