Sikkerhed og drift

API-nøgler og secrets: få dem ud af koden og under kontrol

En app kan virke perfekt og stadig være åben, hvis en databaseadgang, betalingsnøgle eller integrationstoken ligger i frontend, Git-historikken eller en log. Her får I en praktisk model til at finde, placere, begrænse og rotere de følsomme adgange uden at gøre driften afhængig af én persons hukommelse.

En secret er en adgang – ikke bare en tekststreng

En secret er en værdi, der giver adgang eller beviser en identitet. Det kan være en API-nøgle, databaseforbindelse, adgangskode, privat nøgle, webhook-signatur, servicekonto eller et token til deployment. Hvis værdien kan bruges til at læse data, ændre noget eller bruge virksomhedens kvote, skal den behandles som en adgang.

Browseren kan ikke holde på en hemmelighed. Alt, der sendes til frontend, kan undersøges af brugeren i JavaScript, netværkskald eller buildfiler. En skjult variabel i hostingens kontrolpanel er derfor ikke hemmelig, hvis buildprocessen bagefter lægger værdien ind i browserkoden.

Sortér værdierne, før I flytter dem

Ikke alle felter med navnet “API key” er secrets. Firebase-webkonfiguration er for eksempel offentlig af design; adgangen til Firestore og Storage skal håndhæves med Security Rules og relevante begrænsninger. Vurder derfor, hvad værdien faktisk kan, i stedet for kun at se på navnet.

TypeEksempelRigtig placeringKontrol
Offentlig konfigurationAPI-base-URL, Firebase-webkonfigurationMå være i frontendBegræns API'er, domæner, kvote og dataadgang
Applikations-secretBetalingsnøgle, databaseadgang, OAuth client secretKun server-sideMindste rettighed, isoleret miljø og rotation
Personligt tokenUdviklers adgang til Git eller cloudGodkendt lokal credential storePersonlig ejer, snævert scope og udløb
ArbejdsidentitetManaged identity eller OIDCCloudens identitetslagKortlivet adgang uden kopieret langtidsnøgle

Vælg opbevaring efter appens miljø

Lokal udvikling

Brug en lokal fil, som Git ignorerer, eller platformens udviklerværktøj. Commit en.env.examplemed variabelnavne og forklaring – aldrig virkelige værdier.

Hosting og functions

En lille server-side løsning kan ofte bruge hostingplatformens beskyttede miljøvariabler. Afgræns værdierne til det relevante projekt og miljø, og begræns hvem der kan læse eller ændre dem.

Secret manager eller vault

Brug eksempelvis Azure Key Vault eller Google Secret Manager, når I har flere services, skærpede adgangskrav, behov for versionshistorik, rotation eller audit af adgang. Giv appens egen identitet adgang – ikke alle udviklere.

Identitet frem for gemt nøgle

Managed identity og OIDC kan i relevante clouds give kortlivet adgang uden et langlivet credential i kode eller CI. Det er ofte mere robust end at kopiere en servicekontonøgle ind i GitHub Actions.

# .env.example – kun navne og forklaring
DATABASE_URL=
PAYMENT_API_KEY=
WEBHOOK_SIGNING_SECRET=

Frontendværdier er offentlige værdier

I Vite bliver variabler med VITE_-præfiks lagt ind i klientkoden ved build. Andre frameworks har deres egne navne og regler, men sikkerhedsgrænsen er den samme: Kode, der kører i browseren, må kun modtage værdier, som en bruger gerne må se.

  1. 1. Frontend sender en almindelig request til jeres eget backend-endpoint uden leverandørens secret.
  2. 2. Backend validerer bruger og input og afgør, om handlingen er tilladt.
  3. 3. Backend henter secret server-side og kalder betalings-, mail- eller AI-tjenesten.
  4. 4. Frontend får kun det nødvendige svar – aldrig leverandørens credential eller interne fejltekst.

En domænebegrænsning på en offentlig browsernøgle kan være nyttig, men gør ikke i sig selv værdien hemmelig. Det beskyttende lag skal passe til API'ets model: adgangskontrol, Security Rules, App Check, kvoter, servervalidering eller en kombination.

Adskil udvikling, test og produktion

Produktion bør ikke dele credentials eller data med lokale builds og preview-sider. En fejl i en testbranch må ikke kunne sende rigtige mails, hæve betalinger eller ændre kundedata.

  • Brug separate projekter, vaults eller tydeligt isolerede miljøer, hvor platformen understøtter det.
  • Opret forskellige API-nøgler og serviceidentiteter til udvikling, test og produktion.
  • Giv testcredentials adgang til testdata og testkonti – ikke produktionsressourcer.
  • Lad kun den godkendte produktionspipeline få adgang til produktionsværdier.
  • Dokumentér hvem der ejer hvert miljø, og hvem der må ændre secrets.

Lav et secret-register uden at skrive værdierne ned

Dokumentationen skal beskrive adgangen, men må ikke blive endnu et sted, hvor selve nøglen lækker. Et regneark, en runbook eller et internt system kan registrere:

  • Navn og formål: Hvilken integration eller funktion bruger adgangen?
  • Miljø og opbevaringssted: Hvor administreres værdien – uden at kopiere den ind i dokumentet?
  • Teknisk og forretningsmæssig ejer: Hvem kan rotere den, og hvem vurderer konsekvensen?
  • Rettigheder: Hvilke data og handlinger giver den adgang til?
  • Udløb og seneste rotation: Hvornår skal den kontrolleres eller udskiftes?
  • Afhængigheder: Hvilke apps, jobs og webhooks skal opdateres ved rotation?

Rotér uden at slukke appen

Rotation er en ændring i produktion og skal have en plan. Hvis leverandøren tillader to aktive credentials, kan I indføre en ny værdi, opdatere appen, verificere den og først derefter tilbagekalde den gamle. Understøttes overlap ikke, kræver rotation et aftalt vedligeholdelsesvindue eller en leverandørspecifik procedure.

  1. 1. Kortlæg alle forbrugere. Find app, CI, planlagte jobs, webhooks og lokale værktøjer.
  2. 2. Opret en ny begrænset adgang. Kopiér ikke automatisk gamle, brede rettigheder.
  3. 3. Opdatér ét kontrolleret miljø. Test både succes og forventede afvisninger.
  4. 4. Udgiv og overvåg. Kontrollér fejl, leverandørlogs og den kritiske funktion.
  5. 5. Tilbagekald den gamle adgang. Bekræft bagefter, at den ikke længere virker.
  6. 6. Opdatér register og runbook. Notér dato og resultat – ikke secret-værdien.

Hvis en nøgle allerede er lækket

Sletning fra den aktuelle fil er ikke nok. GitHub anbefaler, at en lækket adgang først tilbagekaldes eller roteres. Den kan stadig findes i Git-historik, forks, kloner, buildfiler, logs, screenshots eller chatforløb.

  1. Stop adgangen: Tilbagekald eller rotér hos den tjeneste, der har udstedt den.
  2. Begræns konsekvensen: Sæt integrationen på pause, hvis fortsat misbrug eller dataskade er mulig.
  3. Undersøg brugen: Kontrollér auditlogs, kald, kvote, ændringer og usædvanlige tidspunkter.
  4. Find alle kopier: Søg i repository, historik, builds, CI-logs, dokumenter og AI-chats.
  5. Ryd op med omtanke: Omskrivning af Git-historik kan påvirke commits, branches og kollegers kloner og skal koordineres.
  6. Dokumentér hændelsen: Årsag, omfang, handlinger og forebyggelse skal kunne følges bagefter.
Hvis lækket kan have givet uvedkommende adgang til personoplysninger, skal virksomheden vurdere, om der er sket et brud på persondatasikkerheden. Datatilsynet oplyser, at et anmeldelsespligtigt brud skal anmeldes uden unødig forsinkelse og om muligt inden 72 timer. Det er en konkret risikovurdering – ikke noget, der afgøres alene af, at en nøgle har været synlig.

Typiske fejl i AI-byggede apps

  • Nøglen indsættes i en prompt: Den ender i chat-, terminal- eller leverandørhistorik, fordi det var den hurtigste vej til et eksempel.
  • En offentlig variabel får et beroligende navn: VITE_SECRET_KEY er stadig offentlig, når Vite lægger den i browserens build.
  • Den rigtige .env bruges som skabelon: Filen bliver omdøbt eller kopieret og ender senere i Git.
  • Samme nøgle bruges overalt: Et testprojekt får adgang til produktion, og rotation bryder flere systemer samtidig.
  • Hele requesten logges: Authorization-header, query-parametre eller forbindelsesstrenge gemmes i fejlloggen.
  • En delt administratornøgle løser alle problemer: Der er ingen mindst mulige rettighed og ingen tydelig ejer af handlingerne.
  • Man stoler kun på automatisk maskering: Kodning, opdeling eller transformering af en værdi kan betyde, at logværktøjet ikke genkender den.

Tjekliste før medarbejdere eller kunder bruger appen

  • □ Alle API-nøgler, tokens, adgangskoder, private nøgler og forbindelsesstrenge er kortlagt.
  • □ Hver værdi er klassificeret som offentlig konfiguration, secret eller identitetsbaseret adgang.
  • □ Ingen secret ligger i frontendkode, buildoutput, Git-historik, dokumentation eller AI-chat.
  • □ Lokale env-filer er ignoreret af Git, og en værdiløs .env.example beskriver behovene.
  • □ Udvikling, test, preview og produktion bruger adskilte credentials og data.
  • □ Hver adgang har mindst mulige rettigheder, kendt ejer og relevant udløb eller rotationsplan.
  • □ Managed identity eller OIDC bruges, hvor den valgte platform understøtter det for behovet.
  • □ Logs viser hændelser og fejl uden tokens, komplette headers eller forbindelsesstrenge.
  • □ Secret scanning eller push protection hjælper med at fange nye læk – uden at erstatte review.
  • □ Runbooken beskriver rotation, lækhåndtering, afhængigheder og verifikation uden at indeholde værdierne.
  • □ Mindst én rotation er afprøvet i et sikkert miljø, og den gamle adgang er bekræftet ugyldig.

Relaterede guides

Secret-håndtering er en tværgående driftsopgave. Brug de guider, der passer til jeres stack, når nøglerne skal forbindes med backend, deployment eller en gendannelsesplan.

Officielle kilder

Den konkrete opsætning afhænger af framework, hosting og cloud. Kilderne nedenfor er brugt til sikkerhedsgrænser, opbevaring, rotation og hændelseshåndtering. Kontrollér altid den valgte platforms aktuelle dokumentation før ændringer i produktion.