Vulnerability Management Policy
Document control
| Field | Value |
|---|---|
| Owner | Ron Benisty — CTO & CSO (ron.b@iontwrks.com) |
| Status | Approved |
| Version | 1.0 |
| Classification | Confidential |
| Approved by | Ron Benisty — CTO & CSO |
| Approval date | 2026-05-26 (Tuesday) |
| Last reviewed | 2026-05-26 |
| Review cycle | Annual — next review due May 2027 |
| Parent policy | Secure SDLC (SSDLC) |
Satisfies ISO/IEC 27001:2022 A.8.8 (technical vulnerability management) and NIST SSDF RV.2 (assess, prioritize, remediate vulnerabilities). Closes Gap 8 of the SSDLC gap analysis.
1. Purpose
Every vulnerability finding — from any source — must be triaged, assigned a severity, tracked in a single register, fixed within a documented SLA, and verified. This policy turns the existing scanner toolchain (already locked in Supply Chain & CI/CD Security) into an end-to-end managed process with auditable evidence.
2. Scope — sources of findings
Every source feeds the same register and the same SLA table:
| Source | Tool / channel | How findings enter |
|---|---|---|
| Dependency CVEs | OSV-Scanner, Trivy, Dependabot | CI bot auto-creates a GitHub Issue per finding |
| Container image CVEs | Trivy on image scans | CI bot auto-creates a GitHub Issue per finding |
| SAST findings | Semgrep | CI bot auto-creates a GitHub Issue for high-severity findings; lower severities are addressed in-PR |
| Secret leaks | TruffleHog, Gitleaks, Push Protection | Treated as Sev 1 incident (IR) — vuln record + IR record both created |
| AWS-layer threats | GuardDuty → Logz.io | Alert pipeline triggers manual issue creation by on-call |
| DAST (automated) | OWASP ZAP (baseline per PR + full nightly) + Nuclei (weekly) per the DAST & Penetration Testing Policy | CI bot auto-creates a GitHub Issue per finding (source:zap / source:nuclei) |
| Pen-test (third-party human) | Annual + targeted retests per the DAST & Penetration Testing Policy | Vendor's report → bulk issue creation by CTO & CSO (source:pentest) |
| External reports | security@binarynetworks.ai mailbox + responsible-disclosure form | CTO & CSO triages → issue created |
| Customer reports | In-product support + DPA contact | CTO & CSO triages → issue created |
| Sub-processor advisories | Vendor security bulletins | CTO & CSO subscribes; advisories evaluated against our footprint |
3. Severity classification
3.1 CVSS v3.1
Every finding is scored using CVSS v3.1 (industry-standard, used by NVD, GitHub Advisory Database, Snyk, OSV). The CVSS vector and base score are recorded on the GitHub Issue.
| Severity | CVSS v3.1 base score |
|---|---|
| Critical | 9.0 – 10.0 |
| High | 7.0 – 8.9 |
| Medium | 4.0 – 6.9 |
| Low | 0.1 – 3.9 |
For tool-emitted findings, the scanner's CVSS score is used as the starting point. The triage owner may override with documented justification (e.g. "scanner CVSS 7.5 reduced to High → Medium because the affected code path is not reachable from any user input"). Overrides require CTO & CSO approval.
3.2 KEV override
Any CVE on CISA's Known Exploited Vulnerabilities (KEV) catalog is treated as Critical regardless of its CVSS score. Known-exploited vulnerabilities are by definition the highest urgency — KEV listing trumps CVSS.
The triage step (§6) includes a KEV check via the CISA KEV catalog.
4. Remediation SLAs
Counted from "finding verified" (end of triage in §6) to "fix deployed to production."
| Severity | Fix in production by | Notes |
|---|---|---|
| Critical | ≤ 7 days | Includes anything on CISA KEV. Often weaponized in the wild; exploitation likely. |
| High | ≤ 30 days | Material risk; exploit usually not yet weaponized. |
| Medium | ≤ 90 days | Real but contained; fits into routine release cycle. |
| Low | ≤ next quarter (≤ 120 days) | Queued with regular maintenance. |
The SLA clock is paused only by an approved exception per §7. Silent SLA slips are explicitly forbidden.
5. The vulnerability register
Location: GitHub Issues in the main repo. Same chokepoint as the Change Management PR-as-change-record model — no separate tracker, no spreadsheet, no vendor.
5.1 Mandatory labels
Every vuln issue carries:
vuln— the master label (saved-search anchor for the register).severity:critical·severity:high·severity:medium·severity:lowsource:trivy·source:osv-scanner·source:semgrep·source:trufflehog·source:dependabot·source:guardduty·source:pentest·source:external·source:customer·source:subprocessorstatus:open·status:in-progress·status:exception·status:verified·status:closedkev(added when the CVE is on the CISA KEV catalog)
5.2 Issue template
The .github/ISSUE_TEMPLATE/vulnerability.md template forces the required fields:
## Vulnerability finding
**Source**: <!-- e.g. OSV-Scanner -->
**Identifier**: <!-- CVE-XXXX-XXXX, GHSA-XXXX, Semgrep rule ID -->
**CVSS v3.1 base score**: <!-- 0.0 – 10.0 -->
**CVSS vector**: <!-- e.g. AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H -->
**Severity**: <!-- Critical / High / Medium / Low (override to Critical if KEV-listed) -->
**KEV listed**: <!-- yes / no -->
## Description
<!-- What it is, where it lives, how exploitation works -->
## Impact
<!-- What could happen; affected tenants/data/systems -->
## Affected components
<!-- File paths, package names, image names, AWS resources -->
## Reproduction
<!-- Steps, or "scanner output only" if not reproducible -->
## Triage
- [ ] Confirmed reproducible / scanner finding accepted
- [ ] Severity assigned (CVSS + KEV check)
- [ ] Owner assigned: @{username}
- [ ] SLA clock started: {YYYY-MM-DD}
## SLA
- **Severity tier**: <!-- Critical (≤7d) / High (≤30d) / Medium (≤90d) / Low (≤120d) -->
- **Target fix-in-production date**: {YYYY-MM-DD}
## Resolution
- [ ] Fix implemented in PR: #
- [ ] Deployed to nonprod
- [ ] Deployed to production
- [ ] Verification: <!-- scanner re-run clean / regression test added / pen-test retest passed -->
- [ ] Issue closed
5.3 Ownership
Every issue has exactly one assignee (GitHub's native owner field). For tool-emitted findings, the bot assigns the CODEOWNER of the affected path. For external/customer reports, the CTO & CSO assigns.
6. Triage flow
- Finding enters the register — automatically (CI bot) or manually (CTO & CSO for external reports).
- Triage within 1 business day — owner confirms reproducibility (or accepts scanner output), records CVSS + KEV check, assigns severity, fills the triage checklist. The SLA clock starts when triage completes (not at scanner emission — this avoids false-positive races penalizing the team).
- Fix — owner files a PR linked to the issue (per Change Management). Standard CI gates apply; CODEOWNER review is mandatory.
- Deploy — nonprod → production through the Release Gate Criteria.
- Verify (§8) — owner attaches verification evidence.
- Close — issue closed only after verification passes.
Scanner / report → Auto/manual issue → Triage (1 bd) → SLA clock starts
→ PR fix → Nonprod deploy → Prod deploy → Verify → Close
7. Exception process (when SLA cannot be met)
When a fix genuinely cannot be deployed within its SLA, the owner files an exception on the same GitHub Issue. The SLA clock is paused only after CTO & CSO approval.
Required exception fields (appended to the issue):
## Exception
**Risk while unfixed**: <!-- What could happen during the extended window -->
**Reason SLA cannot be met**: <!-- Honest explanation: breaking change, vendor
dependency, deletion in progress, etc. -->
**Compensating control deployed**: <!-- WAF rule / feature flag / scope limit
/ alerting tweak — MUST be deployed BEFORE the exception is approved -->
**New target date**: {YYYY-MM-DD}
**CTO & CSO approval**: <!-- Comment by CTO & CSO acknowledging risk acceptance -->
- [ ] Status label changed to `status:exception`
- [ ] Reviewed at next quarterly risk-assessment cycle: {YYYY-Q?}
Rules:
- The compensating control must be deployed before approval — not promised, deployed.
- Approval is on the issue itself, by a CTO & CSO comment. The audit trail lives in the issue's history.
- Every open exception is reviewed at every quarterly risk-assessment cycle (per the Risk Assessment Policy). This catches forgotten exceptions.
- A second extension requires a second CTO & CSO approval — the new target date cannot be silently moved.
Silent SLA slips (a Critical past day 7 with no exception filed, no compensating control, no approval) are a process failure that triggers a Root-Cause Analysis — RCA on the management process, not on the developer.
8. Verification
A finding is not "closed" until it is verified gone:
| Source type | Verification |
|---|---|
| Dependency CVE | Scanner re-run on the deployed image shows the finding is gone (or version is now in the patched range) |
| Container image CVE | Trivy on the deployed image shows clean |
| SAST finding | Semgrep on the deployed code no longer fires the rule (or a documented suppression with linked exception) |
| Secret leak | TruffleHog re-run + rotated credential confirmed unused at the source (e.g. WorkOS API key now revoked) |
| AWS-layer (GuardDuty) | Re-occurrence not observed for 30 days post-fix |
| Pen-test | Retest by the same vendor (or annotated as "fixed; retest in next engagement") |
| External / customer / researcher report | Original reporter notified + given verification material; reporter's acknowledgement attached when available |
Verification evidence (scanner output, retest report, reporter email) is attached to the issue before closing.
9. Reporting & monthly review
CTO & CSO reviews the register monthly and produces a one-page summary retained per the Evidence Collection & Retention Policy:
| Metric | Source |
|---|---|
| Open count by severity | GitHub Issues saved search |
| SLA compliance rate — % of closed findings whose fix shipped within SLA | Issue close dates vs. triage dates |
| Mean Time To Resolve (MTTR) by severity | Same |
| Open exceptions count + target dates | status:exception label |
| New findings by source | source:* label distribution |
| Recurring vulnerability classes | Manual; cross-referenced with the RCA process for repeat-class triggers |
The monthly summary is the artifact SOC 2 Type II will sample — both the existence of the review and the trends it reports.
10. Integration with other policies
- Secret leaks → also a Sev 1 incident. Both records exist; they reference each other.
- Cross-tenant findings → automatically Sev 1 incident (any cross-tenant data exposure is a Sev 1 by definition).
- CODEOWNER-protected paths (auth, tenant, crypto, CI workflows, Terraform, schema migrations) — fixes get the heightened review the secure-coding standard already requires.
- Recurring same-class findings (third occurrence within rolling 12 months) trigger a Root-Cause Analysis per RV.3 — fix the class, not just the instance.
- Exceptions are reviewed at every quarterly risk-assessment cycle per the Risk Assessment Policy.
- All findings + their lifecycle are part of the Evidence Register — the GitHub Issue is the evidence.
11. Evidence + retention
- Per-finding: the full GitHub Issue history (creation, triage, fix PRs, verification, close) — retained ≥ 12 months by GitHub by default; we extend by labeling closed
vuln-labeled issues for indefinite retention. - Monthly summary: retained ≥ 12 months per the Evidence Collection & Retention Policy.
- Exception records: retained ≥ 24 months (same as risk-acceptance records).
- Scanner outputs themselves: per Supply Chain & CI/CD Security §SOC 2 evidence retention — 12 months minimum.
12. Document change history
| Version | Date | Author | Description of change | Approved by |
|---|---|---|---|---|
| 1.0 | 2026-05-26 | Ron Benisty (CTO & CSO) | Initial version — CVSS v3.1 severity scoring (+ KEV override); SLAs 7/30/90/120 days; GitHub Issues register with mandatory labels + template; documented exception process with CTO & CSO approval + compensating-control requirement; verification + monthly review. | Ron Benisty (CTO & CSO) |