JOURNAL

Claude Code mods: et CPR-filter, der snublede over et ø

Claude Code har fået mods. Et filter på 37 linjer kode skifter CPR-numre, mails og telefonnumre ud, før Claude læser dem. Første version lod en mail med ø slippe igennem og fik Claude til at tro, at filen var maskeret. Den rettede lod 0 af 26 slippe igennem på en opdigtet kundeeksport. Filteret er gratis.

2. oktober 2026·10 min læsning·Claude · Claude Code · GDPR · CPR-numre · claude-nyheder

Kort fortalt: Claude Code har fået mods, små stykker kode, der kan ændre, hvad Claude Code gør. Jeg fik Claude Code til at bygge et filter, der skifter CPR-numre, mails og telefonnumre ud med pladsholdere, før Claude læser dem, og til at teste det på en opdigtet kundeeksport med 26 af den slags oplysninger. Første version lod en mail med ø slippe igennem og fik Claude til at tro, at filen var maskeret. Den rettede version lod 0 slippe igennem. Navne og adresser læste Claude hver gang. Filteret er gratis: hent zip-filen.

Testen på 37 sekunder: samme fil og samme forespørgsel uden filter, med første version og med den rettede version. Genskabt fra de optagne kørsler, og hver linje fra Claude er Claudes eget svar.Film: Brinvik
Skift mellem de tre tilstande, eller indsæt din egen linje. Intet forlader siden, og alle kunder er opdigtede.

Det kan være en udvikler eller en driftsansvarlig, der sætter Claude Code til at rydde op i en eksport fra CRM'et. Og i Danmark kan den eksport have CPR-numre i.

Claude Code mods kom den 1. oktober. En mod er en lille funktion, som Claude Code kalder, hver gang der sker noget bestemt, for eksempel når Claude læser en fil. Funktionen kan køre før, efter eller i stedet for det, Claude Code ellers ville gøre. Anthropic nævner det selv som et af eksemplerne i lanceringen: „Redact secrets from tool output before Claude reads it.“ Anthropic beskriver mods i Claude Code: i terminalen, i desktop-appen og i VS Code. Den almindelige Claude-chat og Cowork nævnes ikke.

Et tavst filter fik Claude til at tage fejl

Filteret er en mod på 37 linjer kode. Hver gang et værktøj har kørt, for eksempel når Claude har læst en fil, går resultatet gennem filteret, før Claude får det. Det skifter CPR-numre ud med [CPR], mails med [EMAIL] og danske telefonnumre med [TELEFON]. Filen på disken rører det ikke.

En tegning af vejen for ét værktøjsresultat i fire trin fra venstre mod højre. Først kunder.csv på disken, markeret „urørt“. Så værktøjet Read, der læser filen. Så cpr-filter, der skifter CPR-numre, mails og telefonnumre ud med [CPR], [EMAIL] og [TELEFON] og lægger én linje med besked til. Til sidst Claude, der får pladsholderne og beskeden. Under dem står filterets linje på engelsk med tallene 10 CPR-numre, 8 mails og 9 telefonnumre. De 10 er de 9 plantede plus ordrenummeret.
Vejen fra filen til Claude. Filteret sidder i midten, og filen på disken bliver ikke ændret.

Testfilen ligner en eksport fra et CRM: otte opdigtede kunder med navn, CPR-nummer, mail, telefon, adresse, by, omsætning og en note i fritekst. 26 af de oplysninger, filteret skal fange, er plantet i filen. To af dem står inde i noterne: CPR-nummeret på en ny ejer og telefonnummeret på en kundes datter. Den samme forespørgsel blev kørt otte gange: uden filter, med første version, med den rettede og med en kontrol, på dansk og på engelsk. I to kørsler mere blev Claude spurgt om omsætningen i hver by.

Med første version skrev Claude til brugeren: „Filen indeholder ikke selve CPR-numrene, telefonnumrene og de fleste emails.“ Det passede ikke. Filen var urørt. Claude fik pladsholderne uden at vide, hvor de kom fra. Claude troede, at filen var maskeret, og ville have sendt dig på jagt efter en anden fil.

Første version havde også en anden fejl. Én oplysning slap igennem: peter.dahl@eksempel-tømrer.dk. Mønstret for mails kendte kun bogstaverne a til z, så et ø i domænet var nok til, at filteret ikke så en mail.

Den rettede version gør to ting. Mønstret kender alle bogstaver, og Claude får én linje med besked: hvor mange værdier filteret har skiftet ud, og at de rigtige værdier står i filen på disken. Claude Code kørte også det rettede filter uden linjen for at se, om det var linjen eller mønstret, der gjorde forskellen. Så gentog Claude fejlen i svaret på både den danske og den engelske forespørgsel. På den danske lød det: „Der er altså ingen reelle værdier at oplyse.“ Med linjen svarede Claude: „Et CPR-filter erstattede dem med pladsholdere ([CPR], [EMAIL], [TELEFON]), før jeg læste filen. De rigtige værdier står stadig i kunder.csv.“

En animation af Claudes svar i et terminalvindue. Først uden besked fra filteret: svaret lyder „CPR, email og telefon står som pladsholdere (...) i filen. Der er altså ingen reelle værdier at oplyse“, og ordene „i filen“ bliver markeret i bordeauxrødt. Så kommer filterets ene linje ind, og svaret skifter til „Et CPR-filter erstattede dem med pladsholdere (...), før jeg læste filen. De rigtige værdier står stadig i kunder.csv“.
Samme filter, samme fil. Uden filterets ene linje giver Claude filen skylden. Med den siger Claude, hvad der skete. Begge svar er Claudes egne.

Et filter, der skjuler noget uden at sige det, får Claude til at misforstå dine data. Fortæl AI'en, hvad du har fjernet.

Det, Claude så, med og uden filteret

Uden filter læste Claude 26 af 26 og gentog 10 i svaret: CPR-nummer, mail og telefon på de tre største kunder og datterens nummer fra en note. Det var også det, forespørgslen bad om. Med det rettede filter læste Claude 0 af de 26 og gentog 0.

Opgaven blev løst alligevel. Med filteret slået til blev Claude spurgt, hvor meget omsætning der lå i hver by. Svaret var rigtigt: Herning var størst med 2.480.000 kr., og alle otte byer gav 9.910.000 kr., uden at Claude så et eneste CPR-nummer.

Claude læste stadig alle otte navne og alle otte adresser i hver eneste kørsel, for dem er filteret ikke bygget til. Og et ordrenummer i en note, 3112994455, blev skiftet ud med [CPR] i hver kørsel med filteret. Det ligner et CPR-nummer, 31. december 1999 og fire cifre, og mønstret kan ikke kende forskel.

En tabel: „Det, Claude læste om én kunde“. Rækkerne er navn, CPR-nummer, mail, telefon, adresse, datterens telefon i noten og omsætning. Kolonnerne er „Uden filter“, „Første forsøg“ og „Rettet“. Uden filter når CPR, mail og telefonnumre frem. I „Første forsøg“ er CPR og telefonnumre skiftet ud, men mailen når frem. I kolonnen „Rettet“ er alle fire skiftet ud. Navn, adresse og omsætning når frem i alle tre.
Hvad filteret stopper, og hvad det lukker igennem, for én kunde fra testfilen.

Sådan tester du et filter, før du stoler på det

Det, testen viste, gælder ethvert filter, også et, du køber: et værktøj, der skal skjule persondata, en leverandør, der lover at anonymisere, eller en intern regel om at rense eksporten, før den sendes videre.

Lav en testfil med opdigtede kunder, der ligner din egen eksport. Plant de oplysninger, filteret skal fange, og læg fælderne ind med vilje: æ, ø eller å i en mail, et CPR-nummer midt i en note, en anden persons telefonnummer og et tal, der kun ligner et CPR-nummer. Send filen gennem filteret, og bed AI'en om præcis de oplysninger, filteret skal skjule. Tæl så, hvor mange af de plantede oplysninger der står i svaret.

To rækker fra testfilen vist som et kort, med hver fælde markeret. Mailen peter.dahl@eksempel-tømrer.dk er markeret „et dansk bogstav i en mail“, og ø'et er streget under. Noten „Ønsker kontakt via datteren på 61 44 32 10“ er markeret „en anden persons nummer i fritekst“. Et ordrenummer, 3112994455, er markeret „ligner et CPR-nummer“. Navnet og adressen er hver markeret „ikke filterets opgave, tæl for sig“.
To testrækker med fælderne lagt ind med vilje. Alle oplysninger er opdigtede.

Spørg til sidst AI'en, hvorfor oplysningerne mangler. Svarer den, at filen er maskeret, ved den ikke, at der sidder et filter, og så vil den før eller siden give en kollega et forkert svar.

Køber du et filter, så stil leverandøren to spørgsmål: Har I testet det på æ, ø og å, og hvad får AI'en at vide, når noget er fjernet?

Det kan filteret ikke

Filteret kender formater, ikke betydning. Det giver fem begrænsninger:

  • Navne, adresser og det, der står om kunden i noterne, går igennem.
  • Et nummer, der ligner et CPR-nummer, bliver fanget, selv om det er et ordrenummer.
  • Det, du selv skriver i prompten, bliver ikke filtreret. Kun det, værktøjerne henter.
  • Det mindsker, hvad Claude ser. Data ligger stadig på maskinen, og navnene når stadig frem til Claude, så anonymiseret er filen ikke.
  • Tekst, der er formet om, går igennem. Mønstret leder efter 123456-7890. Sætter en kommando mellemrum mellem tegnene, så der står 1 2 3 4 5 6 - 7 8 9 0, genkender mønstret det ikke.

Mods kører desuden med samme adgang til maskinen som Claude Code selv. Anthropic skriver, at de ikke er sandboxede, og at du kun skal installere mods fra kilder, du stoler på. En mod, der skal beskytte dine data, kan altså også læse dem. Filteret er på 53 linjer i alt, heraf 37 linjer kode, og dem skal du læse, før du installerer det. Anthropics egen guide siger om en anden mod, der leder efter farlige kommandoer: „It's a safety net, not a permission system.“ Det gælder også her.

Tilføjet 2. oktober. En læser spurgte, om filteret kun holder øje med Read, så Claude kunne se de rå værdier gennem grep eller Bash i stedet. Claude Code kørte seks test mere på den samme fil. Grep efter et navn, grep efter selve CPR-nummeret og udskrift af filen gennem Bash: 0 af 26 nåede frem til Claude hver gang, fordi filteret tjekker resultatet fra alle værktøjer, ikke kun Read. Uden filter nåede 26 af 26 frem. Da Claude blev bedt om at finde en vej uden om filteret, sagde Claude nej og kaldte filteret en bevidst beskyttelse af persondata. Men da Claude fik besked på at køre en kommando, der sætter mellemrum mellem tegnene, slap 25 af 26 igennem. Filteret stopper altså uheld, ikke en, der vil have fat i dataene.

Kundeeksporten i Claude Code er din beslutning

Har du ansvaret for GDPR, er det dig, der afgør, om dine folk må bruge Claude Code på kundeeksporten. Filteret afgør, om CPR-numre, mails og telefonnumre når frem til Claude, og dermed hvad Claude kan gentage i et svar, og hvad der sendes til modellen. Det ændrer ikke din databehandleraftale, og det ændrer ikke, hvor længe Anthropic gemmer det, der sendes. Om det sidste har jeg skrevet i artiklen om nul datalagring: Aftalen om datalagring styrer, hvad Anthropic beholder. Filteret styrer, hvad Anthropic får.

Har din virksomhed Claude Team eller Enterprise, kan en administrator sørge for, at filteret bliver indlæst for alle, før de mods, folk selv installerer. Så er det ikke op til den enkelte at huske det. Anthropic har selv en indbygget mod, sec-default, som på de planer og på maskiner med managed settings indlæses først og forhindrer mods, som brugerne selv installerer, i at gøre noget risikabelt. Husk at sætte sec-default på listen sammen med filteret, ellers mister du dens begrænsninger.

Til den, der sætter det op: Filteret ligger gratis som en zip-fil med vejledning. Pak den ud, start Claude Code med claude --plugin-dir ./cpr-filter, og kør claude plugin test ./cpr-filter, før du stoler på det. Tilpas mønstrene til dine egne numre, for eksempel kunde- eller medarbejdernumre. Det kræver Claude Code 2.1.287 eller nyere.

AI-implementering med filteret på plads fra start

Som AI-konsulent sætter jeg Claude op i virksomheder, hvor kundedata er en del af arbejdet. Det svære er at finde ud af, hvilke numre og navne der står i dine egne eksporter, at bygge en testfil med de rigtige fælder og at rulle filteret ud centralt til alle, så ingen skal huske det. Det gør jeg som en del af interne AI-værktøjer eller som AI-rådgivning før en udrulning. Det kan starte med kolonneoverskrifterne fra din eksport. Dem kan du sende uden en eneste kunde i, og så kan jeg se, hvad filteret skal fange.

Jeg er også ved at bygge mit eget produkt, PrivaThor: et Windows-program, der finder og erstatter persondata i dokumenter helt offline, så du kan dele dem med tredjepart eller AI, uden at indholdet forlader din maskine. Det er lavet til finans, forsikring og sundhed i Norden og lanceres snart. Du kan skrive dig op på ventelisten nu.

FAQ

Ofte stillede spørgsmål

En lille funktion i TypeScript, som Claude Code kalder, når noget sker, for eksempel når Claude bruger et værktøj. En mod kan se på det, der sker, ændre det eller svare i stedet for Claude Code. Mods kom den 1. oktober 2026 og kræver Claude Code 2.1.287 eller nyere.

Det afhænger af din databehandleraftale, din plan og dine egne regler for persondata. Et filter som dette mindsker, hvad Claude læser og kan gentage, men navne og adresser går igennem, og aftalen er den samme. Er du i tvivl, så brug en testfil med opdigtede kunder, til du har det på plads.

Det, Claude læser i en fil, bliver sendt til modellen som en del af samtalen, også CPR-numre. Med filteret er CPR-numre, mails og danske telefonnumre skiftet ud med pladsholdere, før det sker. Hvor længe Anthropic gemmer data, afhænger af din plan og din aftale.

Ikke efter Anthropics egen beskrivelse. Anthropic beskriver kun mods i Claude Code: i terminalen, i desktop-appens Code-fane, i VS Code-udvidelsen og med claude -p. Den almindelige Claude-chat og Cowork nævnes hverken i lanceringen eller i dokumentationen.

En mod kører med samme adgang som Claude Code: Den kan læse filer, starte programmer og bruge netværket. Installér kun mods fra kilder, du stoler på, og læs koden først. Kommandoen claude plugin validate viser, hvilke hændelser en mod lytter på, og hvad den beder Claude Code om, før du installerer den.

Lav en testfil med opdigtede kunder, og plant de oplysninger, filteret skal fange. Læg fælder ind: æ, ø og å i en mail, et CPR-nummer i en note og et tal, der kun ligner et CPR-nummer. Bed AI'en om oplysningerne, og tæl, hvor mange der står i svaret. Spørg også, hvorfor oplysningerne mangler.

Kilder

Sådan blev denne artikel til. Dette arbejde er udarbejdet i samarbejde med AI. Overordnet: AI cirka 83 procent, Kim cirka 17 procent. I selve produktionen lavede AI cirka 94 procent. Claude Code byggede filteret og testfilen, kørte de ti optagne kørsler, heriblandt to kontrolkørsler, fandt fejlen med ø og testede demoen i en browser, før der blev skrevet et ord af artiklen. Tre Claude-agenter i rollen som kritiske læsere skærpede vinklen og bad om en mere realistisk testfil og om kontrolkørslerne. Arbejdsreglerne, tonen og metoden skrev Kim på forhånd. Tallene er et kvalificeret skøn, ikke en målt log.

Portrætbanner på lys baggrund. Overskriften „Hvem lavede arbejdet?“, derunder to tal for AI og Kim og en delt bjælke i samme forhold. Nederst otte fasebjælker med hver sin etiket.
Fordelingen er et kvalificeret skøn over den færdige opgave, ikke en målt log.

Få nye essays på mail.

Cirka to gange om måneden. Samme stemme. Ingen listeudlejning, ingen retargeting.

Beskyttet af Cloudflare Turnstile. Ingen challenge, ingen CAPTCHA. Brinvik deler aldrig din adresse.