08 - DevSecOps dla programistów: SAST, DAST i bezpieczeństwo w rurociągu CI/CD
W lutym 2024 r. badacz bezpieczeństwa zademonstrował, w jaki sposób doszło do kompromisu tj-actions/changed-files, akcja GitHub używana przez ponad 23 000 repozytoriów, umożliwiło wydobycie tajemnic z systemów CI/CD tysięcy organizacji. Problem nie tkwił w kodzie aplikacji, nie w zależnościach, był w przygotowaniu samo: narzędzie, które miało chronić oprogramowanie, stało się wektorem ataku.
Ten scenariusz odzwierciedla niewygodną prawdę: większość zespołów inwestuje w bezpieczeństwo kodu aplikacji, ale zaniedbuje bezpieczeństwo infrastruktury CI/CD, która ją buduje, testuje i rozpowszechnia. DevSecOps to nie tylko integracja niektórych narzędzi skanujących z potokiem, ale zasadnicza zmiana podejścia: bezpieczeństwo musi stanowić integralną część każdego etapu cyklu rozwojowego, a nie końcową kontrolę przed wydaniem.
Jak wynika z raportu DORA 2025, zespoły stosujące kompleksowe praktyki DevSecOps zgłaszają: Średni czas naprawy (MTTR) krytycznych luk w zabezpieczeniach jest 4 razy krótszy w porównaniu do zespołów, które wykonują tylko testy bezpieczeństwa na etapie testowania lub produkcji. Koszt naprawianie błędu bezpieczeństwa w produkcji i średnio 100 razy więcej niż popraw to podczas programowania: zasada „przesuń w lewo” ma uzasadnienie ekonomiczne solidny i techniczny.
Czego się nauczysz
- Bezpieczeństwo z przesunięciem w lewo: Zintegruj bezpieczeństwo od początku cyklu programistycznego
- SAST z Semgrep i CodeQL: analiza statyczna kodu źródłowego
- DAST z OWASP ZAP: Testowanie dynamiczne działających aplikacji
- SCA z Snyk i Trivy: Analiza składu oprogramowania pod kątem zależności
- Skanowanie sekretów za pomocą Gitleaks i TruffleHog: zapobieganie wyciekom danych uwierzytelniających
- Bezpieczeństwo IaC z Checkovem: skanowanie manifestów Terraform i Kubernetes
- Kompletny potok akcji GitHub z bramkami bezpieczeństwa
- Metryki i KPI do pomiaru dojrzałości DevSecOps
Bezpieczeństwo z przesunięciem w lewo: podstawowa zasada
Termin „przesunięcie w lewo” pochodzi od wizualnego przedstawienia cyklu rozwojowego w postaci linii oś czasu od lewej (planowanie, rozwój) do prawej (testowanie, produkcja). Przesuń Bezpieczeństwo po lewej stronie oznacza przeniesienie kontroli bezpieczeństwa jak najbliżej moment, w którym pisany jest kod: w IDE programisty, w haku przed zatwierdzeniem, w pliku żądania ściągnięcia, nie tylko w środowisku przejściowym.
Poziomy bezpieczeństwa z przesunięciem w lewo, od najbardziej reaktywnego do najbardziej proaktywnego, są następujące:
- Poziom 0 - Produkcja: skanowanie podatności tylko w prod. Późno, drogo.
- Poziom 1 – Inscenizacja/przedprodukcja: DAST w środowisku testowym. Lepiej, ale nadal wolno.
- Poziom 2 – Rurociąg CI/CD: SAST, SCA, skanowanie sekretów przy każdym naciśnięciu. Standardy DevSecOps.
- Poziom 3 – Żądanie ściągnięcia: automatyczny przegląd bezpieczeństwa każdego PR. Szybko i kontekstowo.
- Poziom 4 – Wstępne zatwierdzenie: lokalne kontrole przed zatwierdzeniem. Natychmiastowa informacja zwrotna.
- Poziom 5 – BIZ: Wtyczka bezpieczeństwa w edytorze (Snyk IDE, rozszerzenie CodeQL). W czasie rzeczywistym.
Paradoks 45%.
Badania Veracode i GitLab pokazują, że 45% kodu jest generowane przez narzędzia AI (GitHub Copilot, Cursor, Claude Code) ma luki w zabezpieczeniach, które mogłyby zakończyć się niepowodzeniem podstawowe testy bezpieczeństwa. Nie dlatego, że sztuczna inteligencja jest sama w sobie niebezpieczna, ale dlatego, że się replikuje niepewne wzorce kodu obecne w zbiorach danych szkoleniowych. To sprawia, że kontrole zautomatyzowane w CI/CD, co jest jeszcze ważniejsze w erze kodowania wibracyjnego i wspomagania AI rozwój. Zobacz serię Kodowanie Vibe zagłębić się w ten temat.
SAST: statyczne testowanie bezpieczeństwa aplikacji
SAST analizuje kod źródłowy, bajtowy lub binarny bez uruchamiania aplikacji, szukanie podatnych na ataki wzorców kodu, błędnych konfiguracji i antywzorców bezpieczeństwa. Jest to najszybsza kontrola (można ją wykonać w ciągu kilku sekund lub minut) i można ją zintegrować bezpośrednio w IDE, w haku przed zatwierdzeniem i w potoku CI/CD.
Główne zalety SAST w porównaniu z innymi podejściami to: Działa na kodzie źródłowym (nie wymaga działającej instancji aplikacji), najpierw identyfikuje podatności wdrożenia i może analizować 100% kodu, w tym rzadko wykonywane ścieżki kodu. Główną wadą jest odsetek wyników fałszywie dodatnich, który wymaga procesu selekcji i dostrojenie zasad.
Semgrep: SAST Open Source i szybko
Semgrep jest prawdopodobnie najczęściej używanym narzędziem SAST w ekosystemie open source w 2025 roku.
Jego siła tkwi w prostej składni reguł (struktura niemal identyczna z kodem
który analizuje), szybkości wykonywania i natywnej obsługi TypeScript, JavaScript,
Python, Go, Java i wiele innych języków. Utrzymuje tysiące reguł bezpieczeństwa w
oficjalny rejestr semgrep.dev.
# Installazione Semgrep
pip install semgrep
# oppure con Homebrew
brew install semgrep
# Scansione base con ruleset OWASP
semgrep --config p/owasp-top-ten .
# Scansione con regole specifiche per JavaScript/TypeScript
semgrep --config p/javascript .
semgrep --config p/typescript .
# Regole per Angular/Node.js
semgrep --config p/nodejs-express-security .
semgrep --config p/jwt .
# Output in formato SARIF per GitHub Security tab
semgrep --config p/owasp-top-ten --sarif --output semgrep.sarif .
# Output JSON per processing automatico
semgrep --config p/owasp-top-ten --json --output semgrep.json .
# Escludi cartelle non rilevanti
semgrep --config p/owasp-top-ten \
--exclude="node_modules,dist,coverage,*.min.js" .
# Regola custom Semgrep per trovare JWT senza verifica della firma
# .semgrep/jwt-insecure.yaml
# rules:
# - id: jwt-decode-without-verify
# patterns:
# - pattern: jwt.decode($TOKEN, ...)
# - pattern-not: jwt.verify($TOKEN, ...)
# message: "Uso di jwt.decode senza verifica: usa jwt.verify"
# severity: ERROR
# languages: [javascript, typescript]
CodeQL: Głęboka analiza semantyczna
CodeQL, opracowany przez GitHub, przeprowadza głębszą analizę niż Semgrep: buduje bazę danych kodów i umożliwia pisanie zapytań w języku SQL do wyszukiwania podatność również poprzez wiele poziomów wywołań funkcji (analiza skażeń). LinkedIn ogłosił w lutym 2026 r., że w pewnym sensie korzysta zarówno z CodeQL, jak i Semgrep uzupełnienie dla optymalnego pokrycia bazy kodu. CodeQL jest natywnie zintegrowany z GitHub Advanced Security i jest dostępny bezpłatnie dla repozytoriów publicznych.
# .github/workflows/codeql.yml
name: CodeQL Security Analysis
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
# Analisi settimanale (domenica alle 2:00 UTC)
- cron: '0 2 * * 0'
permissions:
contents: read
security-events: write
actions: read
jobs:
codeql-analysis:
name: CodeQL Analysis
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: ['javascript-typescript']
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Initialize CodeQL
uses: github/codeql-action/init@dd746615b1a4b1e1c5d3b87432fe040f4c04082 # v3.28.0
with:
languages: {{ matrix.language }}
# Query suite: default, extended, security-extended
queries: security-extended
config: |
paths-ignore:
- node_modules
- dist
- '**/*.test.ts'
- '**/*.spec.ts'
- name: Autobuild
uses: github/codeql-action/autobuild@dd746615b1a4b1e1c5d3b87432fe040f4c04082 # v3.28.0
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@dd746615b1a4b1e1c5d3b87432fe040f4c04082 # v3.28.0
with:
category: "/language:{{ matrix.language }}"
upload: true
SAST: Fałszywie pozytywne i segregacja
Głównym problemem SAST jest liczba fałszywych alarmów: agresywny zestaw reguł może wygenerować setki raportów dla każdego zatwierdzenia, co czyni proces niezrównoważonym. Zalecaną strategią jest rozpoczęcie od profilu o wysokiej istotności (tylko KRYTYCZNY/WYSOKI), adjust the rules for your specific codebase, and progressively increase the zasięg, gdy zespół zapoznaje się z narzędziem. Nigdy nie blokuj kompilacji dla NISKIEGO/ŚREDNIEGO bez ustalonego procesu segregacji.
DAST: Dynamiczne testowanie bezpieczeństwa aplikacji
Podczas gdy SAST analizuje kod bez jego wykonywania, DAST testuje aplikację w trakcie i w trakcie działania wykonanie, symulując prawdziwe ataki z zewnątrz, tak jak zrobiłby to atakujący. DZIEŃ znajduje luki, których SAST nie widzi: problemy z konfiguracją serwera, zachowania w czasie wykonywania, luki w interfejsach API REST i problemy z uwierzytelnianiem pojawiają się tylko z prawdziwymi żądaniami HTTP.
DAST uzupełnia SAST, a nie zastępuje: SAST znajduje 70–80% luk w zabezpieczeniach w kodzie źródłowym DAST znajduje pozostałe 20-30%, które pojawia się dopiero w czasie wykonywania. Dla jednego pełne pokrycie, oba są konieczne.
OWASP ZAP: Standard DAST w ekosystemie Open Source
OWASP ZAP (Zed Attack Proxy) jest najczęściej używanym narzędziem DAST w świecie open source natywna integracja z GitHub Actions. Oferuje trzy główne tryby CI/CD: skanowanie podstawowe (pasywny, nieinwazyjny, idealny dla każdego PR), pełne skanowanie (aktywny, wykorzystuje ładunki prawdziwego ataku, tylko w izolowanych środowiskach) tj Skanowanie API (specjalizuje się w OpenAPI/Swagger, idealny do mikroserwisów).
# .github/workflows/dast-zap.yml
name: DAST Security Scan (OWASP ZAP)
on:
push:
branches: [main]
workflow_dispatch:
inputs:
target_url:
description: 'URL target per la scansione DAST'
required: true
default: 'https://staging.myapp.com'
permissions:
contents: read
issues: write # ZAP crea issues GitHub per le vulnerabilità trovate
jobs:
zap-baseline-scan:
name: OWASP ZAP Baseline Scan
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Baseline scan: scansione PASSIVA (non invia payload di attacco)
# Ideale per ogni PR/push - veloce e non invasivo
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.14.0
with:
target: 'https://staging.myapp.com'
rules_file_name: '.zap/rules.tsv'
fail_action: true
cmd_options: '-a -j -l WARN'
# Full scan: scansione ATTIVA (usa payload di attacco reali)
# Solo in ambienti di test isolati, mai in produzione!
# - name: ZAP Full Scan (staging only)
# uses: zaproxy/action-full-scan@v0.11.0
# with:
# target: 'https://staging-isolated.myapp.com'
# API Scan: specializzato per REST API con OpenAPI spec
# - name: ZAP API Scan
# uses: zaproxy/action-api-scan@v0.9.0
# with:
# target: 'https://api.staging.myapp.com/openapi.json'
- name: Upload ZAP Report
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.0
if: always()
with:
name: zap-report
path: report_html.html
# .zap/rules.tsv - personalizzazione regole ZAP
# ID ACTION PARAM
# 10015 WARN # Incomplete or No Cache-control Header Set
# 10038 IGNORE # CSP Header Not Set (gestito separatamente dal server)
# 10096 WARN # Timestamp Disclosure
# 40014 IGNORE # CSRF (se il token CSRF e implementato lato app)
W przypadku projektów Angular z SSR, DAST musi działać na osiągalnej instancji z rurociągu. Skuteczna strategia i wdrożenie w efemerycznym środowisku przejściowym (na przykład w kanale podglądu hostingu Firebase) jako część potoku, uruchom DAST i kontynuuj wdrażanie w środowisku produkcyjnym tylko wtedy, gdy DAST przejdzie pomyślnie.
# Esempio: Deploy staging effimero + DAST in pipeline Angular
# .github/workflows/angular-devsecops.yml (estratto)
jobs:
deploy-staging:
runs-on: ubuntu-latest
outputs:
staging_url: {{ steps.deploy.outputs.details_url }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- run: npm ci --ignore-scripts
- run: npm run build --configuration=staging
- name: Deploy to Firebase Hosting preview channel
id: deploy
uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: {{ secrets.GITHUB_TOKEN }}
firebaseServiceAccount: {{ secrets.FIREBASE_SERVICE_ACCOUNT }}
channelId: staging-{{ github.run_id }}
expires: 1d
dast-scan:
needs: deploy-staging
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: ZAP Baseline Scan on ephemeral staging
uses: zaproxy/action-baseline@v0.14.0
with:
target: {{ needs.deploy-staging.outputs.staging_url }}
fail_action: true
rules_file_name: '.zap/rules.tsv'
SCA: Analiza składu oprogramowania
SCA (Analiza składu oprogramowania) analizuje zależności aplikacji typu open source w celu zidentyfikowania znanych luk w zabezpieczeniach (CVE), problemów z licencjami i przestarzałych pakietów. Poprzedni artykuł z serii ( Bezpieczeństwo łańcucha dostaw: audyt npm i SBOM) szczegółowo omawia audyt npm, Snyk, Depabot i generowanie SBOM. W tym kontekście skupiamy się na Trivy, która oferuje skanowanie SCA i IaC w jednym narzędzie, idealne do ujednoliconych potoków DevSecOps.
# Trivy: SCA + container + IaC in un unico tool
# Installazione
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh \
| sh -s -- -b /usr/local/bin
# Scansione dipendenze npm (SCA)
trivy fs --scanners vuln --pkg-types library .
# Solo vulnerabilità HIGH e CRITICAL (per security gate)
trivy fs --scanners vuln --severity HIGH,CRITICAL \
--pkg-types library --exit-code 1 .
# Output SARIF per GitHub Security tab
trivy fs --scanners vuln --format sarif \
--output trivy-results.sarif .
# Scansione con SBOM output (CycloneDX)
trivy fs --format cyclonedx --output sbom.json .
# File .trivyignore per CVE accettati (con motivazione obbligatoria!)
# .trivyignore
# CVE-2023-44270 # postcss: impatto solo in CLI, non nel build output - review 2026-06-01
# Scansione completa: vuln + segreti + misconfigurazioni
trivy fs --scanners vuln,secret,misconfig .
# GitHub Actions con Trivy Action ufficiale
# - name: Run Trivy vulnerability scanner
# uses: aquasecurity/trivy-action@d43c1f16c00cfd3978dde6c07f4bbcf9eb6993ca
# with:
# scan-type: 'fs'
# scan-ref: '.'
# scanners: 'vuln,secret'
# severity: 'HIGH,CRITICAL'
# exit-code: '1'
# format: 'sarif'
# output: 'trivy-results.sarif'
Skanowanie sekretów: zapobieganie wyciekom danych uwierzytelniających
Co tydzień tysiące tajemnic zostaje przypadkowo ujawnionych w publicznym GitHubie: Klucze API, tokeny OAuth, hasła do baz danych, certyfikaty prywatne. GitGuardian, który monitoruje repozytoria publiczne, podaje, że w 2024 roku wykryto ich ponad 12 milionów tajemnic ujawnionych w repozytoriach publicznych, co stanowi wzrost o 28% w porównaniu z rokiem poprzedni. Gdy sekret znajdzie się w publicznym repozytorium (nawet na kilka minut przed usunięciem), należy uznać za zagrożone i natychmiast je obrócić.
Gitleaks i TruffleHog to dwa najczęściej używane narzędzia do wykrywania tajemnic, wraz z podejściami uzupełnienie: Gitleaks jest szybki i świetny do CI/CD, TruffleHog aktywnie sprawdza czy znalezione tajemnice są nadal ważne (znacznie zmniejsza liczbę fałszywych alarmów).
Gitleaks: konfiguracja i integracja
# Installazione Gitleaks
brew install gitleaks
# oppure scarica il binario da GitHub Releases
# https://github.com/gitleaks/gitleaks/releases
# Scansione del repository corrente (tutti i commit)
gitleaks detect --source . --verbose
# Scansione solo dei file staged (per pre-commit hook)
gitleaks protect --staged --verbose
# Scansione di un range di commit specifico
gitleaks detect --source . --log-opts HEAD~1..HEAD
# Output in formato JSON
gitleaks detect --source . --report-format json \
--report-path gitleaks-report.json
# Configurazione pre-commit con pre-commit framework
# .pre-commit-config.yaml
# repos:
# - repo: https://github.com/gitleaks/gitleaks
# rev: v8.24.2
# hooks:
# - id: gitleaks
# Configurazione custom .gitleaks.toml
# [extend]
# useDefault = true
#
# [[rules]]
# id = "internal-api-token"
# description = "Token API interno MyCompany"
# regex = '''mycompany_token_[0-9a-zA-Z]{32}'''
# tags = ["token", "internal"]
#
# [allowlist]
# description = "Test fixtures e placeholder sicuri"
# regexTarget = "line"
# regexes = [
# '''EXAMPLE_TOKEN_PLACEHOLDER''',
# '''test_secret_[a-z0-9]{8}'''
# ]
# paths = [
# '''.*_test\.ts''',
# '''.*\.spec\.ts''',
# '''.*\.fixture\.ts'''
# ]
TruffleHog: Aktywna weryfikacja tajnego
# Installazione TruffleHog
curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh \
| sh -s -- -b /usr/local/bin
# Scansione con verifica attiva (riduce falsi positivi)
trufflehog git file://. --only-verified
# Scansione di un repository remoto
trufflehog github --repo https://github.com/myorg/myrepo --only-verified
# Output JSON per processing
trufflehog git file://. --json --no-verification
# GitHub Actions: secrets scanning su ogni push/PR
# .github/workflows/secrets-scan.yml
# - name: TruffleHog secrets scan
# uses: trufflesecurity/trufflehog@main
# with:
# path: ./
# base: $GITHUB_BASE_REF
# head: HEAD
# extra_args: --only-verified
# Differenza chiave Gitleaks vs TruffleHog:
# - Gitleaks: veloce, pattern matching, ottimo per pre-commit e CI
# - TruffleHog: verifica attiva (testa il secret contro l'API reale)
# Risultato: meno falsi positivi, ma più lento e invasivo
# Raccomandazione: entrambi in pipeline (Gitleaks fast, TruffleHog verified)
Sekrety nie są usuwane za pomocą git rm
Jeśli sekret został popełniony przez pomyłkę, usuń plik za pomocą git rm lub
dodaj plik do .gitignore to za mało: tajemnica wciąż istnieje
widoczne w historii gita. Aby naprawdę go usunąć, użyj git filter-repo
(narzędzie oficjalnie zalecane przez GitHub), a następnie wymuś push na wszystkich gałęziach,
uważaj, że tajemnica została naruszona i natychmiast ją zmieniaj. GitHub oferuje również
natywne narzędzie „Skanowanie tajne” w monitorowanych przez siebie ustawieniach repozytorium
stale zatwierdzaj historię dla ponad 200 znanych typów tokenów.
IaC Security: Checkov dla Terraform i Kubernetes
Infrastruktura jako kod (IaC) zdemokratyzowała zarządzanie infrastrukturą, ale tak się stało wprowadził także nowy wektor ryzyka: błędne konfiguracje w plikach Terraform, Kubernetes manifests, Docker Compose i AWS CloudFormation, które mogą ujawnić całą infrastrukturę. Checkov (Bridgecrew/Palo Alto Networks) skanuje statycznie te pliki za pomocą ponad 1000 Zintegrowane zasady bezpieczeństwa, odwzorowane na wzorce CIS, NIST i inne standardy.
Uwaga: zintegrowane zostało tfsec, oryginalne narzędzie do skanowania IaC firmy Aqua Security w Trivy. W przypadku nowych projektów zaleca się Trivy for IaC lub Checkov dla szerszego zasięgu.
# Installazione Checkov
pip install checkov
# oppure con Homebrew
brew install checkov
# Scansione directory Terraform
checkov -d ./terraform
# Scansione Kubernetes manifests
checkov -d ./k8s --framework kubernetes
# Scansione Dockerfile
checkov -f Dockerfile --framework dockerfile
# Output in formato SARIF per GitHub Security
checkov -d ./terraform --output sarif --output-file checkov.sarif
# Skippa check specifici (con commento di motivazione!)
checkov -d ./terraform --skip-check CKV_AWS_18,CKV_AWS_21
# Violazioni Terraform AWS comuni che Checkov rileva:
# CKV_AWS_18: S3 bucket - access logging disabilitato
# CKV_AWS_57: S3 bucket - ACL pubblica (mai in produzione!)
# CKV_AWS_87: Lambda - non in VPC
# CKV_AWS_135: EC2 - IMDSv1 abilitato (usa IMDSv2)
# Esempio Kubernetes manifest INSICURO (violazioni Checkov):
# apiVersion: v1
# kind: Pod
# spec:
# containers:
# - name: app
# image: myapp:latest # CKV_K8S_14: usa tag specifico, non :latest
# securityContext:
# runAsRoot: true # CKV_K8S_6: non eseguire come root
# privileged: true # CKV_K8S_16: non usare privileged mode
# resources: {} # CKV_K8S_11: definisci resource limits
# Esempio Kubernetes manifest SICURO (supera Checkov):
# spec:
# containers:
# - name: app
# image: myapp:1.2.3
# securityContext:
# runAsNonRoot: true
# runAsUser: 1000
# allowPrivilegeEscalation: false
# readOnlyRootFilesystem: true
# resources:
# limits:
# memory: "256Mi"
# cpu: "500m"
# requests:
# memory: "128Mi"
# cpu: "250m"
Ukończono potok działań GitHub: najlepsza brama bezpieczeństwa
Zintegrowanie wszystkich tych narzędzi w jeden spójny rurociąg wymaga planowania bądź ostrożny: nie wszystkie zadania muszą blokować kompilację, niektóre skany są bardziej odpowiednie dla PR, podczas gdy inne dla push on main, a równoległość jest podstawą dla non nadmiernie spowalniają rozwój. Poniższy potok ilustruje jeden z nich pełna konfiguracja z 6 zadaniami równoległymi i sekwencyjnymi.
# .github/workflows/devsecops-complete.yml
name: DevSecOps Security Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
schedule:
- cron: '0 3 * * 1' # Ogni lunedi alle 3:00 UTC (scan completo)
# Permissions minime a livello workflow (principio del minimo privilegio)
permissions:
contents: read
jobs:
# ===== JOB 1: SECRETS SCANNING (primo - fail fast) =====
secrets-scan:
name: Secrets Scanning
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0 # Storia completa per Gitleaks
- name: Gitleaks secrets detection
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: {{ secrets.GITHUB_TOKEN }}
# ===== JOB 2: SCA - Dependency Vulnerabilities =====
sca-scan:
name: SCA Dependency Audit
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: '22'
cache: 'npm'
- run: npm ci --ignore-scripts
- name: npm audit (solo production deps)
run: npm audit --audit-level=high --omit=dev
- name: Trivy SCA scan
uses: aquasecurity/trivy-action@d43c1f16c00cfd3978dde6c07f4bbcf9eb6993ca
with:
scan-type: 'fs'
scan-ref: '.'
scanners: 'vuln'
severity: 'HIGH,CRITICAL'
exit-code: '1'
format: 'sarif'
output: 'trivy-vuln.sarif'
- name: Upload Trivy results
uses: github/codeql-action/upload-sarif@dd746615b1a4b1e1c5d3b87432fe040f4c04082
if: always()
with:
sarif_file: 'trivy-vuln.sarif'
# ===== JOB 3: SAST - Static Code Analysis =====
sast-scan:
name: SAST Static Analysis
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
actions: read
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Initialize CodeQL
uses: github/codeql-action/init@dd746615b1a4b1e1c5d3b87432fe040f4c04082
with:
languages: 'javascript-typescript'
queries: security-extended
- name: Autobuild
uses: github/codeql-action/autobuild@dd746615b1a4b1e1c5d3b87432fe040f4c04082
- name: CodeQL Analysis
uses: github/codeql-action/analyze@dd746615b1a4b1e1c5d3b87432fe040f4c04082
with:
category: "/language:javascript-typescript"
- name: Semgrep SAST
uses: semgrep/semgrep-action@v1
with:
config: >-
p/owasp-top-ten
p/javascript
p/typescript
p/jwt
env:
SEMGREP_APP_TOKEN: {{ secrets.SEMGREP_APP_TOKEN }}
# ===== JOB 4: IaC Security =====
iac-scan:
name: IaC Security Scan
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: Trivy config scan
uses: aquasecurity/trivy-action@d43c1f16c00cfd3978dde6c07f4bbcf9eb6993ca
with:
scan-type: 'config'
scan-ref: '.'
severity: 'HIGH,CRITICAL'
exit-code: '1'
- name: Checkov IaC scan
uses: bridgecrewio/checkov-action@v12
with:
directory: .
framework: all
soft_fail_on: MEDIUM
hard_fail_on: HIGH,CRITICAL
# ===== JOB 5: DAST (solo su push a main) =====
dast-scan:
name: DAST ZAP Baseline
runs-on: ubuntu-latest
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [secrets-scan, sca-scan, sast-scan]
permissions:
contents: read
issues: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- name: ZAP Baseline Scan
uses: zaproxy/action-baseline@v0.14.0
with:
target: {{ secrets.STAGING_URL }}
fail_action: true
- name: Upload ZAP Report
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1
if: always()
with:
name: zap-report-{{ github.sha }}
path: report_html.html
retention-days: 30
# ===== JOB 6: SBOM (su push a main dopo tutti i check) =====
sbom-generate:
name: Generate SBOM
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
needs: [sca-scan, sast-scan, iac-scan]
permissions:
contents: write
id-token: write
attestations: write
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af
with:
node-version: '22'
- run: npm ci --ignore-scripts
- name: Generate SBOM (CycloneDX)
run: |
npm install -g @cyclonedx/cyclonedx-npm
cyclonedx-npm --omit dev \
--output-format json \
--output-file sbom-{{ github.sha }}.json
- name: Attest SBOM
uses: actions/attest-build-provenance@v1
with:
subject-path: sbom-{{ github.sha }}.json
- name: Upload SBOM
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1
with:
name: sbom-{{ github.sha }}
path: sbom-{{ github.sha }}.json
retention-days: 365
Bramy bezpieczeństwa: jakie bloki budują, a co nie
Skuteczna bramka bezpieczeństwa nie blokuje każdego pojedynczego ostrzeżenia, ale rozróżnia problemy wymagające natychmiastowej uwagi i problemy, którymi można zarządzać w miarę upływu czasu. Podstawowa zasada brzmi: blokuje tylko to, co jest wyraźnie niebezpieczne i możliwe do podjęcia. Zablokowanie kompilacji ze względu na zbyt wiele fałszywych alarmów lub luk w zabezpieczeniach LOW prowadzi zespół do wyłączenia całkowicie kontrolować, rujnując całą inwestycję.
Zalecana matryca bram bezpieczeństwa
- Zawsze BLOKUJ: Sekrety w kodzie, KRYTYCZNE luki z poprawką dostępne, wyniki wstrzyknięcia SAST/RCE, błędne konfiguracje IaC KRYTYCZNE (Wiadro publiczne S3, grupa zabezpieczeń 0.0.0.0/0 w ruchu przychodzącym SSH)
- BLOK na głównym (nie na PR): WYSOKA luka w zabezpieczeniach z dostępną poprawką, Wyniki DAST ustawione na FAIL, zależności z niekompatybilnymi licencjami (GPL w produkt komercyjny)
- OSTRZEŻENIE (powiadamia, ale nie blokuje): WYSOKA luka w zabezpieczeniach bez poprawki dostępne, ŚREDNIE w SAST, IaC WYSOKIE z obejściem udokumentowanym w wyjątki, wyniki DAST ustawione na WARN
- ZIGNORUJ (z dokumentacją): Luka LOW/INFO, fałszywe alarmy udokumentowane w pliku wyjątków (.trivyignore, .gitleaks.tomlallowlist), CVE bez rzeczywistego wpływu na konkretny kontekst aplikacji
# Gestione delle eccezioni documentate nei file di configurazione
# .trivyignore - CVE accettati con motivazione obbligatoria
# Formato: CVE-ID # [data] Motivazione e piano di revisione
CVE-2023-44270 # [2026-02-01] postcss: impatto solo in CLI usage, non nel build output. Review 2026-06
# .gitleaks.toml - allowlist per pattern non pericolosi
# [allowlist]
# description = "Test fixtures, placeholder e valori di esempio"
# regexes = [
# '''EXAMPLE_API_KEY_[A-Z0-9]{16}''',
# '''test_secret_placeholder''',
# '''YOUR_TOKEN_HERE'''
# ]
# paths = [
# '''.*\.spec\.ts''',
# '''.*\.fixture\.ts''',
# '''README\.md'''
# ]
# Semgrep - eccezione inline nel codice sorgente
# Aggiungi commento sulla stessa riga per sopprimere un finding
# const regex = new RegExp(userPattern); // nosemgrep: javascript.lang.security.audit.unsafe-regex
# Checkov - soppressione inline nel file Terraform
# resource "aws_s3_bucket" "cdn_assets" {
# bucket = "my-public-cdn-assets"
# #checkov:skip=CKV_AWS_57: Bucket CDN per assets statici pubblici - progettato per essere pubblico
# }
Lista kontrolna Angular: potok DevSecOps
Projekty Angular mają specyficzne uwagi związane z DevSecOps Toolchain (Angular CLI, esbuild, ng-packagr), do wykorzystania szablonów HTML z powiązaniami dynamic i do SSR z serwerem Node.js Express.
# Angular DevSecOps Checklist
# 1. SAST: regole Semgrep specifiche per Angular
# Patterns pericolosi da rilevare:
# - DomSanitizer.bypassSecurityTrustHtml(userInput) senza sanitizzazione
# - [innerHTML]="untrustedData" (binding HTML non sicuro)
# - eval() o new Function() in servizi Angular
# - HttpClient senza interceptor di autenticazione
# 2. SECRETS: environment files NON devono contenere valori reali
# SBAGLIATO - environment.ts committato con secret:
# export const environment = {
# apiKey: 'sk-prod-real-key-12345', # Bloccato da Gitleaks!
# googleMapsKey: 'AIza...' # Bloccato da Gitleaks!
# };
# CORRETTO - placeholder nei file committati, valori iniettati in CI:
# export const environment = {
# apiKey: '', // iniettato a build time dalla pipeline CI/CD
# };
# In pipeline: sed -i "s/apiKey: ''/apiKey: '{{ secrets.API_KEY }}'/" src/environments/environment.prod.ts
# 3. CSP HEADER nel server SSR Angular (Express)
# server.ts
# import { randomBytes } from 'crypto';
# const generateNonce = () => randomBytes(16).toString('base64');
#
# app.use((req, res, next) => {
# const nonce = generateNonce();
# res.locals['nonce'] = nonce;
# res.setHeader('Content-Security-Policy', [
# "default-src 'self'",
# `script-src 'self' 'nonce-${nonce}'`,
# "style-src 'self' 'unsafe-inline'",
# "img-src 'self' data: https:",
# "connect-src 'self' https://api.myapp.com",
# "frame-ancestors 'none'"
# ].join('; '));
# next();
# });
# 4. SAST Semgrep per Angular (regola custom bypassSecurityTrust)
# .semgrep/angular-security.yaml
# rules:
# - id: angular-bypass-security-trust
# patterns:
# - pattern: this.$SANITIZER.bypassSecurityTrust$TYPE(...)
# message: "Uso di bypassSecurityTrust$TYPE: verifica la sanitizzazione del valore"
# severity: WARNING
# languages: [typescript]
# 5. Verifica e aggiornamento Angular LTS
ng version
npm outdated @angular/core @angular/cli @angular/material
npm audit --omit=dev --audit-level=high
Metryki i wskaźniki KPI dotyczące dojrzałości DevSecOps
Pomiary są niezbędne do doskonalenia. Metryki DevSecOps muszą się równoważyć szybkość rozwoju ze skutecznością bezpieczeństwa. Cel nigdy nie jest zerowy podatność na zagrożenia (nieosiągalna), ale redukują ryzyko do akceptowalnego poziomu w możliwie najkrótszym czasie.
Niezbędne wskaźniki KPI DevSecOps
- MTTD (średni czas do wykrycia): średni czas pomiędzy wprowadzeniem jednego podatność i jej wykrywanie. Cel z CI/CD: poniżej 24 godzin. Z pełnym przesunięciem w lewo (przed zatwierdzeniem): wykrywanie w ciągu kilku sekund.
- MTTR (średni czas do naprawy): od wykrycia do korekty w produkcji. Cel OWASP: mniej niż 7 dni dla KRYTYCZNEGO, mniej niż 30 dla WYSOKIEGO. Z dojrzałymi procesami DevSecOps: MTTR 4x niższy niż w przypadku tradycyjnych zespołów.
- Współczynnik wykrywania Shift-Left (SLDR): procent podatności wykryte w fazie rozwoju i produkcji. Cel: ponad 80% wykrytych przed wdrożeniem.
- Dług zabezpieczający: łączna liczba otwartych luk według ważności. Monitoruj trend w czasie: musi się zmniejszać lub pozostać stabilny.
- Wskaźnik wyników fałszywie dodatnich: odsetek fałszywie pozytywnych alertów SAST/DAST. Cel: poniżej 20%, aby nie męczyć zespołu i zachować wiarygodność procesu.
- Czas trwania rurociągu: całkowity czas potoku DevSecOps. Cel: SAST + SCA + sekrety w czasie krótszym niż 10 minut, aby uniknąć wpływu na produktywność.
- Zakres bezpieczeństwa: procent bazy kodu objętej SAST, Procent API objęty DAST. Cel: ponad 90% dla SAST.
# Script per generare un report KPI di sicurezza dal progetto
# Conta vulnerabilità aperte con npm audit
npm audit --json | jq '.metadata.vulnerabilities'
# Output: { "info": 2, "low": 5, "moderate": 3, "high": 1, "critical": 0, "total": 11 }
# Conta findings SAST da Semgrep (JSON output)
semgrep --config p/owasp-top-ten --json . 2>/dev/null \
| jq '.results | group_by(.extra.severity) | map({severity: .[0].extra.severity, count: length})'
# Verifica durata pipeline (GitHub Actions API)
curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$OWNER/$REPO/actions/runs?per_page=10" \
| jq '[.workflow_runs[] | select(.name == "DevSecOps Security Pipeline") | {
run_id: .id,
status: .status,
conclusion: .conclusion,
duration_seconds: ((.updated_at | fromdateiso8601) - (.run_started_at | fromdateiso8601))
}]'
# Badge GitHub Actions per status sicurezza nel README
# 
Kultura DevSecOps: czynnik ludzki
Sama technologia nie wystarczy: DevSecOps wymaga zmiany kulturowej co przekształca bezpieczeństwo z odpowiedzialności wyspecjalizowanego zespołu w odpowiedzialność wspólne dla wszystkich programistów. Wymaga to szkoleń, jasnych procesów, a przede wszystkim usunięcie tarcia, które sprawia, że bezpieczeństwo jest postrzeganą przeszkodą, a nie przeszkodą narzędzie jakości.
Podstawowe zasady dojrzałej kultury DevSecOps to:
- „Bezpieczeństwo jako kod”: Zasady bezpieczeństwa są kodowane i wersjonowane w git, przejrzana jak każda inna zmiana bazy kodu. Wyjątki od zasad są udokumentowane w samym kodeksie, wraz z uzasadnieniem i datą rewizji.
- Natychmiastowa i kontekstowa informacja zwrotna: deweloper otrzymuje informację zwrotną od bezpieczeństwo w IDE lub PR, a nie tygodnie później w niezrozumiałym raporcie PDF. Kontekst jest kluczowy: „w tej funkcji występuje problem z iniekcją SQL w linii 42” i znacznie bardziej przydatne niż „wykryto podatność typu A07 w module zaplecza”.
- Żadnego obwiniania, tak uczenia się: W CI/CD znaleziono luki możliwości uczenia się, a nie kary. Deweloper, który je wprowadził musimy zrozumieć, dlaczego i jak zapobiegać im w przyszłości.
- Program mistrza bezpieczeństwa: każdy zespół ma mistrza bezpieczeństwa, który działa jako pomost między zespołem programistów a zespołem ds. bezpieczeństwa, dokonuje wstępnej selekcji alertów i promuje najlepszych praktyk w sposób kontekstowy.
- Prewencyjne modelowanie zagrożeń: przed wdrożeniem funkcji, zespół omawia potencjalne wektory ataku. STRIDE (podszywanie się, manipulowanie, Odrzucenie, ujawnienie informacji, DoS, podniesienie uprawnień) i ramy proste i praktyczne w tym procesie.
Szybkie wygrane za rozpoczęcie pracy z DevSecOps już dziś
Jeśli zaczynasz od zera, nie próbuj wdrażać wszystkiego na raz. Tutaj trzy kroki, które pokrywają 80% ryzyka przy 20% wysiłku:
-
Dodaj Gitleaks do wstępnego zatwierdzenia: zainstaluj framework przed zatwierdzeniem,
dodaj konfigurację Gitleaks w
.pre-commit-config.yaml, uruchomićpre-commit install. Zapobiegaj wyciekaniu sekretów, zanim dotrą do celu zdalne repozytorium. Szacowany czas: 30 minut. -
Włącz kontrolę GitHub Zależność i npm w CI: Aktywuj zależnego robota w
ustawienia repozytorium i dodaj
npm audit --audit-level=high --omit=devdo istniejącego rurociągu CI. Otrzymuj automatyczne alerty dotyczące podatnych na ataki zależności. Szacowany czas: 1 godzina. - Włącz CodeQL w GitHub: Bezpłatnie dla repozytoriów publicznych, w zestawie w GitHub Advanced Security dla prywatnych repozytoriów przedsiębiorstw. Automatyczny SAST na każdym żądania push i pull bez konieczności dodatkowej konfiguracji. Szacowany czas: 15 minut.
Wnioski i dalsze kroki
DevSecOps nie jest produktem do kupienia ani narzędziem do zainstalowania: jest to proces ciągłe doskonalenie, które integruje bezpieczeństwo, rozwój i operacje w jednym cyklu cnotliwy. Rurociąg przedstawiony w tym artykule obejmuje wszystkie główne warstwy: skanowanie sekretów w celu zapobiegania wyciekom poświadczeń, SCA pod kątem zależności, SAST dla kodu źródłowego, DAST dla runtime, bezpieczeństwo IaC dla infrastruktury, oraz generowanie SBOM w celu zapewnienia identyfikowalności i zgodności.
Zasada przewodnia jest zawsze taka sama: znajdź problemy tak wcześnie, jak to możliwe i kiedy koszt korekty jest minimalny. Ponieważ 45% kodu wygenerowanego przez sztuczną inteligencję kończy się niepowodzeniem, tj Podstawowe testy bezpieczeństwa, automatyzacja DevSecOps stała się jeszcze bardziej krytyczna w tej epoce rozwoju wspomaganego sztuczną inteligencją. Nie możemy na tym polegać wyłącznie na podstawie ręcznego przeglądu w kontekście szybkiego rozwoju.
Artykuł ten kończy serię Bezpieczeństwo sieciowe dla programistów: przejrzeliśmy cały stos zabezpieczeń, począwszy od 10 najważniejszych luk w zabezpieczeniach OWASP do zabezpieczeń frontendowych, od zabezpieczeń backendowych po szyfrowanie i DevSecOps klej, który łączy w sobie wszystkie najlepsze praktyki w zautomatyzowanym i mierzalnym procesie. Bezpieczeństwo nie jest produktem końcowym, ale ciągłą podróżą: każde wydanie nim jest możliwość poprawy stanu zabezpieczeń oprogramowania.
Cała seria: Bezpieczeństwo sieciowe dla programistów
- 01 - 10 najlepszych OWASP 2025: Przewodnik dla programistów
- 02 - XSS, CSRF i CSP: Bezpieczeństwo frontonu
- 03 — Wstrzykiwanie SQL i sprawdzanie poprawności danych wejściowych: Bezpieczeństwo zaplecza
- 04 - Bezpieczne uwierzytelnianie: sesja i pliki cookie
- 05 - Bezpieczeństwo API: OAuth 2.1, JWT i ograniczanie szybkości
- 06 - Bezpieczeństwo łańcucha dostaw: audyt npm i SBOM
- 07 - Błędy kryptograficzne: haszowanie, szyfrowanie i token
- 08 - DevSecOps dla programisty: SAST, DAST w CI/CD (ten artykuł)
Dowiedz się także więcej o serialu Interfejs DevOps (identyfikatory 250-255) aby zintegrować bezpieczeństwo z przepływem pracy wdrożeniowym Angular i serią Kodowanie Vibe aby zrozumieć ryzyko problemy bezpieczeństwa specyficzne dla kodu generowanego przez sztuczną inteligencję i sposoby ich łagodzenia za pomocą DevSecOps.







