Gå til hovedindhold

Hemmelighedsscanning

fremforge leder efter committede legitimationsoplysninger med gitleaks tre steder:

HvorHvad det gørKan det slås fra?
Push-beskyttelseEt pre-receive-hook scanner hvert push og afviser det med det sammeNej
Tjek på pull requestsfremforge/secret-scan fejler en pull request, der tilføjer en secret, også i arkiver og Git LFS-filerJa, pr. organisation
Gennemgang af historikkenEn gang om ugen læser gitleaks git hele historikken i hvert repository og viser det, der allerede er committetNej

Fund fra alle tre vises under Sikkerhed › Fund › Hemmelighedsscanning (/<org>/_admin/security/findings/secrets) og på GET /_app/api/v1/orgs/{org}/code-security/secrets/findings.

En secret, der allerede ligger på den branch, pull requesten merges ind i, får ikke tjekket til at fejle; se Tjek på pull requests: kun nye fund blokerer. Den vises stadig, og den ugentlige gennemgang og push-beskyttelsen er uændrede.

Europæiske cloududbydere

gitleaks’ egne regler dækker flere hundrede formater for legitimationsoplysninger, men ingen fra de europæiske cloududbydere. fremforge tilføjer regler for dem, og de kører alle tre steder ovenfor:

UdbyderRegel-idHvad den finder
Hetzner Cloudhetzner-cloud-api-tokenEt API-token under et HCLOUD_- eller HETZNER_-navn, også TF_VAR_hcloud_token
Scalewayscaleway-secret-keyEn hemmelig nøgle under et SCW_- eller SCALEWAY_-navn
Scalewayscaleway-key-pairEn adgangsnøgle efterfulgt af dens secret_key, som i ~/.config/scw/config.yaml
OVHcloudovh-application-secretOVH_APPLICATION_SECRET, OVH_CONSUMER_KEY eller OVH_CLIENT_SECRET
OVHcloudovh-conf-application-secretapplication_secret, consumer_key eller client_secret i en ovh.conf-fil
IONOS Cloudionos-cloud-tokenEt token under et IONOS_-navn
T Cloud / Open Telekom Cloudotc-secret-access-keyEn hemmelig adgangsnøgle under et navn for en hemmelig nøgle med OTC_, OS_, HW_ eller OBS_, eller et *_SK-navn, der indeholder et af dem
T Cloud / Open Telekom Cloudotc-terraform-provider-secret-keysecret_key skrevet direkte i en opentelekomcloud-providerblok
T Cloud / Open Telekom Cloudotc-credentials-csvDen credentials.csv, som konsollen downloader, når du opretter en adgangsnøgle

Disse tokens har intet fast præfiks, så en regel matcher kun, hvor udbyderens navn eller filformat siger, hvad værdien er. En løs streng på 64 tegn eller et UUID andre steder rapporteres ikke. Pladsholdere (xxxx…, nul-UUID’et) og variabelreferencer (${HCLOUD_TOKEN}) ignoreres. For en legitimationsoplysning, som disse regler ikke dækker, kan du tilføje et eget mønster.

Flere detektorer

fremforge tilføjer også regler for disse legitimationsoplysninger ud over gitleaks’ egne:

UdbyderRegel-idHvad den finderVed push
Supabasesupabase-access-tokenEt personligt adgangstoken, klassisk eller afgrænset, eller et OAuth-adgangstoken: sbp_, sbp_oauth_ eller sbp_v0_ efterfulgt af 40 hexadecimale tegnBlokerer
Supabasesupabase-secret-keyEn hemmelig projektnøgle (sb_secret_…), som omgår Row Level Security. Publicerbare nøgler (sb_publishable_…) er beregnet til browsere og rapporteres ikke, og det gør Supabase CLI’ens offentliggjorte lokale standardnøgle heller ikkeBlokerer
Lovablelovable-api-keyEn API-nøgle til et workspace (lov_…)Blokerer
Pydanticpydantic-logfire-tokenEt Logfire-skrivetoken eller en API-nøgle, eller en nøgle til Pydantic AI Gateway (pylf_v…)Blokerer
Cloudsmithcloudsmith-api-keyEn API-nøgle: 40 hexadecimale tegn under et Cloudsmith-navn som CLOUDSMITH_API_KEYKun rapporteret

Hver regel matcher tokenets eget faste præfiks eller format med grænser for længde og entropi, så den blokerer ved push som enhver anden regel, og tilsidesættelse og omgåelse gælder for den. En Cloudsmith-nøgle har intet præfiks, så dens regel er kun rapporteret. En Cloudsmith-nøgle, der tildeles et navn som CLOUDSMITH_API_KEY, blokeres som regel alligevel af gitleaks’ generiske regel for API-nøgler.

Det er kun regler til at finde dem. fremforge tilbyder ikke gyldighedstjek for dem.

Adgangskoder i konfigurationsfiler

fremforge-password-config finder en adgangskode skrevet direkte ind i en konfigurations- eller scriptfil, for eksempel DB_PASSWORD=… i en .env-fil, password: … i YAML, spring.datasource.password=… eller ENV REDIS_PASS=… i en Dockerfile. Den læser .env-filer, YAML, .properties, .ini, .conf, .cfg, .toml, shell-, PowerShell- og batch-scripts, Dockerfiles og compose-filer. Den leder efter en nøgle, der er opkaldt efter en adgangskode (password, passwd, passphrase, pwd, pass), med en værdi uden anførselstegn, der afslutter linjen. Den udelader:

  • referencer til en anden værdi (${DB_PASSWORD}, %(password)s, {{ … }});
  • pladsholdere (changeme, example, xxx);
  • oversættelseskataloger;
  • indstillinger, der navngiver en hash eller en algoritme (root_password_sha2, password.encoding.alg).

Den er en heuristik, ikke et tokenformat. Vi har målt den på CredData, et offentligt, mærket datasæt med legitimationsoplysninger i open source-repositorier, mod gitleaks’ generiske regel for API-nøgler på de samme filer. Den var mere præcis og fandt flere af de rigtige adgangskoder, på data der var holdt uden for dens tilpasning (præcision 0,97 mod 0,95, recall 8 % mod 5 % af alle mærkede adgangskoder). Den er kun rapporteret. Den læser ikke kildekode, og en værdi i anførselstegn i YAML (password: "…") er ikke dækket: de former blev også målt og slog ikke den generiske regel.

Adgangskoder fundet af en klassifikator (fremforges egne organisationer)

Et andet trin læser kode- og konfigurationsfiler for hardkodede adgangskoder, der ikke har noget tokenformat, som db_password = "…" i Python eller password: "…" i YAML. Det kører i dag kun på fremforges egne organisationer. Det er endnu ikke tilgængeligt for kunders organisationer; det er en separat beslutning efter to ugers data om falske positiver.

Det arbejder i to trin, efter reglerne ovenfor, i tjekket på pull requests:

  1. Et nøgleordsfilter beholder kun de linjer, der nævner en adgangskode eller har user:password@ i en URL, omkring 1 % af linjerne.
  2. En maskinlæringsklassifikator giver hver af de linjer en score. Det er modellen fra CredSweeper (Samsung, MIT-licens), gentrænet af fremforge. Den kører inde i scanneren uden netværksadgang, og ingen kode eller værdi forlader den.

Et fund har regel-id’et fremforge-password-ml. Et fund i en teststi (test/, __tests__/, *.test.ts, test_*.py, *_test.go og lignende) beholdes med regel-id’et fremforge-password-ml-test-path og mærkes som sandsynligvis testdata. Begge er kun rapporteret.

Den udelader:

  • dokumentation, datafiler og alt, der ikke er kode eller konfiguration;
  • oversættelseskataloger;
  • konstanter, der indeholder et regulært udtryk om adgangskoder, som PASSWORD_RE;
  • linjer, som en anden regel allerede har rapporteret.

Hvis klassifikatoren ikke kan køre eller tager mere end 120 sekunder, rapporterer tjekket de andre reglers fund som normalt.

Sådan blev den målt. Vi gentrænede modellen på CredDatas udviklingsrepositorier, kun dem under en permissiv licens, og gav den én score på repositorier, der var holdt uden for træningen. Tærsklen blev fastlagt, før den score blev taget.

FilerPræcisionRecall
Kode (værdier i anførselstegn)0,940,98
Konfiguration0,960,99

Adgangskoder i URL’er og i andre filer nåede ikke en præcision på 0,9 og rapporteres ikke. Træningsrepositorierne og deres licenser står i scannerens NOTICE-training-data.md.

Regler, der kun rapporteres

cloudsmith-api-key, fremforge-password-config, fremforge-password-ml og fremforge-password-ml-test-path rapporteres kun. Deres fund vises under Sikkerhed › Fund › Hemmelighedsscanning, og de to gitleaks-regler også i gennemgangen af historikken (klassifikatoren kører kun i tjekket på pull requests). I en pull request vises de i fremforge/secret-scan som advisory (not blocking): de får aldrig tjekket til at fejle og blokerer aldrig et push. Alle andre regler blokerer.

Indstillingen

Blokér pull requests, der tilføjer en secret afgør, om tjekket på pull requests kører. Indtil en organisation gemmer et valg, kører tjekket og blokerer. Når den er slået fra, kører tjekket ikke, og dets status fjernes fra branch-beskyttelsen; push-beskyttelsen og den ugentlige gennemgang kører videre. Sæt den under Sikkerhed › Fund › Hemmelighedsscanning eller med PUT /_app/api/v1/orgs/{org}/code-security/secrets/settings og {"enabled": true} (policy:write).

Egne mønstre

Din organisation kan tilføje sine egne formater for secrets: en tokenform, som kun du udsteder, et internt nøglepræfiks, en partners legitimationsoplysning. Hvert mønster bliver en ekstra gitleaks-regel alle tre steder ovenfor, så et match blokeres ved push, får tjekket på pull requesten til at fejle og findes i historikken. Et fund fra et eget mønster har regel-id’et custom-<name> og viser mønstrets navn.

Tilføj dem under Sikkerhed › Politikker › Push-beskyttelse › Egne hemmelighedsmønstre eller med POST /_app/api/v1/orgs/{org}/code-security/secrets/custom-patterns (policy:write; GET viser dem, PUT og DELETE på /custom-patterns/{id} ændrer og fjerner et).

FeltPåkrævetHvad det gør
namejaVises på hvert fund. Op til 80 tegn.
regexjaRE2-syntaks, op til 300 tegn.
keywordsnejOp til 10. Mønstret kører kun på indhold, der indeholder et af dem, hvilket holder push hurtige.
entropynej0 til 8. Match med mindre tilfældighed end dette, fx pladsholdere, rapporteres ikke.
allowlist_pathsnejOp til 20 sti-globs (*, **, ?), hvor mønstret ikke rapporteres. Et glob matcher på ethvert mappeniveau.
repositorynejÉt af organisationens repositorier, efter navn. Udelad det for alle repositorier.
repository_idnejDet samme, efter repository-id. Angiv repository eller repository_id, ikke begge.
samplenejEt eksempel, som mønstret skal matche. Tjekkes, når du gemmer, og gemmes aldrig.

Send "dry_run": true for at validere uden at gemme.

Ét repository eller dem alle. Et mønster uden repository gælder for alle organisationens repositorier. Et mønster med et repository gælder kun for det repository, alle tre steder, sammen med dem, der gælder for hele organisationen. I konsollen vælger du repositoriet på listen eller Alle repositorier. Mønstret er knyttet til selve repositoriet, ikke dets navn: omdøber du repositoriet, bliver mønstret på det. Et repository, der slettes og senere oprettes igen med samme navn, er et nyt repository og arver det ikke. Et mønster, hvis repository er slettet eller flyttet til en anden organisation, gælder ingen steder og vises som sådan, indtil du ændrer eller sletter det. Svarene indeholder både repository_id og repository, repositoriets nuværende navn.

# Validate only
curl -sS -X POST "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Acme deploy key", "regex": "acme_live_[A-Za-z0-9]{24}", "sample": "KEY=acme_live_abcdefghijklmnopqrstuvwx", "dry_run": true}'
# {"valid": true, "rule_id": "custom-acme-deploy-key"}

# Create (201)
curl -sS -X POST "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Acme deploy key", "regex": "acme_live_[A-Za-z0-9]{24}", "keywords": ["acme_live_"], "allowlist_paths": ["test/fixtures/**"]}'

# List
curl -sS "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN"

# Replace (the whole pattern) and delete
curl -sS -X PUT "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns/$ID" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Acme deploy key", "regex": "acme_live_[A-Za-z0-9]{32}"}'
curl -sS -X DELETE "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns/$ID" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN"

Et afvist mønster besvares med 400 og en problem+json-body, hvis type angiver årsagen: invalid-repository, invalid-regex, regex-too-complex, regex-matches-empty, regex-too-broad, sample-not-matched, invalid-name, invalid-keywords, invalid-entropy eller invalid-allowlist-paths. Et andet mønster med samme navn besvares med 409 duplicate-name, et 101. med too-many-patterns, og et 21. uden nøgleord med too-many-without-keywords.

Med Terraform/OpenTofu-provideren:

resource "fremforge_secret_custom_pattern" "acme_deploy_key" {
  org             = "acme"
  name            = "Acme deploy key"
  regex           = "acme_live_[A-Za-z0-9]{24}"
  keywords        = ["acme_live_"]
  allowlist_paths = ["test/fixtures/**"]
  # repository    = "infra"   # one repository only (provider 0.7.0 and later)
}

Hvorfor kun RE2. Et mønster kører inde i push-hooket ved hvert push. RE2 har ingen backtracking, så køretiden vokser lineært med inputtet, og intet mønster kan få et push til at gå i stå. Tilbagereferencer (\1) og lookarounds ((?=, (?!, (?<=) kræver backtracking og afvises. Et mønster afvises også, når det:

  • matcher en tom streng eller almindelig tekst som const x = 1;;
  • gentager mere end 256 gange ({n,m}) eller indlejrer grupper mere end 6 niveauer dybt.

Test et mønster, før du gemmer det

Test på repositories i formularen til at tilføje et mønster, eller dry-run-API’et, kører et kandidatmønster på det seneste commit i hvert repositorys standardbranch og viser, hvor det ville matche. Intet gemmes: mønstret lagres ikke, der oprettes intet fund, og resultatet gemmes i 24 timer.

Det viser repository, fil, linje, commit og fingeraftryk for hvert match, aldrig den matchede tekst. Hvert repository tælles én gang i en af tre grupper:

  • tjekket;
  • kunne ikke tjekkes: kloning mislykkedes, tidsgrænsen blev nået, scanningen mislykkedes, eller det blev ikke nået inden for grænsen på 10 minutter;
  • sprunget over: arkiveret, et spejl, tomt, for stort (over 100 MB eller en checkout over 256 MB) eller over grænsen på 200 repositorier.

Et mønster, der er afgrænset til ét repository, testes kun på det repository.

# Start one (202); the body is the same as creating a pattern
curl -sS -X POST "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns/dry-runs" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN" -H 'Content-Type: application/json' \
  -d '{"name": "Acme deploy key", "regex": "acme_live_[A-Za-z0-9]{24}", "keywords": ["acme_live_"]}'
# {"id": "…", "status": "queued", …}

# Read it back until status is done (or failed)
curl -sS "https://frem.sh/_app/api/v1/orgs/$ORG/code-security/secrets/custom-patterns/dry-runs/$ID" \
  -H "Authorization: Bearer $FREMFORGE_TOKEN"
# {"status": "done", "repositories": {"total": 118, "scanned": 70, "not_checked": 48},
#  "matches": [{"repository": "web", "path": "config/partner.txt", "line": 1, "commit": "…", "fingerprint": "…"}], …}

Begge kræver policy:write, fordi resultatet navngiver filer på tværs af alle organisationens repositorier. Der kører én testkørsel pr. organisation ad gangen, og der kan startes én hvert 10. minut. En kørsel, som ingen scanner tager imod inden for 2 minutter, ender som failed med error: expired; start den igen et par minutter senere. Når en startes, registreres det i revisionsloggen som code-security.secret_scan.custom_pattern.dry_run_started. En afvist start besvares med de samme typer som ved oprettelse af et mønster eller med dry-run-in-progress (409), dry-run-cooldown (429) eller dry-run-unavailable (503).

Grænser. En organisation kan have op til 100 mønstre, inklusive dem, der er afgrænset til ét repository. Højst 20 af dem må være uden keywords. Svaret på listen angiver begge som limit og limit_without_keywords.

Grunden er tiden ved push. Et mønster med nøgleord kører kun på indhold, der indeholder et af dem, så det koster næsten intet. Et mønster uden nøgleord kører på hver del af hvert push. Målt med vores push-hook tog 200 mønstre uden nøgleord et push med 100 commits fra omkring 2 sekunder til 17. Et nøgleord er som regel hemmelighedens faste præfiks.

Når du gemmer eller sletter et mønster, sættes en ny scanning af hele historikken i hvert repository i kø, så et nyt mønster også finder det, der allerede er committet. Det tager som regel op til 15 minutter. Ændringer registreres i revisionsloggen som code-security.secret_scan.custom_pattern.created, .updated og .deleted.

Hvis mønstrene ikke kan indlæses ved push, for eksempel mens API’et kortvarigt ikke kan nås, scannes pushet stadig med de indbyggede regler, og en linje i revisionsloggen registrerer, at de egne mønstre ikke blev anvendt. Gennemgangen af historikken finder så det oversete, når den når standardbranchen.

Gyldighedstjek

En secret, der stadig virker, haster mere end en, der allerede er roteret. Et gyldighedstjek spørger den tjeneste, der udstedte en fundet secret, om den stadig er aktiv, og mærker fundet Aktiv, Inaktiv eller Ukendt. Aktive fund vises først, i konsollen og i API’et (validity, validity_checked_at).

Hver udbyder er sin egen indstilling under Sikkerhed › Politikker › Push-beskyttelse › Gyldighedstjek eller PUT /_app/api/v1/orgs/{org}/code-security/secrets/validity-settings/{provider} med {"enabled": true} (policy:write). Før du slår et til, viser siden, hvilken vært tjekket kontakter, og om udbyderen er Drevet fra USA, Drevet i EU, Drevet fra Storbritannien eller Drevet fra Canada. API’et angiver det samme som operator_jurisdiction (us, eu, uk, ca eller null for det interne tjek). Storbritannien og Canada har begge en tilstrækkelighedsafgørelse fra EU; ingen udbyder, der drives fra et andet land uden for EU, tilbydes på GET .../validity-settings.

Denne tabel er den liste over udbydere, som databehandleraftalen (bilag B §B.10) henviser til. fremforge tilbyder kun et tjek for en udbyder på listen, hver med én skrivebeskyttet forespørgsel til en fast vært, eller, hvor en udbyder betjener sine nøgler fra regionale værter (SendGrid, Mailgun, Datadog, Intercom, Postman, Square, HCP Terraform, Typeform), til en fast liste af værter, der spørges i rækkefølge; du kan ikke tilføje din egen URL. En udbyder, der tilføjes senere, starter slået fra.

UdbyderRegler, der tjekkesHvor tjekket går henForespørgslenDrevetStandard
fremshfrem.sh API-tokens (ffp_)Inden for frem.sh. Intet eksternt kaldTokenets hash mod frem.sh’s tokenlager—Til
githubGitHub-tokensapi.github.comGET /rate_limitDrevet fra USAFra
gitlabPersonlige adgangstokens til GitLab.com (et token fra en selvadministreret server viser Ukendt)gitlab.comGET /api/v4/personal_access_tokens/selfDrevet fra USAFra
awsAWS-adgangsnøglersts.amazonaws.comGetCallerIdentity, som ikke kræver nogen tilladelseDrevet fra USAFra
slackSlack-tokensslack.comPOST /api/auth.test, uden bodyDrevet fra USAFra
stripeStripe API-nøglerapi.stripe.comGET /v1/balanceDrevet fra USAFra
hetznerHetzner Cloud API-tokensapi.hetzner.cloudGET /v1/locationsDrevet i EUFra
scalewayHemmelige Scaleway-nøglerapi.scaleway.comGET /account/v3/projects?page_size=1Drevet i EUFra
ionosIONOS Cloud API-tokensapi.ionos.comGET /cloudapi/v6/Drevet i EUFra
npmnpm-adgangstokensregistry.npmjs.orgGET /-/whoamiDrevet fra USAFra
openaiOpenAI API-nøglerapi.openai.comGET /v1/modelsDrevet fra USAFra
anthropicAnthropic API-nøgler (ikke Admin API-nøgler)api.anthropic.comGET /v1/modelsDrevet fra USAFra
huggingfaceHugging Face-adgangstokens (ikke ældre api_org_-tokens)huggingface.coGET /api/whoami-v2Drevet fra USAFra
digitaloceanDigitalOcean-tokensapi.digitalocean.comGET /v2/accountDrevet fra USAFra
sendgridSendGrid API-nøglerapi.sendgrid.com, derefter api.eu.sendgrid.com, indtil en svarerGET /v3/scopesDrevet fra USAFra
mailgunPrivate Mailgun API-nøglerapi.mailgun.net, derefter api.eu.mailgun.net, indtil en svarerGET /v3/domainsDrevet fra USAFra
datadogDatadog API-nøglerDatadogs seks sites i denne rækkefølge, indtil et svarer: api.datadoghq.com, api.datadoghq.eu, api.us3.datadoghq.com, api.us5.datadoghq.com, api.ap1.datadoghq.com, api.ddog-gov.comGET /api/v1/validateDrevet fra USAFra
azuredevopsPersonlige Azure DevOps-adgangstokens. Kun Aktiv eller Ukendtapp.vssps.visualstudio.comGET /_apis/profile/profiles/meDrevet fra USAFra
ovhOVHcloud API-legitimationsoplysninger. Kun Aktiv eller Ukendteu.api.ovh.comGET /1.0/auth/currentCredential, signeretDrevet i EUFra
adafruitAdafruit IO-nøglerio.adafruit.comGET /api/v2/userDrevet fra USAFra
airtablePersonlige Airtable-adgangstokensapi.airtable.comGET /v0/meta/whoamiDrevet fra USAFra
asanaPersonlige Asana-adgangstokensapp.asana.comGET /api/1.0/users/meDrevet fra USAFra
dopplerPersonlige Doppler-tokensapi.doppler.comGET /v3/meDrevet fra USAFra
dropboxDropbox-adgangstokensapi.dropboxapi.comPOST /2/users/get_current_account, som læser kontoenDrevet fra USAFra
easypostEasyPost API-nøglerapi.easypost.comGET /v2/addresses?page_size=1Drevet fra USAFra
fastlyFastly API-tokensapi.fastly.comGET /tokens/selfDrevet fra USAFra
herokuHeroku API-nøglerapi.heroku.comGET /accountDrevet fra USAFra
intercomIntercom-adgangstokensapi.intercom.io, derefter api.eu.intercom.io, derefter api.au.intercom.io, indtil en svarerGET /meDrevet fra USAFra
lobLob API-nøglerapi.lob.comGET /v1/addresses?limit=1Drevet fra USAFra
notionNotion-integrationstokensapi.notion.comGET /v1/users/meDrevet fra USAFra
postmanPostman API-nøglerapi.getpostman.com, derefter api.eu.postman.com, indtil en svarerGET /meDrevet fra USAFra
readmeReadMe API-nøglerdash.readme.comGET /api/v1Drevet fra USAFra
rubygemsRubyGems API-nøglerrubygems.orgGET /api/v1/gems.jsonDrevet fra USAFra
shippoShippo API-tokensapi.goshippo.comGET /addresses/?results=1Drevet fra USAFra
squareSquare-adgangstokensconnect.squareup.com, derefter connect.squareupsandbox.com, indtil en svarerGET /v2/merchants/meDrevet fra USAFra
brevoBrevo (Sendinblue) API-nøglerapi.brevo.comGET /v3/accountDrevet i EUFra
gocardlessGoCardless-adgangstokens (live)api.gocardless.comGET /creditors?limit=1Drevet fra StorbritannienFra
duffelDuffel-adgangstokensapi.duffel.comGET /air/airlines?limit=1Drevet fra StorbritannienFra
cohereCohere API-nøglerapi.cohere.comPOST /v1/check-api-key, Coheres eget nøgletjekDrevet fra CanadaFra
hcpterraformHCP Terraform API-tokens. Kun Aktiv eller Ukendtapp.terraform.io, derefter app.eu.terraform.io, indtil en svarerGET /api/v2/account/detailsDrevet fra USAFra
pulumiPulumi-adgangstokens. Kun Aktiv eller Ukendtapi.pulumi.comGET /api/userDrevet fra USAFra
sentrySentry-brugertokens. Kun Aktiv eller Ukendtsentry.ioGET /api/0/Drevet fra USAFra
messagebirdMessageBird-adgangsnøgler. Kun Aktiv eller Ukendtrest.messagebird.comGET /balanceDrevet i EUFra
typeformPersonlige Typeform-adgangstokens. Kun Aktiv eller Ukendtapi.typeform.com, derefter api.eu.typeform.com, indtil en svarerGET /meDrevet i EUFra

Personlige Azure DevOps-adgangstokens, Datadog API-nøgler og personlige Asana-adgangstokens findes af tre fremforge-regler, azure-devops-pat, datadog-api-key og asana-personal-access-token, som kører alle tre steder ovenfor.

Nogle tjek kan vise, at en secret er aktiv, men aldrig, at den ikke er. Azure DevOps afviser et aktivt token, der er begrænset til én organisation eller mangler profil-scopet, så en afvisning der viser Ukendt, aldrig Inaktiv. En OVHcloud-forespørgsel skal signeres med applikationsnøglen, applikationshemmeligheden og forbrugernøglen sammen. Tjekket kører kun, når gennemgangen af historikken finder alle tre i samme fil, som en ovh.conf, og ethvert andet svar end succes viser Ukendt. HCP Terraform-, Pulumi- og Sentry-tokens kan tilhøre en selvhostet Terraform Enterprise, Pulumi eller Sentry, som den offentlige tjeneste afviser. MessageBird-nøgler fra den nyere Bird-platform kan blive afvist af MessageBirds oprindelige API. Et Typeform-token uden konto-scopet kan blive afvist på samme måde som et dødt. Derfor viser disse fem Aktiv eller Ukendt, aldrig Inaktiv.

En secret er kun inaktiv, når alle værter siger det. En SendGrid-nøgle, der er låst til EU-regionen, fejler på den globale vært, en Datadog-nøgle hører til ét af Datadogs sites, og en Intercom-, Postman- eller Typeform-nøgle til én af deres regioner; et Square-sandbox-token fejler i produktion. Derfor spørger tjekket værterne i den viste rækkefølge og stopper ved den første, der svarer, at secreten er aktiv. Den viser kun Inaktiv, når alle værter afviser den.

Intet automatisk tjek: Atlassian, Twilio, Flutterwave, Mailchimp, Telegram, selvadministreret GitLab og T Cloud. Deres fund har kun Tjek den selv. Et Atlassian-token kræver også sitet og kontoens e-mailadresse, og en Twilio API-nøgle kræver sit SID. Flutterwave-reglen finder kun testnøgler. En Mailchimp-nøgle angiver sin egen datacentervært, så der er ingen fast vært at tjekke. Telegram drives fra et land uden for EU, Storbritannien, Canada og USA. En selvadministreret GitLab-server, eller enhver anden vært, du vælger, er en destination, som fremforge ikke kontakter på dine vegne. T Cloud er den cloud, fremforge selv kører på, og dens identitetstjeneste kan bevidst ikke nås fra fremforges tjek. For en T Cloud-nøgle beder kommandoen OBS om at liste dine buckets: en nøgle, der ikke kendes, besvares med InvalidAccessKeyId.

En nøgle, der er aktiv, men ikke må foretage tjekkets læsning, tæller som Aktiv: en Stripe-nøgle, der nægtes saldoen, en Scaleway-nøgle, der nægtes projekterne, en Anthropic-nøgle, der afvises med permission_error, en OpenAI-nøgle, der afvises for manglende tilladelser, et Dropbox-token, der afvises med missing_scope, eller en Heroku-, RubyGems-, Square-, Asana-, GoCardless- eller Duffel-nøgle, der afvises med 403. For de udbydere, der blev tilføjet 2026-10-24, viser kun det præcise svar, hver af dem giver en nøgle, der ikke findes, Inaktiv; ethvert andet svar viser Ukendt. OpenAI’s invalid_api_key er det eneste OpenAI-svar, der læses som Inaktiv. Anthropic Admin API-nøgler og ældre organisationstokens fra Hugging Face tjekkes ikke, fordi endpointene ovenfor ikke kan afgøre, om de er aktive.

Sådan virker et tjek, og hvad der gemmes. Hvert tjek er skrivebeskyttet. Det spørger, hvem et token tilhører, eller om det er gyldigt, og ændrer aldrig noget hos udbyderen. Selve secreten gemmes stadig aldrig. Mens gennemgangen af historikken læser et repository, krypterer scanneren hver matchende værdi til en nøgle, som API’et opretter til netop den ene scanning. API’et åbner den, kører tjekket, beholder kun resultatet og tidspunktet for tjekket og kasserer værdien. Nøglen slettes, når scanningen slutter. Scanneren selv har ingen netværksadgang til udbyderne.

Et frem.sh-token tjekkes mod frem.sh’s eget tokenlager, og dets tilstand læses live: tilbagekalder du tokenet, vises fundet straks som Inaktiv. For de andre udbydere er tilstanden fra den seneste gennemgang, der læste secreten.

Ukendt betyder, at udbyderen ikke gav et klart svar, for eksempel ved en timeout eller en hastighedsbegrænsning, en AWS-nøgle, hvis hemmelige halvdel ikke blev fundet inden for fem linjer fra den, eller en OVHcloud-legitimationsoplysning, hvis tre dele ikke blev fundet sammen. Ukendt vises aldrig som Inaktiv.

Når du slår en udbyder til, scannes historikken i alle repositorier igen, fordi værdien af en fundet secret kun findes, mens gennemgangen læser den. Slår du den fra, ryddes udbyderens resultater. Ændringer registreres i revisionsloggen som code-security.secret_scan.validity.updated.

Tjek den selv, og markér den så

Du behøver ikke slå et gyldighedstjek til for at vide, om en secret stadig virker. For en secret udstedt af en af udbyderne ovenfor, eller af Atlassian, Twilio, Flutterwave, Mailchimp, Telegram, en selvadministreret GitLab-server eller T Cloud, har fundet Tjek den selv: udbyderens egen skrivebeskyttede forespørgsel som en kommando, du kører i din terminal, for eksempel for et GitHub-token:

read -rs TOKEN && curl -s -o /dev/null -w '%{http_code}\n' -H "Authorization: Bearer $TOKEN" https://api.github.com/rate_limit

Kommandoen indeholder aldrig secreten. Den venter på, at du skriver eller indsætter den, viser den ikke og holder den ude af din shell-historik. Den sendes kun til udbyderen, aldrig til fremforge. Fundet fortæller, hvad kommandoen udskriver, når secreten er aktiv (her 200), og når den ikke er (401).

Registrér derefter, hvad du fandt, med Markér aktiv eller Markér roteret i fundets menu, eller PUT /_app/api/v1/orgs/{org}/code-security/secrets/findings/{id}/mark med {"mark": "active"}, {"mark": "rotated"} eller {"mark": null} (findings:write). Et fund, der er markeret aktivt, vises sammen med de aktive. Hver placering markeres for sig: en markering hører til ét fund (én fil, linje og commit) og bevares på tværs af gennemgange af historikken, ligesom en afvisning. Blev den samme secret fundet i to commits, så markér begge. fremforge gemmer intet afledt af secreten, der kunne binde placeringerne sammen. En markering afviser ikke fundet. Hver markering registreres i revisionsloggen som code-security.secrets.marked. Fund-API’et returnerer markeringen som mark og kommandoen som self_check.

Rotér som udgangspunkt, og hvilke du skal rotere først

Behandl enhver secret, der er fundet her, som kompromitteret, og rotér den, medmindre udbyderen eller du har bekræftet, at den ikke længere virker. At fjerne en secret fra koden tilbagekalder den ikke: den bliver i historikken, hvor alle med læseadgang kan finde den.

For at hjælpe dig med at beslutte, hvilke du skal rotere først, når ingen udbyder har svaret, sorteres fundene efter, hvor sandsynligt det er, at secreten stadig er aktiv. Skønnet bruger kun det, fremforge allerede ved, aldrig selve secreten, og kontakter ingen:

SignalVirkning
Den præcise linje findes stadig i standardbranchens nuværende kodeSandsynligvis aktiv
Push-beskyttelsen har blokeret samme type secret i dette repository inden for de seneste 90 dageSandsynligvis aktiv
Linjen blev senere ændret eller fjernet på standardbranchenMuligvis aktiv: at fjerne den tilbagekaldte den ikke
Commit’et findes kun på en anden branch end standardbranchenMuligvis aktiv
Committet inden for de seneste 90 dageHæver skønnet
Committet for mere end to år siden og ikke i den nuværende kodeMindre sandsynligt aktiv

En udbyders eget svar (Aktiv eller Inaktiv) og din egen markering går altid forud. Skønnet vises med op til to af sine begrundelser på hvert fund, som ingen udbyder har svaret på, og som du ikke har markeret. Signalerne fra koden registreres af den ugentlige gennemgang af historikken, så et fund, der blev gennemgået før den gennemgang, der tilføjede dem, kun viser signalet fra push-beskyttelsen indtil den næste. Fund-API’et returnerer det som likely_live (level og reasons) sammen med committed_at. Det er null, når en udbyder har svaret, eller fundet er markeret. Det er et skøn, ikke et tjek: “Mindre sandsynligt aktiv” betyder stadig, at du skal rotere.

Hvad der gemmes

Kun et fingeraftryk af matchet gemmes, aldrig den matchede tekst. Regel, sti, linje og commit er nok til at åbne filen ved den commit. Et gyldighedstjek tilføjer resultatet og tidspunktet. For et frem.sh-token gemmer det også id’et på den matchende tokenpost, aldrig selve tokenet.

Når en secret er fundet

Rotér først legitimationsoplysningen ved kilden. At slette linjen gør ikke lækket ugjort: alle, der har historikken, har stadig værdien. Fjern den derefter fra koden: Åbn rettelses-PR i fundets kolonne Ret flytter en legitimationsoplysning i Go, Python, JavaScript eller TypeScript over i en miljøvariabel, uden AI; se Regelbaserede rettelser. Pull requesten fjerner ikke værdien fra historikken, så rotation kommer først under alle omstændigheder.

Se også