IaC-scans
IaC-scans zijn een eigen controle, fremforge/iac-scan, met eigen instellingen en een eigen tabblad met bevindingen. Bij elke pull request, en bij elke push naar de standaardbranch of een beschermde releasebranch, draait fremforge trivy config over de repository met alle ingebouwde misconfiguratiecontroles van Trivy:
- Dockerfiles en Containerfiles
- Docker Compose-bestanden
- Kubernetes-manifesten
- Helm-charts
- Terraform en OpenTofu, zowel
.tf- als.tofu-bestanden, waarbij ook hun externe modules worden gecontroleerd: modules van je organisatie op frem.sh en van de mirrors van fremforge, en registermodules en bronnen op github.com of gitlab.com bij een tag of commit via de modulecache. Elke andere externe bron wordt niet opgehaald en als zodanig vermeld - AWS CloudFormation-templates, YAML en JSON
- Azure Resource Manager-templates (ARM), JSON
- Bicep-bestanden, eerst gecompileerd naar ARM; zie Bicep
- Ansible-playbooks en -taken, voor de cloudresources die hun modules aanmaken (bijvoorbeeld
amazon.aws.s3_bucket); niet elke module wordt gedekt
Elk van deze is op 19 oktober 2026 bewezen met een pull request die een bekende misconfiguratie toevoegt (die zakte voor de controle) en een met de veilige versie (die slaagde).
Tot 17 oktober 2026 draaiden deze controles binnen de image-scan en waren hun bevindingen image-bevindingen. De imagecontrole, fremforge/image-scan, bevat ze niet meer.
De pull-requestcontrole
fremforge/iac-scan faalt wanneer de pull request een misconfiguratie op of boven je drempel toevoegt. Een misconfiguratie die de branch waarin hij wordt samengevoegd al heeft, blokkeert hem niet: de controle vergelijkt met de laatste scan van die branch, de standaardbranch of een beschermde releasebranch. Een bevinding is dezelfde bevinding als het dezelfde controle in hetzelfde bestand is; een tweede geval van een controle in een bestand is nieuw.
Is er nog geen scan van die branch, dan blokkeert elke bevinding op of boven de drempel, en wordt een scan van de branch aangevraagd, zodat de volgende run van de controle wel vergelijkt.
De status zegt wat er is gevonden, bijvoorbeeld 1 new high/critical misconfiguration(s); merge blocked; 2 already on main, en linkt naar Beveiliging › Bevindingen › IaC.
Wanneer het een vereiste controle is
fremforge/iac-scan meldt zich bij elke pull request. Of een fout het samenvoegen blokkeert, hangt ervan af of het in je organisatie een vereiste controle van de branchbescherming is:
- Organisaties die op of na 19 oktober 2026 zijn aangemaakt, hebben het vanaf hun eerste repository als vereiste controle.
- Oudere organisaties krijgen het organisatie voor organisatie, zodat geen pull request die werd geopend voordat de controle bestond, erop wacht. Tot dan toont de controle het resultaat zonder het samenvoegen op zichzelf te blokkeren.
- Modus Uit haalt hem uit de vereiste controles; Audit houdt hem vereist, maar laat hem nooit falen.
Beveiliging › Beleid › Scanners › IaC zegt wat voor je organisatie geldt: Een vereiste controle in deze organisatie of Nog geen vereiste controle in deze organisatie. Je kunt hem op elk moment zelf aan je vereiste controles toevoegen; zie Branchbescherming.
Instellingen
Onder Beveiliging › Beleid › Scanners › IaC:
| Instelling | Waarden | Standaard |
|---|---|---|
| Modus | Afdwingen (merge blokkeren), Audit (melden, nooit blokkeren), Uit (niet scannen) | Afdwingen |
| Controle faalt bij | elke ernst, gemiddeld of hoger, hoog of kritiek, alleen kritiek | hoog of kritiek |
Dezelfde instellingen vormen het onderdeel iac_scan van het scanbeleid van de organisatie, zodat je ze ook via de API en per repository kunt instellen:
PUT /_app/api/v1/orgs/{org}/policy
{ "scan_policy": { "iac_scan": { "mode": "enforce", "block_severity": "critical" } } }Een waarde per repository gaat voor die van de organisatie:
PUT /_app/api/v1/orgs/{org}/repos/{repo}/policy
{ "scan_policy": { "iac_scan": { "mode": "audit" } } }Met Terraform of OpenTofu gebruik je fremforge_scan_policy met scanner = "iac_scan" (provider 0.4.0 en later):
resource "fremforge_scan_policy" "iac" {
org = "acme"
scanner = "iac_scan"
mode = "enforce"
block_severity = "high"
}Externe Terraform-modules
De controle leest de modules die je configuratie aanroept, zodat ook een misconfiguratie binnen een module wordt gevonden:
Via de modulecache. Een registermodule (
terraform-aws-modules/vpc/aws, met of zonderversion) en een bron op github.com of gitlab.com bij een tag of commit worden gelezen via de modulecache van de dependency proxy: de nieuwste versie die past bij jeversion-voorwaarde, vastgezet bij de eerste keer ophalen. Alleen de.tf- en.tf.json-bestanden van de module, en de lokale modules die ze aanroepen, worden gecontroleerd; de voorbeelden en tests ervan niet. Je repository wordt nooit gewijzigd: de scanner werkt op een privékopie.Van frem.sh. Modules in je eigen organisatie, en in de mirrors van publieke repository’s die fremforge bijhoudt, worden van frem.sh gelezen.
Van je eigen Git-host, met je eigen inloggegevens. Een module op een andere Git-host via https (
git::https://git.example.com/infra/modules.git?ref=v1.2.0, ofhttps://git.example.com/infra/modules.git) wordt gelezen wanneer je organisatie een alleen-lezen inloggegeven van het typekind: gitvoor precies die host heeft. Een eigenaar slaat dat op onder Beveiliging › Toegang › Registerinloggegevens, met de keuze Git-modulehost, of via de API voor registerinloggegevens; de functie staat uit totdat een eigenaar haar inschakelt. De scan haalt de module op via de dependency proxy, die je inloggegeven toevoegt:- alleen lezen: een git fetch, nooit een push;
- je inloggegeven gaat naar die host en nergens anders heen, en een redirect wordt geweigerd;
- er wordt niets gecachet, dus als je het inloggegeven verwijdert, blijft er geen kopie achter.
Een host waarvoor je geen inloggegeven hebt, wordt net als voorheen niet opgehaald.
Al het andere wordt niet opgehaald. Een andere host zonder inloggegeven, een bron op github.com of gitlab.com zonder tag (een branch), een archief-URL of een SSH-bron wordt nooit door de scanner opgehaald. Zo’n module staat met haar bron vermeld onder Niet gecontroleerd op Beveiliging › Bevindingen › IaC, en de status van de controle zegt hoeveel modules niet zijn opgehaald; de resources die ze definieert, worden niet gecontroleerd.
Bevindingen binnen een module staan apart vermeld, onder In modules, gegroepeerd per module met de versie die de scan heeft gelezen en de plek van waaruit ze wordt aangeroepen. Ze blokkeren nooit een pull request, hebben geen hersteltermijn en sturen geen melding, omdat de oplossing in je aanroep zit (een input, of een moduleversie die het oplost), niet in je bestanden. Een negering blijft behouden over moduleversies heen: ze is gekoppeld aan de module, het bestand daarin en de controle, niet aan de versie.
Bicep
Trivy heeft geen controles voor Bicep, maar controleert wel ARM. Daarom compileert fremforge elk .bicep-bestand in de repository met de Bicep CLI naar ARM en controleert het resultaat met dezelfde controles, drempel en negeringen als de rest van de repository. Een bevinding wordt getoond op het .bicep-bestand, op de regel van de gemarkeerde eigenschap als die te vinden is, anders op de resourcedeclaratie, en vermeldt dat de regel is afgeleid uit de gecompileerde ARM.
- Offline. Bicep draait zonder netwerktoegang en zonder modules te herstellen. Een module uit een register (
br:) of een template spec (ts:) kan niet worden opgehaald, dus een bestand dat er een gebruikt, wordt niet gecompileerd en als zodanig vermeld. Lokale modules (module x './y.bicep') werken wel. - Elk bestand afzonderlijk. Elk
.bicep-bestand, modules inbegrepen, wordt op zichzelf gecompileerd en gecontroleerd, dus een resource in een module wordt gecontroleerd in het bestand van de module. - Je
bicepconfig.jsonwordt niet gelezen. Module-aliassen, extensies, experimentele functies en analyzerinstellingen daarin hebben geen effect op de scan. Een bestand dat een experimentele functie nodig heeft om te compileren, wordt vermeld als niet gecompileerd. - Nooit stilletjes geslaagd. Een bestand dat niet kon worden gecompileerd (een fout, een registermodule, meer dan 60 seconden, of voorbij de limiet van 200 bestanden of 2 MiB per repository), blokkeert het samenvoegen niet, omdat het geen misconfiguratie is. Maar de status van de controle zegt hoeveel bestanden niet zijn gecontroleerd, en Beveiliging › Bevindingen › IaC vermeldt ze onder Niet gecontroleerd, met de reden.
Je eigen controles
Een organisatie kan eigen controles toevoegen, geschreven in Rego als aangepaste Trivy-controles. fremforge/iac-scan draait ze samen met de ingebouwde controles op elke repository van de organisatie, met dezelfde modus en drempel, en alleen wat een pull request toevoegt, blokkeert hem.
Voeg ze toe onder Beveiliging › Beleid › IaC-controles, of via de API (hieronder). Een controle moet:
- in een package onder
custom.staan, bijvoorbeeldpackage custom.acme.no_root; - een
# METADATA-blok hebben met eentitle, eencustom.id(de bevindingen ervan worden getoond alscustom/<id>) en eencustom.severity(LOW,MEDIUM,HIGHofCRITICAL);custom.input.selectornoemt de bestandstypen die ze leest, zoals in Trivy; - alleen het gescande bestand (
input) lezen: geenimport dataen geen verwijzing naardata; - geen netwerk- of runtime-built-ins gebruiken:
http.send,net.lookup_ip_addr,opa.runtime,rego.parse_module,trace,numbers.rangeennumbers.range_stepworden geweigerd.
Maximaal 25 controles per organisatie, elk 32 KiB. De console biedt een uitgewerkt voorbeeld om mee te beginnen.
Een opgeslagen controle staat op Wordt gecontroleerd totdat de scanner haar met OPA heeft geverifieerd, in dezelfde afgeschermde omgeving waarin je pull-requestscans draaien, en daarna op Actief of Afgewezen, met de reden. Alleen een actieve controle die niet is uitgeschakeld, draait. Als je de broncode van een controle bewerkt, wordt ze opnieuw geverifieerd; tot dan geldt het vorige oordeel niet meer en draait ze niet. Je kunt een controle uitschakelen zonder haar te verwijderen.
Bevindingen van je controles verschijnen samen met de ingebouwde, in de pull-requestcontrole en onder Beveiliging › Bevindingen › IaC, gemarkeerd als Aangepast met de naam van de controle.
API
GET /_app/api/v1/orgs/{org}/code-security/iac/policies
POST /_app/api/v1/orgs/{org}/code-security/iac/policies { "name": "No root", "source": "<rego>", "enabled": true }
PUT /_app/api/v1/orgs/{org}/code-security/iac/policies/{id}
DELETE /_app/api/v1/orgs/{org}/code-security/iac/policies/{id}Met Terraform of OpenTofu is elke controle een fremforge_iac_custom_check (provider 0.4.0 en later): name, source en enabled, waarbij status, status_reason, check_id, title en severity worden teruggelezen uit het oordeel van de scanner.
resource "fremforge_iac_custom_check" "no_root" {
org = "acme"
name = "No root"
source = file("checks/no_root.rego")
}Voor het opvragen van de lijst is findings:read of policy:read nodig; voor wijzigingen policy:write. Een nieuwe of gewijzigde controle komt terug met status pending; het oordeel van de scanner zet die op valid of invalid, met status_reason. Een controle die de API al kan weigeren voordat de scanner haar ziet (te groot, geen custom.-package, geen METADATA), krijgt 400 met de reden; de 26e controle krijgt 409. Elke wijziging staat in de auditlog.
Bevindingen
Beveiliging › Bevindingen › IaC toont de openstaande misconfiguraties: de controle (bijvoorbeeld KSV-0014), de titel ervan, de repository en het bestand, met ernst en hersteltermijn. Filter op ernst, open het bestand bij de gescande commit, en negeer er een of meer met een reden, net als op de andere tabbladen met bevindingen. Een negering blijft voor dezelfde controle in hetzelfde bestand over scans heen behouden.
Voor een paar controles waarbij één eigenschap één veilige waarde heeft, zoals het S3-blok voor publieke toegang en de instellingen voor alleen HTTPS en de minimale TLS-versie van Azure-opslag, opent Fix-PR openen in de kolom Fix een pull request die de waarde instelt, zonder AI. Zie Regelgebaseerde fixes.
Ze verschijnen ook op Beveiliging › Bevindingen › Alle als het type IaC, als eigen rij op het beveiligingsoverzicht, in het compliancerapport en via de findings-API (type=iac).
Benchmarks en NIS2
Het compliancerapport groepeert de openstaande IaC-bevindingen naar de benchmarkmaatregelen die hun controles testen (CIS Docker, CIS Kubernetes, RKE2 en EKS, de NSA-handleiding voor het harden van Kubernetes, Pod Security Standards, CIS AWS), op basis van de compliancekoppelingen die Trivy publiceert, en naar onderdeel van artikel 21, lid 2, van NIS2. De NIS2-indeling is van fremforge zelf; het is geen officiële koppeling en zegt niets over naleving van welke maatregel dan ook.
Wil je een controle in een repository negeren, gebruik dan een Trivy-ignore-bestand; zie Trivy-ignore-bestanden.
Niet gedekt
Deze controles vinden misconfiguraties. Ze vergelijken geen versies met kwetsbaarheidsadviezen:
- Terraform-modules worden niet gecontroleerd op kwetsbare versies. Terraform- en OpenTofu-providers wel, door de afhankelijkheidsscan; zie Terraform- en OpenTofu-providers.
- Helm-charts worden niet gecontroleerd op kwetsbare chartversies. De containerimages die een chart uitrolt wel, door de image-scan; zie Images die je Helm-charts uitrollen.
- Pulumi en de AWS CDK worden niet gescand: hun resources bestaan pas wanneer je programma draait, en fremforge voert je code niet uit.
- De dekking binnen een formaat is die van Trivy. Zo worden regels van netwerkbeveiligingsgroepen in ARM-templates (en dus in Bicep) niet beoordeeld, en wordt een Ansible-taak alleen gecontroleerd als Trivy de module ervan kent: in onze test werd een taak met
amazon.aws.s3_bucketgecontroleerd en een taak metamazon.aws.ec2_security_groupniet. - Versies van CI-actions worden wel gecontroleerd, maar door de afhankelijkheidsscan en niet door deze controle: een action met een bekende kwetsbaarheid is een afhankelijkheidsbevinding; zie Versies van CI-actions. Of ze aan een commit zijn vastgepind, wordt apart gecontroleerd; zie Workflow-pinning.