Waarom je AI-codehulp een beveiligingslek is (en hoe je het fixt)
Waarom je AI-code-assistent een beveiligingslek is (en hoe je dat fixt)
Vorige week drong het tot me door: maandenlang gaf ik een AI-assistent vrije toegang tot mijn machine. Hij kon rommelen met AWS-credentials, SSH-keys, privé GitHub-repos en alles in mijn home-map. Eng? Ik had het niet eens door, want het ding werkte gewoon goed en er was niks misgegaan.
Precies dat soort gemakzucht wist production-databases uit.
Gemak is een valkuil voor beveiliging
De bittere waarheid: veel AI-code-tools krijgen dezelfde rechten als een top DevOps'er op dag één. Aan een nieuwe freelancer geef je geen onbeperkte SSH-toegang tot alle servers. Maar een LLM? Die mag alles, zonder nadenken.
Het zit niet in kwaadwilligheid. Het is luiheid. Deze tools zijn zó handig dat je vergeet wat ze kunnen aanrichten. Eén prompt-injectie via een gekloond repo, een verkeerd doel, of een onschuldig commando – en je credentials zijn weg naar een hacker-server. Je merkt er niks van.
Goed nieuws: tools als Claude Code hebben sterke beveiligingsopties. De meeste gebruikers zetten ze gewoon niet aan.
De risico's van de standaardinstellingen
Standaard draaien veel AI-assistenten in 'auto'-modus. Ze voeren commando's uit zonder te vragen, tenzij iets expliciet geblokkeerd is. Klinkt handig? In de praktijk betekent het dit:
Met een lege blokkeerlijst en auto als default, mag je AI los:
curlnaar willekeurige serverswgetvoor downloadssshnaar externe machinesncvoor netwerkverbindingen- Elke
.env-file lezen - Toegang tot
~/.aws/credentials,~/.ssh,~/.gnupg - Code pushen naar repos
Alles stilzwijgend. Geen melding. Weg.
Een drielaags beveiligingsmodel opzetten
Je hebt fijne controle nodig. Niet alles moet goedgekeurd worden, maar riskante acties wel. Zo pak je het aan:
Laag 1: Strakke blokkade
Begin met een deny-list voor credential-stuff:
{
"deny": [
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.gnupg/**)",
"Read(~/.azure/**)",
"Read(~/.kube/**)",
"Read(~/.npmrc)",
"Read(~/.git-credentials)",
"Read(*.env)",
"Read(.env.*)",
"Bash(curl *)",
"Bash(wget *)",
"Bash(nc *)",
"Bash(ssh *)"
]
}
Dit is je firewall. Niets hier komt erdoor, punt uit. Zelfs als de AI probeert credentials te stelen, blokkeert het systeem het.
Laag 2: Controlepunt voor review
Een 'ask'-list voor omkeerbare maar gevaarlijke acties:
{
"ask": [
"Bash(git push *)",
"Bash(git commit *)",
"Bash(git merge *)",
"Bash(git reset *)",
"Bash(npm publish *)",
"Bash(docker push *)"
]
}
De AI kan dit nodig hebben – code pushen, packages publiceren, containers deployen – maar jij keurt het goed. Een popup voor uitvoering. Productief, zonder rampen.
Laag 3: Vrije baan voor veilig spul
Sta expliciet veilige commando's toe:
{
"allow": [
"Bash(npm run *)",
"Bash(git status *)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(ls *)",
"Read(src/**)",
"Read(tests/**)"
]
}
Geen gedoe hier. De AI vliegt ermee, want het wijzigt niks gevaarlijks.
Kies je default-modus slim
Na je lijsten moet je een default kiezen voor de rest. Drie keuzes:
auto- Alles wat niet geblokkeerd is, runt stil. Snelst, maar je deny-list moet waterdicht zijn.acceptEdits- Vrije leesrechten en edit-suggesties, maar bash-commando's buiten allow? Vragen eerst. Goede balans.ask- Vragen bij elk risico. Traagst, maar super veilig voor voorzichtige setups.
Voor teams werkt acceptEdits vaak het best. Productiviteit blijft, met bewuste keuzes voor changes.
Voorbeeldconfig voor de praktijk
Zo ziet een battle-tested config eruit:
{
"permissions": {
"deny": [
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Read(~/.gnupg/**)",
"Read(~/.azure/**)",
"Read(~/.kube/**)",
"Read(~/.npmrc)",
"Read(~/.git-credentials)",
"Read(~/.config/gh/**)",
"Read(*.env)",
"Read(.env.*)",
"Bash(curl *)",
"Bash(wget *)",
"Bash(nc *)",
"Bash(ssh *)"
],
"ask": [
"Bash(git push *)",
"Bash(git commit *)",
"Bash(npm publish *)",
"Bash(docker push *)"
],
"allow": [
"Bash(npm run *)",
"Bash(npm install *)",
"Bash(npm test *)",
"Bash(git status *)",
"Bash(git diff *)",
"Bash(git log *)"
],
"defaultMode": "acceptEdits"
}
}
Hiermee helpt je AI bij tests, linting en code-begrip. Maar stelen, pushen zonder oké of rare connecties? No way.
Twee modi voor verschillende klussen
Ik gebruik shell-aliases:
# Standaard: veilig en snel
alias cc="claude --permission-mode auto"
# Debug: volle trust (spaarsamig!)
alias ccd="claude --permission-mode dangerously-skip-permissions"
cc voor dagelijks werk. ccd alleen bij noodgevallen, met volle bewustzijn van het risico.
Branch-wide issue
Dit geldt niet alleen voor Claude Code. Elke AI-tool met shell-toegang heeft dit probleem: GitHub Copilot-extensies, Devin, Cursor, ChatGPT met code-uitvoering. Allemaal die keuze: gemak of veiligheid.
Claude Code blinkt uit met echte controls. Anderen dwingen all-in of niks.
Impact op je infra
In teams wordt dit cruciaal. Je kunt niet afwachten tot een dev het verkloot.
Denk aan:
- Verplichte deny-lists in team-configs
- Credential-files blokkeren op filesystem-niveau
- Tijdelijke tokens i.p.v. vaste keys
- Netwerkregels tegen data-lekken
- Training over productiviteit vs. risico
Kernboodschap
AI-code-assistenten zijn topgereedschap. Maar gratis is het niet. De controls zijn er – gebruik ze.
Nu doen: 15 minuten voor je deny-list op credentials. Ask-list voor deploys. Slimme default. Dan werk je relaxed, met AI die helpt maar niet sloopt.
'Er is nog niks gebeurd' is geen strategie.