Skip to content

Security Gate silently passes with 0 container vulnerabilities due to file naming pattern mismatch #362

@WilliamBerryiii

Description

@WilliamBerryiii

Summary

Invoke-SecurityGate.ps1 reports 0 container vulnerabilities and PASSES even when Invoke-ContainerSecurityScan.ps1 has found vulnerabilities (e.g., 34 including 1 critical during build #4810). The aggregate security gate is completely blind to container scan results.

Root Cause

File naming pattern mismatch between the scanner and the gate:

Component Pattern Example
Invoke-ContainerSecurityScan.ps1 writes ${ImageName}-${ImageTag}-${timestamp}.json mqtt-tools/mqtt-otel-trace-exporter-4810-20250115-143022.json
Invoke-SecurityGate.ps1 searches for grype-*.json Never matches scanner output

The scanner never prefixes output files with grype-, so Get-GrypeScanResult returns an empty array, ContainerFindings = 0, and the gate passes.

Secondary Issue: Forward Slash in ImageName

ApplicationBuilder.Build.psm1 passes ImageName values like mqtt-tools/mqtt-otel-trace-exporter (containing /). When Join-Path computes the output path, this creates a subdirectory under security-reports/:

./security-reports/mqtt-tools/mqtt-otel-trace-exporter-4810-20250115-143022.json

Even if the grype- prefix were corrected, the first glob $ResultsPath/grype-*.json would miss files in subdirectories. The recursive ** pattern may work but is fragile.

Minor Typo

In Invoke-SecurityGateEvaluation, the variable is named $gryteFindings instead of $grypeFindings (cosmetic but contributes to maintenance confusion).

Data Flow

  1. Pipeline triggers Application-Builder.ps1 → Phase 7 calls Invoke-SecurityScan
  2. Invoke-ContainerSecurityScan.ps1 runs Grype, writes results as ${ImageName}-${ImageTag}-${timestamp}.json (no grype- prefix)
  3. Security Gate step (runs with condition: always()) calls Invoke-SecurityGate.ps1
  4. Gate searches for grype-*.json → finds 0 files → reports 0 container vulnerabilitiesPASSES

Additional Finding: Dead breakBuild Parameter

application-build-template.yml defines a breakBuild boolean parameter (default: false) but it is never referenced in the template body. Build-breaking is controlled by the hardcoded -ExitOnFailure $true on the Security Gate step. This parameter should either be wired to -ExitOnFailure or removed.

Severity

Critical — The aggregate security gate is completely blind to container vulnerabilities. During build #4810, 34 vulnerabilities (1 critical, 9 high, 21 medium, 3 low) in the mqtt-otel-trace-exporter CBL-Mariner 2.0 base image were invisible to the gate. The per-image scan in Application-Builder correctly failed the build, but the aggregate gate is the intended enforcement point.

Recommended Fix

Option A (Preferred): Fix scanner output naming

In Invoke-ContainerSecurityScan.ps1, Invoke-GrypeScan function:

# Current
$reportBaseName = "${ImageName}-${ImageTag}-${timestamp}"

# Fix: Add grype- prefix and sanitize slashes
$sanitizedImageName = $ImageName -replace '[/\\]', '-'
$reportBaseName = "grype-${sanitizedImageName}-${ImageTag}-${timestamp}"

Option B: Fix gate search pattern (more fragile)

Update Get-GrypeScanResult to search *.json with content-based filtering.

Option C (Recommended): Both changes for defense in depth

Apply Option A and ensure the gate also supports recursive discovery.

Also Fix

  • Wire breakBuild parameter to -ExitOnFailure or remove the dead parameter
  • Fix $gryteFindings typo to $grypeFindings
  • Audit Get-CheckovScanResult and Get-DependencyAuditResult for the same class of naming mismatch bug

Affected Files

  • scripts/security/Invoke-SecurityGate.ps1Get-GrypeScanResult glob pattern
  • scripts/security/Invoke-ContainerSecurityScan.ps1Invoke-GrypeScan output naming
  • scripts/build/modules/ApplicationBuilder.Build.psm1Invoke-SecurityScan passes ImageName with /
  • .azdo/templates/application-build-template.yml — Dead breakBuild parameter, Security Gate step

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecuritySecurity-related changes or concerns

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions