Hemmelighedsscanning
fremforge leder efter committede legitimationsoplysninger med gitleaks tre steder:
| Hvor | Hvad det gør | Kan det slås fra? |
|---|---|---|
| Push-beskyttelse | Et pre-receive-hook scanner hvert push og afviser det med det samme | Nej |
| Tjek på pull requests | fremforge/secret-scan fejler en pull request, der tilføjer en secret, også i arkiver og Git LFS-filer | Ja, pr. organisation |
| Gennemgang af historikken | En gang om ugen læser gitleaks git hele historikken i hvert repository og viser det, der allerede er committet | Nej |
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:
| Udbyder | Regel-id | Hvad den finder |
|---|---|---|
| Hetzner Cloud | hetzner-cloud-api-token | Et API-token under et HCLOUD_- eller HETZNER_-navn, også TF_VAR_hcloud_token |
| Scaleway | scaleway-secret-key | En hemmelig nøgle under et SCW_- eller SCALEWAY_-navn |
| Scaleway | scaleway-key-pair | En adgangsnøgle efterfulgt af dens secret_key, som i ~/.config/scw/config.yaml |
| OVHcloud | ovh-application-secret | OVH_APPLICATION_SECRET, OVH_CONSUMER_KEY eller OVH_CLIENT_SECRET |
| OVHcloud | ovh-conf-application-secret | application_secret, consumer_key eller client_secret i en ovh.conf-fil |
| IONOS Cloud | ionos-cloud-token | Et token under et IONOS_-navn |
| T Cloud / Open Telekom Cloud | otc-secret-access-key | En 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 Cloud | otc-terraform-provider-secret-key | secret_key skrevet direkte i en opentelekomcloud-providerblok |
| T Cloud / Open Telekom Cloud | otc-credentials-csv | Den 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:
| Udbyder | Regel-id | Hvad den finder | Ved push |
|---|---|---|---|
| Supabase | supabase-access-token | Et personligt adgangstoken, klassisk eller afgrænset, eller et OAuth-adgangstoken: sbp_, sbp_oauth_ eller sbp_v0_ efterfulgt af 40 hexadecimale tegn | Blokerer |
| Supabase | supabase-secret-key | En 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 ikke | Blokerer |
| Lovable | lovable-api-key | En API-nøgle til et workspace (lov_…) | Blokerer |
| Pydantic | pydantic-logfire-token | Et Logfire-skrivetoken eller en API-nøgle, eller en nøgle til Pydantic AI Gateway (pylf_v…) | Blokerer |
| Cloudsmith | cloudsmith-api-key | En API-nøgle: 40 hexadecimale tegn under et Cloudsmith-navn som CLOUDSMITH_API_KEY | Kun 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:
- Et nøgleordsfilter beholder kun de linjer, der nævner en adgangskode eller har
user:password@i en URL, omkring 1 % af linjerne. - 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.
| Filer | Præcision | Recall |
|---|---|---|
| Kode (værdier i anførselstegn) | 0,94 | 0,98 |
| Konfiguration | 0,96 | 0,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).
| Felt | Påkrævet | Hvad det gør |
|---|---|---|
name | ja | Vises på hvert fund. Op til 80 tegn. |
regex | ja | RE2-syntaks, op til 300 tegn. |
keywords | nej | Op til 10. Mønstret kører kun på indhold, der indeholder et af dem, hvilket holder push hurtige. |
entropy | nej | 0 til 8. Match med mindre tilfældighed end dette, fx pladsholdere, rapporteres ikke. |
allowlist_paths | nej | Op til 20 sti-globs (*, **, ?), hvor mønstret ikke rapporteres. Et glob matcher på ethvert mappeniveau. |
repository | nej | Ét af organisationens repositorier, efter navn. Udelad det for alle repositorier. |
repository_id | nej | Det samme, efter repository-id. Angiv repository eller repository_id, ikke begge. |
sample | nej | Et 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.
| Udbyder | Regler, der tjekkes | Hvor tjekket går hen | Forespørgslen | Drevet | Standard |
|---|---|---|---|---|---|
fremsh | frem.sh API-tokens (ffp_) | Inden for frem.sh. Intet eksternt kald | Tokenets hash mod frem.sh’s tokenlager | — | Til |
github | GitHub-tokens | api.github.com | GET /rate_limit | Drevet fra USA | Fra |
gitlab | Personlige adgangstokens til GitLab.com (et token fra en selvadministreret server viser Ukendt) | gitlab.com | GET /api/v4/personal_access_tokens/self | Drevet fra USA | Fra |
aws | AWS-adgangsnøgler | sts.amazonaws.com | GetCallerIdentity, som ikke kræver nogen tilladelse | Drevet fra USA | Fra |
slack | Slack-tokens | slack.com | POST /api/auth.test, uden body | Drevet fra USA | Fra |
stripe | Stripe API-nøgler | api.stripe.com | GET /v1/balance | Drevet fra USA | Fra |
hetzner | Hetzner Cloud API-tokens | api.hetzner.cloud | GET /v1/locations | Drevet i EU | Fra |
scaleway | Hemmelige Scaleway-nøgler | api.scaleway.com | GET /account/v3/projects?page_size=1 | Drevet i EU | Fra |
ionos | IONOS Cloud API-tokens | api.ionos.com | GET /cloudapi/v6/ | Drevet i EU | Fra |
npm | npm-adgangstokens | registry.npmjs.org | GET /-/whoami | Drevet fra USA | Fra |
openai | OpenAI API-nøgler | api.openai.com | GET /v1/models | Drevet fra USA | Fra |
anthropic | Anthropic API-nøgler (ikke Admin API-nøgler) | api.anthropic.com | GET /v1/models | Drevet fra USA | Fra |
huggingface | Hugging Face-adgangstokens (ikke ældre api_org_-tokens) | huggingface.co | GET /api/whoami-v2 | Drevet fra USA | Fra |
digitalocean | DigitalOcean-tokens | api.digitalocean.com | GET /v2/account | Drevet fra USA | Fra |
sendgrid | SendGrid API-nøgler | api.sendgrid.com, derefter api.eu.sendgrid.com, indtil en svarer | GET /v3/scopes | Drevet fra USA | Fra |
mailgun | Private Mailgun API-nøgler | api.mailgun.net, derefter api.eu.mailgun.net, indtil en svarer | GET /v3/domains | Drevet fra USA | Fra |
datadog | Datadog API-nøgler | Datadogs 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.com | GET /api/v1/validate | Drevet fra USA | Fra |
azuredevops | Personlige Azure DevOps-adgangstokens. Kun Aktiv eller Ukendt | app.vssps.visualstudio.com | GET /_apis/profile/profiles/me | Drevet fra USA | Fra |
ovh | OVHcloud API-legitimationsoplysninger. Kun Aktiv eller Ukendt | eu.api.ovh.com | GET /1.0/auth/currentCredential, signeret | Drevet i EU | Fra |
adafruit | Adafruit IO-nøgler | io.adafruit.com | GET /api/v2/user | Drevet fra USA | Fra |
airtable | Personlige Airtable-adgangstokens | api.airtable.com | GET /v0/meta/whoami | Drevet fra USA | Fra |
asana | Personlige Asana-adgangstokens | app.asana.com | GET /api/1.0/users/me | Drevet fra USA | Fra |
doppler | Personlige Doppler-tokens | api.doppler.com | GET /v3/me | Drevet fra USA | Fra |
dropbox | Dropbox-adgangstokens | api.dropboxapi.com | POST /2/users/get_current_account, som læser kontoen | Drevet fra USA | Fra |
easypost | EasyPost API-nøgler | api.easypost.com | GET /v2/addresses?page_size=1 | Drevet fra USA | Fra |
fastly | Fastly API-tokens | api.fastly.com | GET /tokens/self | Drevet fra USA | Fra |
heroku | Heroku API-nøgler | api.heroku.com | GET /account | Drevet fra USA | Fra |
intercom | Intercom-adgangstokens | api.intercom.io, derefter api.eu.intercom.io, derefter api.au.intercom.io, indtil en svarer | GET /me | Drevet fra USA | Fra |
lob | Lob API-nøgler | api.lob.com | GET /v1/addresses?limit=1 | Drevet fra USA | Fra |
notion | Notion-integrationstokens | api.notion.com | GET /v1/users/me | Drevet fra USA | Fra |
postman | Postman API-nøgler | api.getpostman.com, derefter api.eu.postman.com, indtil en svarer | GET /me | Drevet fra USA | Fra |
readme | ReadMe API-nøgler | dash.readme.com | GET /api/v1 | Drevet fra USA | Fra |
rubygems | RubyGems API-nøgler | rubygems.org | GET /api/v1/gems.json | Drevet fra USA | Fra |
shippo | Shippo API-tokens | api.goshippo.com | GET /addresses/?results=1 | Drevet fra USA | Fra |
square | Square-adgangstokens | connect.squareup.com, derefter connect.squareupsandbox.com, indtil en svarer | GET /v2/merchants/me | Drevet fra USA | Fra |
brevo | Brevo (Sendinblue) API-nøgler | api.brevo.com | GET /v3/account | Drevet i EU | Fra |
gocardless | GoCardless-adgangstokens (live) | api.gocardless.com | GET /creditors?limit=1 | Drevet fra Storbritannien | Fra |
duffel | Duffel-adgangstokens | api.duffel.com | GET /air/airlines?limit=1 | Drevet fra Storbritannien | Fra |
cohere | Cohere API-nøgler | api.cohere.com | POST /v1/check-api-key, Coheres eget nøgletjek | Drevet fra Canada | Fra |
hcpterraform | HCP Terraform API-tokens. Kun Aktiv eller Ukendt | app.terraform.io, derefter app.eu.terraform.io, indtil en svarer | GET /api/v2/account/details | Drevet fra USA | Fra |
pulumi | Pulumi-adgangstokens. Kun Aktiv eller Ukendt | api.pulumi.com | GET /api/user | Drevet fra USA | Fra |
sentry | Sentry-brugertokens. Kun Aktiv eller Ukendt | sentry.io | GET /api/0/ | Drevet fra USA | Fra |
messagebird | MessageBird-adgangsnøgler. Kun Aktiv eller Ukendt | rest.messagebird.com | GET /balance | Drevet i EU | Fra |
typeform | Personlige Typeform-adgangstokens. Kun Aktiv eller Ukendt | api.typeform.com, derefter api.eu.typeform.com, indtil en svarer | GET /me | Drevet i EU | Fra |
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_limitKommandoen 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:
| Signal | Virkning |
|---|---|
| Den præcise linje findes stadig i standardbranchens nuværende kode | Sandsynligvis aktiv |
| Push-beskyttelsen har blokeret samme type secret i dette repository inden for de seneste 90 dage | Sandsynligvis aktiv |
| Linjen blev senere ændret eller fjernet på standardbranchen | Muligvis aktiv: at fjerne den tilbagekaldte den ikke |
| Commit’et findes kun på en anden branch end standardbranchen | Muligvis aktiv |
| Committet inden for de seneste 90 dage | Hæver skønnet |
| Committet for mere end to år siden og ikke i den nuværende kode | Mindre 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.