Proaktiv Sårbarhedsscanning i CI/CD Pipelines

En CI/CD pipeline automatiserer vejen fra kode til produktion – men uden integrerede sikkerhedskontroller er den også en hurtig vej til at sende sårbarheder ud til brugerne. Ved at bygge proaktiv sårbarhedsscanning ind i pipelinen opdages fejl og risici der, hvor de er billigst og hurtigst at rette: i udviklingsprocessen, ikke efter deployment.

Denne tilgang kaldes ofte “Shift Left Security” – et princip om at rykke sikkerhedskontrollen tidligst muligt mod venstre i udviklingsforløbet, frem for at behandle det som en eftertanke til sidst.


Hvad er proaktiv sårbarhedsscanning?

Proaktiv sårbarhedsscanning handler om at identificere og reagere på sikkerhedsrisici automatisk og løbende, frem for at afvente manuelle audits eller hændelser i produktion. I en CI/CD-kontekst betyder det, at scanning aktiveres ved hvert commit, pull request eller deployment – ikke kun kvartalsvis.

De primære scanningstyper, der er relevante i en pipeline, er:

  • SAST (Static Application Security Testing): Analyserer kildekoden uden at eksekvere den. Finder kendte fejlmønstre som SQL Injection, hardcodede secrets og usikre funktionskald direkte i koden.
  • SCA (Software Composition Analysis): Kortlægger alle tredjeparts- og open source-afhængigheder (dependencies) og tjekker dem op mod kendte sårbarhedsdatabaser (f.eks. CVE/NVD). Producerer en Software Bill of Materials (SBOM).
  • Container Image Scanning: Analyserer de container-images der bygges og deployes, for forældede pakker og OS-komponenter med kendte CVE’er.
  • DAST (Dynamic Application Security Testing): Tester en kørende instans af applikationen udefra ved at simulere angreb. Egner sig bedst i staging-miljøer.
  • IaC Scanning: Analyserer infrastrukturkode for sikkerhedsmæssige fejlkonfigurationer, inden ressourcerne provisioners i skyen (se nedenfor).
  • Secrets Detection: Søger systematisk efter utilsigtet eksponerede nøgler, tokens, adgangskoder og certifikater i kodebasen og dens historik.

Integrering i pipeline-stadierne

En robust sikkerhedspipeline benytter sig af et lagdelt forsvar (Defense in Depth), hvor scanning sker i flere uafhængige stadier. Nedenfor er en teknologineutral model:

[Commit / Pull Request]


┌───────────────────┐
│  1. Code Stage    │  ← SAST, Secrets Detection, Linting
└───────────────────┘


┌───────────────────┐
│  2. Build Stage   │  ← SCA (dependency check), Container Image Scan
└───────────────────┘


┌───────────────────┐
│  3. IaC Stage     │  ← IaC Scanning (Policy-as-Code)
└───────────────────┘


┌───────────────────┐
│  4. Test Stage    │  ← DAST mod staging-miljø
└───────────────────┘


┌───────────────────┐
│  5. Deploy Stage  │  ← Deployment til produktion (gate: alle tjek bestået)
└───────────────────┘

Vigtige principper for integrationen

  • Fail fast: Kritiske fund bør stoppe pipelinen (breaking change). Lave-risiko fund kan logges som advarsler uden at blokere.
  • Definér en “Quality Gate”: En klar politik for, hvad der tillades at passere til produktion (f.eks. ingen kritiske CVE’er i dependencies, ingen eksponerede secrets).
  • Behandl fund som teknisk gæld: Resultater fra scanninger bør automatisk oprette tickets i projektets issue-tracker, så de behandles systematisk.
  • Undgå “alert fatigue”: Konfigurér scanners med relevante regler for konteksten. En lang liste af falske positiver læres hurtigt at ignorere.

Infrastructure as Code (IaC) og sårbarhedsscanning

Infrastructure as Code (IaC) er praksisset med at definere og provisionere infrastruktur (servere, netværk, cloud-ressourcer) via maskinlæsbare konfigurationsfiler frem for manuelle klik i en konsol. Populære paradigmer er deklarative skabeloner og imperativ kode til cloud-udbydere.

Fordi IaC-filer beskriver hele infrastrukturens tilstand, rummer de også et enormt potentiale for fejlkonfiguration. Klassiske eksempler:

  • En storage bucket konfigureret med offentlig adgang i stedet for privat.
  • En firewall-regel der åbner port 22 (SSH) for hele internettet (0.0.0.0/0).
  • En virtuel maskine der deployes uden diskkryptering aktiveret.
  • En IAM-rolle med overskydende rettigheder, der overtræder Least Privilege-princippet.
  • Manglende aktivering af audit-logging på kritiske tjenester.

IaC Scanning med Policy-as-Code

IaC scanning analyserer konfigurationsfilerne statisk – det vil sige inden ressourcerne overhovedet oprettes. Det er den samme “Shift Left”-logik anvendt på infrastrukturen: billigst og hurtigst at rette en fejlkonfiguration i en fil, frem for i en kørende cloud-ressource.

Scanning foretages typisk ved at sammenligne konfigurationen med et sæt sikkerhedspolicies. Disse policies kan udtrykkes som kode (Policy-as-Code), der giver følgende fordele:

  • Versioneret og reviewbart: Policies lever i Git som al anden kode og kan gennemgå code review.
  • Konsistent håndhævelse: Den samme policy køres identisk i udviklermiljøet, i pipelinen og i compliancetjek.
  • Automatiseret: Ingen manuel gennemgang af konfigurationsfiler er nødvendig.

Eksempel på en policy (pseudokode)

# Policy: Ingen storage buckets må have offentlig adgang
rule "deny_public_storage_bucket" {
  resource = storage_bucket
  condition = resource.access_control != "public"
  severity  = CRITICAL
  message   = "Storage bucket må ikke have offentlig adgang. Brug private adgangskontroller og signerede URL'er."
}

Når IaC-scanneren evaluerer infrastrukturkoden mod denne policy og finder en bucket med access_control = "public", fejler pipelinen – og fejlkonfigurationen når aldrig produktion.

Scanning som en del af pull request-flowet

En effektiv måde at integrere IaC-scanning på er som en status check på pull requests. Når en udvikler åbner et PR med ændringer til infrastrukturkoden:

  1. Scanneren aktiveres automatisk.
  2. Fund annoteres direkte i kode-differencen i PR’et.
  3. PR’et kan ikke merges, inden kritiske fund er løst.

Dette skaber en naturlig feedback-loop: udvikleren ser resultatet i sin normale arbejdsgang og retter det, inden koden merges til main-branchen.


Kontinuerlig scanning (Continuous Monitoring)

Pipeline-scanning dækker nyt kode – men hvad med eksisterende infrastruktur og afhængigheder?

  • Afhængighedsscanning: Mange scanningsværktøjer understøtter planlagte kørsler (f.eks. dagligt), der tjekker om eksisterende dependencies har fået nye CVE’er siden sidst.
  • Cloud Security Posture Management (CSPM): Overvåger løbende de faktiske kørende cloud-ressourcer og sammenligner dem med compliance-baselines og sikkerhedspolicies – opdager “configuration drift”, altså afvigelser fra den ønskede tilstand.
  • Renovering og automatiske opdateringsforslag: Automatiserede bots kan oprette pull requests med opdaterede dependency-versioner, der løser kendte CVE’er.

Nøgleprincipper at huske

PrincipBeskrivelse
Shift LeftRyk sikkerhedskontrollen tidligst muligt i udviklingsprocessen
Fail FastBlokér pipelinen ved kritiske fund – stop problemer tidligt
Policy-as-CodeUdtryk og versionér sikkerhedspolicies som kode
Defense in DepthAnvend flere uafhængige scanningslag
Least PrivilegeIaC-ressourcer og pipelines bør kun have minimale nødvendige rettigheder
SBOMVedligehold en Software Bill of Materials over alle afhængigheder

Opsummering

Proaktiv sårbarhedsscanning i en CI/CD pipeline er ikke et enkelt værktøj – det er en strategi og en kulturændring mod at betragte sikkerhed som et kontinuerligt teknisk krav frem for et periodisk audit. Ved at kombinere SAST, SCA, container-scanning, IaC-scanning og secrets detection i et lagdelt pipelinedesign reduceres angrebsfladen markant, og sikkerhedsansvaret forankres i de teams, der skriver koden og definerer infrastrukturen.

Infrastructure as Code giver en unik mulighed: infrastrukturen kan nu sikkerheds-reviewes ligesom applikationskode, i det samme repository, med de samme processer.


Relaterede Artikler og Noter

Kilder

> Quiz: Test din viden

1. Hvad betyder sikkerhedsprincippet Shift Left i CI/CD?

2. Hvilken scanningstype analyserer kildekode uden at køre applikationen?

3. Hvilken scanningstype kortlægger tredjepartsafhængigheder og kendte CVEer?

4. Hvad kaldes en maskinlæsbar oversigt over softwarekomponenter i en build?