Skip to main content

Vulnerability Management Policy

Document control

FieldValue
OwnerRon Benisty — CTO & CSO (ron.b@iontwrks.com)
StatusApproved
Version1.0
ClassificationConfidential
Approved byRon Benisty — CTO & CSO
Approval date2026-05-26 (Tuesday)
Last reviewed2026-05-26
Review cycleAnnual — next review due May 2027
Parent policySecure 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:

SourceTool / channelHow findings enter
Dependency CVEsOSV-Scanner, Trivy, DependabotCI bot auto-creates a GitHub Issue per finding
Container image CVEsTrivy on image scansCI bot auto-creates a GitHub Issue per finding
SAST findingsSemgrepCI bot auto-creates a GitHub Issue for high-severity findings; lower severities are addressed in-PR
Secret leaksTruffleHog, Gitleaks, Push ProtectionTreated as Sev 1 incident (IR) — vuln record + IR record both created
AWS-layer threatsGuardDuty → Logz.ioAlert pipeline triggers manual issue creation by on-call
DAST (automated)OWASP ZAP (baseline per PR + full nightly) + Nuclei (weekly) per the DAST & Penetration Testing PolicyCI 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 PolicyVendor's report → bulk issue creation by CTO & CSO (source:pentest)
External reportssecurity@binarynetworks.ai mailbox + responsible-disclosure formCTO & CSO triages → issue created
Customer reportsIn-product support + DPA contactCTO & CSO triages → issue created
Sub-processor advisoriesVendor security bulletinsCTO & 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.

SeverityCVSS v3.1 base score
Critical9.0 – 10.0
High7.0 – 8.9
Medium4.0 – 6.9
Low0.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."

SeverityFix in production byNotes
Critical≤ 7 daysIncludes anything on CISA KEV. Often weaponized in the wild; exploitation likely.
High≤ 30 daysMaterial risk; exploit usually not yet weaponized.
Medium≤ 90 daysReal 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:low
  • source:trivy · source:osv-scanner · source:semgrep · source:trufflehog · source:dependabot · source:guardduty · source:pentest · source:external · source:customer · source:subprocessor
  • status:open · status:in-progress · status:exception · status:verified · status:closed
  • kev (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

  1. Finding enters the register — automatically (CI bot) or manually (CTO & CSO for external reports).
  2. 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).
  3. Fix — owner files a PR linked to the issue (per Change Management). Standard CI gates apply; CODEOWNER review is mandatory.
  4. Deploy — nonprod → production through the Release Gate Criteria.
  5. Verify (§8) — owner attaches verification evidence.
  6. 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 typeVerification
Dependency CVEScanner re-run on the deployed image shows the finding is gone (or version is now in the patched range)
Container image CVETrivy on the deployed image shows clean
SAST findingSemgrep on the deployed code no longer fires the rule (or a documented suppression with linked exception)
Secret leakTruffleHog 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-testRetest by the same vendor (or annotated as "fixed; retest in next engagement")
External / customer / researcher reportOriginal 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:

MetricSource
Open count by severityGitHub Issues saved search
SLA compliance rate — % of closed findings whose fix shipped within SLAIssue close dates vs. triage dates
Mean Time To Resolve (MTTR) by severitySame
Open exceptions count + target datesstatus:exception label
New findings by sourcesource:* label distribution
Recurring vulnerability classesManual; 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

VersionDateAuthorDescription of changeApproved by
1.02026-05-26Ron 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)