Back to CI/CD Pipeline
Q8Question 8 of 56

Should a failing security scan block the build: how do you choose blocking criteria, remediation SLAs by severity, and an auditable exception process?

Key Concepts
  • Blocking on every HIGH/CRITICAL finding floods developers with noise and causes them to bypass the gate entirely.
  • The strongest blocking criterion combines severity (CVSS), reachability (does your code call the vulnerable function?), and exploitability (CISA KEV, EPSS).
  • Remediation SLAs by severity: Critical within 72 hours, High within 30 days, Medium within 90 days, Low within 180 days.
  • The gate stops NEW critical issues from entering; the SLA process drives DOWN the existing backlog over time.
  • Exceptions are time-boxed, signed, and expiring: who requested, who approved, justification, compensating control, and expiry date.
  • An exception that expires automatically forces re-review and produces an auditable trail for regulators.

Definition

Block the build on severity plus exploitability, fix the rest against severity-based SLAs, and allow only time-boxed, signed, expiring exceptions.
  • Build-breaking gate – a pipeline policy that fails the build when a scanner reports a finding above a defined risk threshold.
  • Blocking criteria – severity (CVSS) combined with reachability (does your code call it?) and exploitability (is there a known exploit?).
  • Remediation SLAs – deadlines per severity: Critical within 72 hours, High within 30 days, Medium within 90 days, Low within 180 days.
  • Exception process – a formal, time-boxed risk acceptance with approver, justification, compensating control, and expiry date.
  • Gate vs. SLA – the gate stops new critical issues from entering; the SLA drives down the existing backlog over time.

Think of the security scan as the metal detector at the entrance of National Bank of India. If it beeps for a real gun (a critical, exploitable vulnerability), the guard must stop that person. If it beeps for a metal belt buckle (a low-severity issue in code that never runs), you note it and give it a deadline. If someone genuinely needs to carry a tool, a manager signs a dated, expiring permission slip: the auditable exception.

Understanding the Concepts

Should a failing security scan block the build?

Yes, but the engineering skill is in choosing what exactly to block on. Blocking on every HIGH or CRITICAL destroys developer trust because most scanners produce a flood of findings, many in transitive dependencies your code never calls. When every build goes red, engineers bypass the gate, which is worse than having no gate.

YAML
# WRONG: block on every HIGH or above -- too noisy
- run: mvn dependency-check:check -DfailBuildOnCVSS=7
# Result: every build fails, team bypasses the gate
# Developer trust in the gate is destroyed

# CORRECT: block on Critical + reachable, or on CISA KEV list
- run: mvn dependency-check:check -DfailBuildOnCVSS=9
# Critical findings block. Pre-existing Mediums become tracked tickets.

How do you choose blocking criteria?

The strongest blocking criterion combines three signals: severity, reachability, and exploitability.

| Signal | Source | What It Tells You |
|--------|--------|-------------------|
| Severity | CVSS base score | How bad the vulnerability is in theory |
| Reachability | Snyk, GitHub reachability analysis | Does your code actually call the vulnerable function? |
| Exploitability | CISA KEV catalog, EPSS score | Are attackers using this exploit right now? |

YAML
# A sensible blocking policy:
# Block if: Critical (CVSS >= 9.0) AND reachable
# Block if: On CISA KEV list (regardless of CVSS)
# Block if: Newly introduced HIGH (not pre-existing)
# Track (don't block): pre-existing Mediums and Lows
# Track (don't block): non-reachable findings
JAVA
package com.bank.security;

import java.math.BigDecimal;

public class VulnerabilityPolicy {

    public enum Decision { BLOCK, TRACK, ACCEPT }

    public Decision evaluate(BigDecimal cvssScore, boolean reachable, boolean onKevList,
                             boolean newlyIntroduced) {
        // Block: on KEV list regardless of CVSS
        if (onKevList) return Decision.BLOCK;

        // Block: Critical AND reachable
        if (cvssScore.compareTo(new BigDecimal("9.0")) >= 0 && reachable) return Decision.BLOCK;

        // Block: newly introduced HIGH
        if (cvssScore.compareTo(new BigDecimal("7.0")) >= 0 && newlyIntroduced) return Decision.BLOCK;

        // Track: everything else gets an SLA
        return Decision.TRACK;
    }
}

What are remediation SLAs by severity?

Remediation SLAs are deadlines assigned by severity. The clock starts when the finding is first detected.

| Severity | CVSS Range | SLA | Example |
|----------|-----------|-----|---------|
| Critical | 9.0 - 10.0 | 24-72 hours | Remote code execution in a web framework |
| High | 7.0 - 8.9 | 7-30 days | SQL injection in a reachable endpoint |
| Medium | 4.0 - 6.9 | 90 days | Information disclosure in error messages |
| Low | 0.1 - 3.9 | 180 days or risk-accepted | Minor information leak, low impact |

TEXT
 Gate vs. SLA -- two different jobs:

 Gate:  Stops NEW critical issues from entering production
        (blocks the build on this commit)

 SLA:   Drives DOWN the existing backlog over time
        (tracked tickets with deadlines)

 Metric: mean-time-to-remediate (MTTR) measures program health

How does the auditable exception process work?

Sometimes you genuinely cannot fix a finding immediately: there is no patch yet, or the fix is a breaking major-version upgrade, or the vulnerable path is provably not exploitable.

YAML
# .snyk policy file -- exception with governance metadata
ignore:
  'SNYK-JAVA-COMFABORXML-6053542':
    - '*':
        reason: >-
          No patch available. Vulnerable path is not reachable in our
          configuration (confirmed by security team review SR-2024-042).
        expires: 2024-06-30T00:00:00.000Z
        created: 2024-03-15T00:00:00.000Z
TEXT
 A good exception MUST record:

 1. Who requested it          (developer name)
 2. Who approved it            (security owner -- NOT the developer)
 3. Business justification     (why we cannot fix now)
 4. Compensating control       (what mitigates the risk)
 5. Expiry date                (when the gate re-blocks automatically)

 When the exception expires:
   - The gate fails again
   - Forces a fresh review
   - Either the fix is applied or a new exception is justified
   - This is what makes it auditable
JAVA
package com.bank.security;

import java.time.LocalDate;

public class SecurityException {
    private final String vulnerabilityId;
    private final String requestedBy;
    private final String approvedBy;
    private final String justification;
    private final String compensatingControl;
    private final LocalDate expiryDate;

    public SecurityException(String vulnerabilityId, String requestedBy,
                             String approvedBy, String justification,
                             String compensatingControl, LocalDate expiryDate) {
        this.vulnerabilityId = vulnerabilityId;
        this.requestedBy = requestedBy;
        this.approvedBy = approvedBy;
        this.justification = justification;
        this.compensatingControl = compensatingControl;
        this.expiryDate = expiryDate;
    }

    public boolean isExpired() {
        return LocalDate.now().isAfter(expiryDate);
    }

    // When expired, the gate re-blocks automatically
}

What is the difference between blocking and tracking?

| Aspect | Blocking (Gate) | Tracking (SLA) |
|--------|----------------|----------------|
| When | At build time, on this commit | After detection, with a deadline |
| Effect | Build fails, code cannot merge | Ticket created, SLA clock starts |
| Applies to | New critical/reachable findings | Pre-existing mediums, lows, non-reachable |
| Metric | Block rate, false positive rate | Mean time to remediate (MTTR) |

What are common mistakes with security gates?

YAML
# WRONG: blocking on everything -- developers lose trust
- run: trivy image --exit-code 1 --severity LOW,MEDIUM,HIGH,CRITICAL ...
# Every build fails. Team adds --exit-code 0 to ignore. Gate is now useless.

# CORRECT: block on critical/reachable only
- run: trivy image --exit-code 1 --severity CRITICAL --ignore-unfixed ...
TEXT
# WRONG: permanent ignore buried in a config file
ignore:
  'CVE-2024-1234': true  # No expiry, no approver, no justification
# This is a silent permanent suppression, not an exception

# CORRECT: time-boxed, approved, expiring exception
ignore:
  'CVE-2024-1234':
    expires: 2024-06-30
    approvedBy: security-team
    justification: "No patch available, WAF rule mitigates"

How do you measure program health?

The key metric is mean-time-to-remediate (MTTR) across the backlog. A healthy program shows MTTR shrinking over time, meaning the backlog is going down, not just new issues being caught.

TEXT
 Dashboard metrics:

 1. Gate block rate       -- how often the gate stops a build (should be low)
 2. False positive rate   -- findings that are not real (should be decreasing)
 3. MTTR by severity      -- how fast findings are fixed (should meet SLAs)
 4. Backlog trend         -- total open findings over time (should be declining)
 5. Exception count       -- active risk acceptances (should be small and shrinking)

What should a senior engineer know?

The senior skill is building a gate that engineers actually trust. It only stops them when stopping them is genuinely warranted: on reachable criticals, on known-exploited vulnerabilities, and on newly introduced highs. Everything else gets tracked with SLAs and driven down over time. Exceptions are formal, expiring, and auditable, so a regulator can ask for every risk acceptance and you can produce the list instantly.

Visual Overview

DIAGRAM
 Security Gate Decision Flow
 =============================

 Scanner Finding
       │
       ▼
 On CISA KEV list? ──Yes──▶ BLOCK BUILD
       │
       No
       │
       ▼
 CVSS >= 9.0 AND reachable? ──Yes──▶ BLOCK BUILD
       │
       No
       │
       ▼
 Newly introduced HIGH? ──Yes──▶ BLOCK BUILD
       │
       No
       │
       ▼
 Has valid exception? ──Yes──▶ PASS (logged)
       │
       No
       │
       ▼
 TRACK: create ticket with SLA
   Critical: 72h
   High: 30d
   Medium: 90d
   Low: 180d

 Exception Lifecycle
 =====================

 Request ──▶ Security Owner Approves ──▶ Exception Active
                                              │
                                         Expiry Date
                                              │
                                              ▼
                                    Gate Re-blocks Automatically
                                              │
                                              ▼
                                    Fix Applied OR New Exception

Key Takeaway

A failing security scan should be able to block the build, but the skill is choosing what to block on. Blocking on every HIGH floods developers with noise and makes them bypass the gate, which is worse than no gate. Block on a combination of severity, reachability, and exploitability: reachable criticals, anything on the CISA KEV list, and newly introduced highs. Pre-existing mediums and lows become tracked tickets with SLAs.

Remediation SLAs by severity give deadlines: Critical within 72 hours, High within 30 days, Medium within 90 days, Low within 180 days. The gate stops new risk from entering; the SLA process drives down the existing backlog. Mean-time-to-remediate is the program health metric.

The exception process keeps the gate both safe and practical. Exceptions must be time-boxed, signed by a security owner (not the developer), and have an expiry date. When the exception expires, the gate re-blocks automatically, forcing a fresh review. This expiry and approval trail is exactly what makes it auditable for regulators.

Remember one sentence: block the build on reachable criticals and known-exploited vulnerabilities, track the rest with SLAs, and allow only time-boxed, signed, expiring exceptions.

---

Share
Use ← → arrow keys to navigate