08 - DevSecOps pentru dezvoltatori: SAST, DAST și securitate în conducta CI/CD
În februarie 2024, un cercetător de securitate a demonstrat cum compromisul de tj-actions/fișiere-schimbate, o acțiune GitHub folosită de peste 23.000 de depozite, a permis exfiltrarea secretelor din conductele CI/CD a mii de organizații. Problema nu era în codul aplicației, nu era în dependențe, era în curs de dezvoltare în sine: instrumentul care trebuia să protejeze software-ul devenise vectorul de atac.
Acest scenariu reflectă un adevăr incomod: majoritatea echipelor investesc în securitate a codului aplicației, dar neglijează securitatea infrastructurii CI/CD care o construiește, testează și distribuie. DevSecOps nu integrează doar unele instrumente de scanare în conductă, ci o schimbare fundamentală de abordare: siguranța trebuie să fie o parte integrantă a fiecărei etape a ciclului de dezvoltare, nu o verificare finală înainte de lansare.
Conform raportului DORA 2025, echipele care adoptă practici cuprinzătoare DevSecOps raportează a Timpul mediu de remediere (MTTR) pentru vulnerabilități critice de 4 ori mai scurt comparativ cu echipele care efectuează doar teste de securitate în scenă sau producție. Costul de remedierea unui bug de securitate în producție și în medie de 100 de ori mai mare decât corectează-l în timpul dezvoltării: principiul „schift-left” are o justificare economică solid, cât și tehnic.
Ce vei învăța
- Securitate Shift-left: Integrați securitatea de la începutul ciclului de dezvoltare
- SAST cu Semgrep și CodeQL: analiza statică a codului sursă
- DAST cu OWASP ZAP: testare dinamică a aplicațiilor care rulează
- SCA cu Snyk și Trivy: Analiza compoziției software pentru dependențe
- Scanarea secretelor cu Gitleaks și TruffleHog: prevenirea scurgerilor de acreditări
- Securitate IaC cu Checkov: scanarea manifestelor Terraform și Kubernetes
- Completați pipeline GitHub Actions cu porți de securitate
- Metrici și KPI pentru a măsura maturitatea DevSecOps
Securitate Shift-Left: Principiul fundamental
Termenul „shift-left” provine de la reprezentarea vizuală a ciclului de dezvoltare ca o linie cronologie de la stânga (planificare, dezvoltare) la dreapta (testare, producție). Mutați securitatea din stânga înseamnă aducerea controalelor de securitate cât mai aproape de momentul în care este scris codul: în IDE-ul dezvoltatorului, în pre-commit hook, în solicitări de extragere, nu doar în mediul de pregătire.
Nivelurile de securitate pentru schimbarea la stânga, de la cea mai reactivă la cea mai proactivă, sunt:
- Nivelul 0 - Productie: scanarea vulnerabilităților numai în prod. Tarziu, scump.
- Nivelul 1 - Montare/Preproducție: DAST în mediul de testare. Mai bine, dar tot lent.
- Nivelul 2 - Conducta CI/CD: SAST, SCA, scanare secrete la fiecare apăsare. Standardele DevSecOps.
- Nivelul 3 - Solicitare de tragere: revizuire automată de securitate pentru fiecare PR. Rapid și contextual.
- Nivelul 4 - Precomitare: verificări locale înainte de comitere. Feedback imediat.
- Nivelul 5 - ISD: Plugin de securitate în editor (Snyk IDE, extensia CodeQL). În timp real.
Paradoxul 45%.
Cercetările de la Veracode și GitLab arată că 45% din codul este generat de instrumente AI (GitHub Copilot, Cursor, Claude Code) are vulnerabilități de securitate care ar eșua teste de securitate de bază. Nu pentru că AI este intrinsec periculoasă, ci pentru că se reproduce modele de cod nesigure prezente în seturile de date de antrenament. Acest lucru face controalele automatizat în CI/CD și mai critic în era codării vibrațiilor și asistate de AI dezvoltare. Vezi serialul Codare Vibe pentru a aprofunda acest subiect.
SAST: Testarea securității aplicațiilor statice
SAST analizează codul sursă, bytecode sau binar fără a rula aplicația, caută modele de cod vulnerabile, configurații greșite și anti-modele de securitate. Este cel mai rapid control (se poate face în secunde sau minute) și poate fi integrat direct în IDE, în pre-commit hook și în conducta CI/CD.
Principalele avantaje ale SAST față de alte abordări sunt: Rulează pe cod sursă (nu necesită o instanță de aplicație care rulează), identifică mai întâi vulnerabilitățile de implementare și poate analiza 100% din cod, inclusiv căile de cod executate rar. Principalul dezavantaj este rata fals pozitive, care necesită un proces de triaj și reglarea regulilor.
Semgrep: SAST Open Source și Fast
Semgrep este probabil cel mai folosit instrument SAST în ecosistemul open source în 2025.
Puterea sa constă în sintaxa simplă a regulilor (structură aproape identică cu codul
care analizează), în viteza de execuție și în suportul nativ pentru TypeScript, JavaScript,
Python, Go, Java și multe alte limbi. Menține mii de reguli de securitate în
registru oficial 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: Analiză semantică profundă
CodeQL, dezvoltat de GitHub, efectuează analize mai profunde decât Semgrep: construiește o bază de date de cod și vă permite să scrieți interogări în limbaj asemănător SQL pentru a le găsi vulnerabilitate și prin mai multe niveluri de apeluri de funcții (analiza taint). LinkedIn a anunțat în februarie 2026 că folosește atât CodeQL, cât și Semgrep într-un fel complementar pentru o acoperire optimă a bazei de cod. CodeQL este integrat nativ în GitHub Advanced Security și este disponibil gratuit pentru depozitele publice.
# .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: false pozitive și triaj
Principala problemă a SAST este numărul de fals pozitive: un set de reguli agresiv poate genera sute de rapoarte pentru fiecare comitere, făcând procesul nesustenabil. Strategia recomandată este să începeți cu un profil de severitate ridicat (doar CRITIC/RIGHT), ajustați regulile pentru baza de cod specifică și creșteți progresiv acoperire pe măsură ce echipa se familiarizează cu instrumentul. Nu blocați niciodată construcția pentru LOW/MEDIUM fără un proces de triaj stabilit.
DAST: Testare dinamică de securitate a aplicațiilor
În timp ce SAST analizează codul fără a-l executa, DAST testează aplicația în timp ce și în interior execuție, simulând atacuri reale din exterior, așa cum ar face un atacator. DAST găsește vulnerabilități pe care SAST nu le poate vedea: probleme de configurare a serverului, comportamente de rulare, vulnerabilități în API-urile REST și probleme de autentificare care ele apar doar cu cereri HTTP reale.
DAST este complementar SAST, nu un înlocuitor: SAST găsește 70-80% dintre vulnerabilități în codul sursă, DAST găsește restul de 20-30% care apare doar în timpul execuției. Pentru unul acoperire completă, ambele sunt necesare.
OWASP ZAP: Standard DAST în ecosistemul Open Source
OWASP ZAP (Zed Attack Proxy) este cel mai folosit instrument DAST din lumea open source, cu integrare nativă în GitHub Actions. Oferă trei moduri principale pentru CI/CD: scanarea liniei de bază (pasiv, non-invaziv, ideal pentru fiecare PR), scanare completă (activ, folosește încărcături utile de atac reale, numai în medii izolate) e Scanare API (specializat pentru OpenAPI/Swagger, ideal pentru microservicii).
# .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)
Pentru proiectele Angular cu SSR, DAST trebuie să ruleze pe o instanță accesibilă din conductă. O strategie eficientă și o implementare într-un mediu de punere în scenă efemer (de exemplu, pe canalul de previzualizare a găzduirii Firebase) ca parte a conductei, rulați DAST și continuați cu implementarea în producție numai dacă DAST trece.
# 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 compoziției software
SCA (Software Composition Analysis) analizează dependențele open source ale aplicației pentru a identifica vulnerabilități cunoscute (CVE), probleme de licențiere și pachete învechite. Articolul anterior din serie ( Securitatea lanțului de aprovizionare: audit npm și SBOM) acoperă în detaliu auditul npm, Snyk, Dependabot și generarea SBOM. In aceasta context ne concentrăm pe Trivy, care oferă atât scanarea SCA, cât și IaC într-unul instrument, ideal pentru conductele DevSecOps unificate.
# 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'
Scanarea secretelor: prevenirea scurgerilor de acreditări
Mii de secrete sunt expuse accidental pe GitHub public în fiecare săptămână: Chei API, jetoane OAuth, parole baze de date, certificate private. GitGuardian, care monitorizează depozitele publice, raportează că peste 12 milioane au fost detectate în 2024 a secretelor expuse pe depozitele publice, cu o creștere de 28% față de anul anterior. Odată ce un secret este într-un depozit public (chiar și pentru câteva minute înainte de îndepărtare), ar trebui să fie considerat compromis și rotit imediat.
Gitleaks și TruffleHog sunt cele două instrumente cele mai utilizate pentru detectarea secretelor, cu abordări complementar: Gitleaks este rapid și excelent pentru CI/CD, TruffleHog verifică în mod activ dacă secretele găsite sunt încă valabile (reduce în mod semnificativ falsele pozitive).
Gitleaks: configurare și integrare
# 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: Verificare secretă activă
# 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)
Secretele nu sunt eliminate cu git rm
Dacă un secret este comis din greșeală, eliminați fișierul cu git rm sau
adăugați fișierul la .gitignore nu este suficient: secretul este încă
vizibil în istoria git. Pentru a-l elimina cu adevărat folosiți git filter-repo
(instrument recomandat oficial de GitHub), apoi apăsați forțat pe toate ramurile,
și considerați secretul compromis și rotiți-l imediat. GitHub oferă și
instrumentul nativ „Scanare secretă” în setările depozitului pe care le monitorizează
Istoricul de comitere continuă pentru peste 200 de tipuri de token cunoscute.
Securitate IaC: Checkov pentru Terraform și Kubernetes
Infrastructura ca cod (IaC) a democratizat managementul infrastructurii, dar a făcut-o a introdus și un nou vector de risc: configurări greșite în fișierele Terraform, Kubernetes manifests, Docker Compose și AWS CloudFormation, care vă pot expune întreaga infrastructură. Checkov (Bridgecrew/Palo Alto Networks) scanează static aceste fișiere cu peste 1000 Politici de securitate integrate, mapate la benchmark-uri CIS, NIST și alte standarde.
Notă: tfsec, instrumentul original de scanare IaC al Aqua Security, a fost integrat în Trivy. Pentru proiecte noi, se recomandă Trivy pentru IaC sau Checkov pentru o acoperire mai largă.
# 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"
GitHub Actions Pipeline Complete: The Ultimate Security Gate
Integrarea tuturor acestor instrumente într-un canal coerent necesită planificare fiți atenți: nu toate lucrările trebuie să blocheze construcția, unele scanări sunt mai potrivite pentru PR în timp ce alții pentru push on main, iar paralelizarea este fundamentală pentru non încetini excesiv fluxul de dezvoltare. Următorul conduct ilustrează unul configurație completă cu 6 joburi paralele și secvențiale.
# .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
Porți de securitate: ce blocuri se construiesc și ce nu
O poartă de securitate eficientă nu blochează fiecare avertisment, ci face distincția între probleme care necesită atenție imediată și probleme care pot fi gestionate în timp. Regula de bază este: blochează doar ceea ce este clar periculos și posibil. Blocarea build-ului pentru prea multe false pozitive sau vulnerabilități SCI determină echipa să dezactiveze controalele complet, distrugând întreaga investiție.
Matricea porților de securitate recomandată
- Întotdeauna BLOCAȚI: Secrete în cod, vulnerabilități CRITICE cu remediere disponibile, constatări injecție SAST/RCE, configurații greșite IaC CRITICE (bucket public S3, grup de securitate 0.0.0.0/0 în SSH de intrare)
- BLOCARE pe principal (nu pe PR): Vulnerabilitate ridicată cu remediere disponibilă, Constatările DAST setate la FAIL, dependențe cu licențe incompatibile (GPL în produs comercial)
- AVERTISMENT (anunțează, dar nu blochează): Vulnerabilitate ridicată fără remediere disponibil, MEDIU în SAST, IaC HIGH cu soluție documentată în excepții, constatările DAST setate la WARN
- IGNORE (cu documentație): Vulnerabilitate LOW/INFO, fals pozitive documentat în fișierul de excepții (.trivyignore, .gitleaks.toml allowlist), CVE fără impact real asupra contextului specific al aplicației
# 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 de verificare unghiulară: DevSecOps Pipeline
Proiectele unghiulare au anumite considerații legate de DevSecOps lanț de instrumente (Angular CLI, esbuild, ng-packagr), la utilizarea șabloanelor HTML cu legături dinamic și la SSR cu serverul 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
Metrici și KPI pentru maturitatea DevSecOps
Măsurarea este esențială pentru îmbunătățire. Valorile DevSecOps trebuie să fie echilibrate viteza de dezvoltare cu eficacitatea siguranței. Ținta nu este niciodată zero vulnerabilitate (de neatins), dar reduce riscul la niveluri acceptabile în cel mai scurt timp posibil.
KPI-uri esențiale pentru DevSecOps
- MTTD (Timp mediu de detectare): timpul mediu dintre introducerea unuia vulnerabilitatea și detectarea acesteia. Țintă cu CI/CD: sub 24 de ore. Cu shift complet la stânga (pre-comitare): detectarea în secunde.
- MTTR (Timp mediu pentru remediere): de la detectare la corectare in productie. Ținta OWASP: mai puțin de 7 zile pentru CRITIC, mai puțin de 30 pentru HIGH. Cu procese DevSecOps mature: MTTR de 4 ori mai mic decât echipele tradiționale.
- Raport de detectare Shift-Left (SLDR): procentul de vulnerabilitate detectat în dezvoltare vs producție. Țintă: peste 80% au fost detectate înainte de implementare.
- Datorii de garanție: numărul total de vulnerabilități deschise în funcție de gravitate. Monitorizați tendința în timp: trebuie să scadă sau să rămână stabilă.
- Rata fals pozitive: procentul de alerte SAST/DAST fals pozitive. Țintă: sub 20% pentru a evita oboseala echipei și pentru a menține credibilitatea procesului.
- Durata conductei: timpul total al conductei DevSecOps. Țintă: SAST + SCA + secrete sub 10 minute pentru a evita afectarea productivității.
- Acoperire de securitate: procent din baza de cod acoperită de SAST, Procentul API acoperit de DAST. Țintă: peste 90% pentru 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
# 
Cultura DevSecOps: factorul uman
Tehnologia singură nu este suficientă: DevSecOps necesită o schimbare culturală care transformă securitatea din responsabilitatea unei echipe specializate într-o responsabilitate partajată de toți dezvoltatorii. Acest lucru necesită pregătire, procese clare și, mai presus de toate, eliminarea frecării care fac din siguranță un obstacol perceput mai degrabă decât unul instrument de calitate.
Principiile fundamentale ale unei culturi mature DevSecOps sunt:
- „Securitatea ca cod”: Politicile de securitate sunt cod, versiuni în git, revizuit ca orice altă modificare a bazei de cod. Excepții de la politici sunt documentate în codul propriu-zis, cu justificarea și data revizuirii.
- Feedback imediat și contextual: dezvoltatorul primește feedback de la securitate în IDE sau PR, nu săptămâni mai târziu într-un raport PDF de neînțeles. Contextul este crucial: „această funcție are o problemă de injectare SQL pe linia 42” și mult mai util decât „vulnerabilitatea tip A07 detectată în modulul backend”.
- Fără vină, da învățare: Vulnerabilitățile găsite în CI/CD sunt oportunități de învățare, nu pedepse. Dezvoltatorul care le-a prezentat trebuie să înțeleagă de ce și cum să le prevină în viitor.
- Program campion al securității: fiecare echipă are un campion de securitate care acționează ca o punte între echipa de dezvoltare și securitate, face triajul inițial al alertelor și promovează cele mai bune practici într-un mod contextual.
- Modelarea preventivă a amenințărilor: înainte de a implementa o caracteristică, echipa discută despre potențialii vectori de atac. STRIDE (falsificare, falsificare, Repudierea, divulgarea informațiilor, DoS, ridicarea privilegiilor) și un cadru simplu și practic pentru acest proces.
Câștiguri rapide pentru începerea utilizării DevSecOps astăzi
Dacă porniți de la zero, nu încercați să implementați totul deodată. Aici cei trei pași care acoperă 80% din risc cu 20% din efort:
-
Adăugați Gitleaks la precomitare: instalați cadrul de pre-comitare,
adăugați configurația Gitleaks în
.pre-commit-config.yaml, fugipre-commit install. Preveniți scurgerea secretelor înainte ca acestea să ajungă depozit la distanță. Timp estimat: 30 minute. -
Activați GitHub Dependabot și auditul npm în CI: Activați Dependabot în
setările depozitului și adăugați
npm audit --audit-level=high --omit=devla conducta dvs. CI existentă. Primiți alerte automate pentru dependențe vulnerabile. Timp estimat: 1 oră. - Activați CodeQL pe GitHub: gratuit pentru depozitele publice, inclus în GitHub Advanced Security pentru depozitele private de întreprindere. SAST automat pe fiecare solicitări push și pull, fără a fi necesară o configurație suplimentară. Timp estimat: 15 minute.
Concluzii și pașii următori
DevSecOps nu este un produs de cumpărat sau un instrument de instalat: este un proces îmbunătățire continuă care integrează securitatea, dezvoltarea și operațiunile într-un singur ciclu virtuos. Conducta prezentată în acest articol acoperă toate straturile principale: scanarea secretelor pentru a preveni scurgerile de acreditări, SCA pentru dependențe, SAST pentru codul sursă, DAST pentru runtime, securitate IaC pentru infrastructură, și generarea de SBOM pentru trasabilitate și conformitate.
Principiul călăuzitor este întotdeauna același: găsiți problemele cât mai curând posibil, când costul corectării este minim. Cu 45% din codul generat de AI eșuând i Testare de bază de securitate, automatizarea DevSecOps a devenit și mai critică în epocă de dezvoltare asistată de inteligența artificială. Nu ne putem baza pe ea numai pe revizuirea manuală într-un context de dezvoltare de mare viteză.
Acest articol încheie seria Securitate web pentru dezvoltatori: am trecut prin întreaga stivă de securitate, din Top 10 vulnerabilități OWASP la apărarea front-end, de la securitatea backend la criptare, la DevSecOps adeziv care reunește toate cele mai bune practici într-un proces automatizat și măsurabil. Securitatea nu este un produs final, ci o călătorie continuă: fiecare lansare este o oportunitate de a îmbunătăți poziția de securitate a software-ului dvs.
Întreaga serie: Securitate web pentru dezvoltatori
- 01 - OWASP Top 10 2025: Ghid pentru dezvoltatori
- 02 - XSS, CSRF și CSP: Securitate Frontend
- 03 - Injecție SQL și validare a intrărilor: Securitate backend
- 04 - Autentificare sigură: sesiune și cookie-uri
- 05 - Securitate API: OAuth 2.1, JWT și Rate Limiting
- 06 - Securitatea lanțului de aprovizionare: audit npm și SBOM
- 07 - Erori criptografice: hashing, criptare și token
- 08 - DevSecOps pentru dezvoltatori: SAST, DAST în CI/CD (acest articol)
Aflați și mai multe despre serie Frontend DevOps (ID-uri 250-255) pentru a integra securitatea cu fluxul de lucru de implementare Angular și cu seria Codare Vibe pentru a înțelege riscurile problemele de securitate specifice codului generat de AI și cum să le atenuați cu DevSecOps.







