Hoppa till huvudinnehållet

Hemlighetsskanning

fremforge letar efter incheckade inloggningsuppgifter med gitleaks på tre ställen:

VarVad den görKan den stängas av?
Push-skyddEn pre-receive-hook skannar varje push och avvisar den direktNej
Kontroll av pull requestsfremforge/secret-scan underkänner en pull request som lägger till en hemlighet, även i arkiv och Git LFS-filerJa, per organisation
Genomsökning av historikenEn gång i veckan läser gitleaks git hela historiken i varje repo och listar det som redan är incheckatNej

Fynd från alla tre listas under Säkerhet › Fynd › Hemlighetsskanning (/<org>/_admin/security/findings/secrets), och på GET /_app/api/v1/orgs/{org}/code-security/secrets/findings.

En hemlighet som redan finns på den branch som pull requesten mergas in i underkänner inte kontrollen; se Kontroller av pull requests: bara nya fynd blockerar. Den listas fortfarande, och den veckovisa genomsökningen och Push-skydd är oförändrade.

Europeiska molnleverantörer

gitleaks egna regler täcker flera hundra format för inloggningsuppgifter, men inga från de europeiska molnleverantörerna. fremforge lägger till regler för dem, och de körs på alla tre ställena ovan:

LeverantörRegel-idVad den hittar
Hetzner Cloudhetzner-cloud-api-tokenEn API-token under ett namn med HCLOUD_ eller HETZNER_, inklusive TF_VAR_hcloud_token
Scalewayscaleway-secret-keyEn hemlig nyckel under ett namn med SCW_ eller SCALEWAY_
Scalewayscaleway-key-pairEn åtkomstnyckel följd av sin 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 fil ovh.conf
IONOS Cloudionos-cloud-tokenEn token under ett namn med IONOS_
T Cloud / Open Telekom Cloudotc-secret-access-keyEn hemlig åtkomstnyckel under ett namn för hemlig nyckel med OTC_, OS_, HW_ eller OBS_, eller ett namn på *_SK som innehåller något av dem
T Cloud / Open Telekom Cloudotc-terraform-provider-secret-keysecret_key skriven direkt i ett provider-block för opentelekomcloud
T Cloud / Open Telekom Cloudotc-credentials-csvFilen credentials.csv som konsolen laddar ned när du skapar en åtkomstnyckel

De här tokens har inget fast prefix, så en regel matchar bara där leverantörens namn eller filformat säger vad värdet är. En lös sträng på 64 tecken eller ett UUID någon annanstans rapporteras inte. Platshållare (xxxx…, noll-UUID:t) och variabelreferenser (${HCLOUD_TOKEN}) ignoreras. För en inloggningsuppgift som de här reglerna inte täcker, lägg till ett eget mönster.

Fler detektorer

fremforge lägger också till regler för de här inloggningsuppgifterna, utöver gitleaks egna:

LeverantörRegel-idVad den hittarVid push
Supabasesupabase-access-tokenEn personlig åtkomsttoken, klassisk eller avgränsad, eller en OAuth-åtkomsttoken: sbp_, sbp_oauth_ eller sbp_v0_ följt av 40 hexadecimala teckenBlockerar
Supabasesupabase-secret-keyEn hemlig projektnyckel (sb_secret_…), som kringgår Row Level Security. Publicerbara nycklar (sb_publishable_…) är avsedda för webbläsare och rapporteras inte, och inte heller Supabase CLI:s publicerade lokala standardnyckelBlockerar
Lovablelovable-api-keyEn API-nyckel för en arbetsyta (lov_…)Blockerar
Pydanticpydantic-logfire-tokenEn skrivtoken eller API-nyckel för Logfire, eller en nyckel för Pydantic AI Gateway (pylf_v…)Blockerar
Cloudsmithcloudsmith-api-keyEn API-nyckel: 40 hexadecimala tecken under ett Cloudsmith-namn som CLOUDSMITH_API_KEYBara rapporterad

Varje regel matchar tokens eget fasta prefix eller format, med gränser för längd och entropi, så den blockerar vid push som alla andra regler, och vägarna för undantag och förbikoppling gäller för den. En Cloudsmith-nyckel har inget prefix, så dess regel är bara rapporterad. En Cloudsmith-nyckel som tilldelas ett namn som CLOUDSMITH_API_KEY blockeras oftast ändå, av gitleaks generiska regel för API-nycklar.

Det här är bara detekteringsregler. fremforge erbjuder ingen giltighetskontroll för dem.

Lösenord i konfigurationsfiler

fremforge-password-config hittar ett lösenord som skrivits direkt i en konfigurations- eller skriptfil, till exempel 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, skal-, PowerShell- och batchskript, Dockerfiles och compose-filer. Den letar efter en nyckel som är uppkallad efter ett lösenord (password, passwd, passphrase, pwd, pass) och som har ett bart värde som avslutar raden. Den utelämnar:

  • referenser till ett annat värde (${DB_PASSWORD}, %(password)s, {{ … }});
  • platshållare (changeme, example, xxx);
  • översättningskataloger;
  • inställningar som anger en hash eller en algoritm (root_password_sha2, password.encoding.alg).

Det är en heuristik, inte ett tokenformat. Vi mätte den på CredData, en publik märkt uppsättning inloggningsuppgifter i repon med öppen källkod, mot gitleaks generiska regel för API-nycklar på samma filer. Den var mer precis och hittade fler av de verkliga lösenorden, på data som hölls utanför dess justering (precision 0,97 mot 0,95, recall 8 % mot 5 % av alla märkta lösenord). Den är bara rapporterad. Den läser inte källkod, och ett värde inom citattecken i YAML (password: "…") täcks inte: de formerna mättes också och slog inte den generiska regeln.

Lösenord som hittas av en klassificerare (fremforges egna organisationer)

Ett andra steg läser kod- och konfigurationsfiler efter hårdkodade lösenord som saknar tokenformat, till exempel db_password = "…" i Python eller password: "…" i YAML. Det körs i dag bara på fremforges egna organisationer. Det är ännu inte tillgängligt för kunders organisationer; det är ett separat beslut efter två veckors data om falska positiva.

Det fungerar i två steg, bakom reglerna ovan, i kontrollen av pull requests:

  1. Ett nyckelordsfilter behåller bara de rader som nämner ett lösenord eller har user:password@ i en URL, ungefär 1 % av raderna.
  2. En maskininlärningsklassificerare poängsätter var och en av de raderna. Det är modellen från CredSweeper (Samsung, MIT-licens), omtränad av fremforge. Den körs inne i skannern utan nätverksåtkomst, och ingen kod eller inget värde lämnar den.

Ett fynd har regel-id:t fremforge-password-ml. Ett fynd i en testsökväg (test/, __tests__/, *.test.ts, test_*.py, *_test.go och liknande) behålls med regel-id:t fremforge-password-ml-test-path och märks som troligen en fixtur. Båda är bara rapporterade.

Det utelämnar:

  • dokumentation, datafiler och allt som inte är kod eller konfiguration;
  • översättningskataloger;
  • konstanter som innehåller ett reguljärt uttryck om lösenord, till exempel PASSWORD_RE;
  • rader som redan rapporterats av en annan regel.

Om klassificeraren inte kan köras eller tar längre tid än 120 sekunder rapporterar kontrollen de andra reglernas fynd som vanligt.

Hur den mättes. Vi tränade om modellen på CredDatas utvecklingsrepon, med bara de som har en tillåtande licens, och poängsatte den en gång på repon som hållits utanför träningen. Tröskeln låstes innan den poängen togs.

FilerPrecisionRecall
Kod (värden inom citattecken)0,940,98
Konfiguration0,960,99

Lösenord i URL:er och i andra filer nådde inte precisionen 0,9 och rapporteras inte. Träningsrepona och deras licenser listas i skannerns NOTICE-training-data.md.

Regler som bara rapporteras

cloudsmith-api-key, fremforge-password-config, fremforge-password-ml och fremforge-password-ml-test-path rapporteras bara. Deras fynd listas under Säkerhet › Fynd › Hemlighetsskanning, och de två gitleaks-reglerna även i genomsökningen av historiken (klassificeraren körs bara i kontrollen av pull requests). I en pull request visas de i fremforge/secret-scan som advisory (not blocking): de underkänner aldrig kontrollen och blockerar aldrig en push. Alla andra regler blockerar.

Inställningen

Blockera pull requests som lägger till en secret avgör om kontrollen av pull requests körs. Tills en organisation har sparat ett val körs kontrollen och blockerar. När den är avstängd körs kontrollen inte och dess status tas bort från branch-skyddet; Push-skydd och den veckovisa genomsökningen fortsätter att köras. Ange den under Säkerhet › Fynd › Hemlighetsskanning eller med PUT /_app/api/v1/orgs/{org}/code-security/secrets/settings och {"enabled": true} (policy:write).

Egna mönster

Din organisation kan lägga till egna format för hemligheter: en tokenform som bara du utfärdar, ett internt nyckelprefix, en partners inloggningsuppgift. Varje mönster blir en extra gitleaks-regel på alla tre ställena ovan, så en träff blockeras vid push, underkänner kontrollen av pull requests och hittas i historiken. Ett fynd från ett eget mönster har regel-id:t custom-<name> och visar mönstrets namn.

Lägg till dem under Säkerhet › Policyer › Push-skydd › Egna hemlighetsmönster, eller med POST /_app/api/v1/orgs/{org}/code-security/secrets/custom-patterns (policy:write; GET listar dem, PUT och DELETE på /custom-patterns/{id} ändrar och tar bort ett).

FältObligatorisktVad det gör
namejaVisas på varje fynd. Upp till 80 tecken.
regexjaRE2-syntax, upp till 300 tecken.
keywordsnejUpp till 10. Mönstret körs bara på innehåll som innehåller något av dem, vilket håller pushar snabba.
entropynej0 till 8. Träffar med mindre slumpmässighet än så, till exempel platshållare, rapporteras inte.
allowlist_pathsnejUpp till 20 sökvägsmönster (*, **, ?) där mönstret inte rapporteras. Ett mönster matchar på vilken katalognivå som helst.
repositorynejEtt av organisationens repon, efter namn. Utelämna för alla repon.
repository_idnejDetsamma, efter repo-id. Ange repository eller repository_id, inte båda.
samplenejEtt exempel som mönstret måste matcha. Kontrolleras när du sparar, sparas aldrig.

Skicka "dry_run": true för att validera utan att spara.

Ett repo eller alla. Ett mönster utan repo gäller för alla organisationens repon. Ett mönster med ett repo gäller bara för det repot, på alla tre ställena, tillsammans med de som gäller hela organisationen. I konsolen väljer du repot i listan, eller Alla repon. Mönstret är knutet till själva repot, inte dess namn: om repot byter namn följer mönstret med. Ett repo som tas bort och senare skapas på nytt med samma namn är ett nytt repo och ärver det inte. Ett mönster vars repo har tagits bort eller flyttats till en annan organisation gäller ingenstans och visas så tills du ändrar eller tar bort det. Svaren innehåller både repository_id och repository, repots nuvarande namn.

# 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"

Ett avvisat mönster svarar 400 med ett problem+json-innehåll vars type anger orsaken: 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. Ett andra mönster med samma namn svarar 409 duplicate-name, ett 101:a too-many-patterns, och ett 21:a utan nyckelord too-many-without-keywords.

Med Terraform/OpenTofu-providern:

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)
}

Varför bara RE2. Ett mönster körs i push-hooken vid varje push. RE2 har ingen backtracking, så körtiden växer linjärt med indata och inget mönster kan få en push att stå still. Bakåtreferenser (\1) och lookarounds ((?=, (?!, (?<=) kräver backtracking och avvisas. Ett mönster avvisas också när det:

  • matchar en tom sträng, eller vanlig text som const x = 1;;
  • upprepas mer än 256 gånger ({n,m}), eller nästlar grupper djupare än 6 nivåer.

Testa ett mönster innan du sparar det

Testa på repon i formuläret för att lägga till, eller API:t för torrkörning, kör ett kandidatmönster över den senaste commiten på varje repos standard-branch och visar var det skulle träffa. Inget sparas: mönstret lagras inte, inget fynd skapas, och resultatet behålls i 24 timmar.

Det visar repo, fil, rad, commit och fingeravtryck för varje träff, aldrig den matchade texten. Varje repo räknas en gång, i en av tre grupper:

  • kontrollerade;
  • kunde inte kontrolleras: kloningen misslyckades, tog för lång tid, skanningen misslyckades, eller repot nåddes inte inom tidsgränsen på 10 minuter;
  • hoppades över: arkiverat, en spegel, tomt, för stort (över 100 MB, eller en utcheckning över 256 MB), eller över gränsen på 200 repon.

Ett mönster som är avgränsat till ett repo testas bara på det repot.

# 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": "…"}], …}

Båda kräver policy:write, eftersom resultatet namnger filer i alla organisationens repon. En torrkörning per organisation körs åt gången, och en kan startas var 10:e minut. En körning som ingen skanner tar emot inom 2 minuter slutar som failed med error: expired; starta den igen några minuter senare. Att starta en loggas i granskningsloggen som code-security.secret_scan.custom_pattern.dry_run_started. En avvisad start svarar med samma typer som när ett mönster skapas, eller dry-run-in-progress (409), dry-run-cooldown (429) eller dry-run-unavailable (503).

Gränser. En organisation kan ha upp till 100 mönster, inklusive de som är avgränsade till ett repo. Högst 20 av dem får sakna keywords. Listsvaret anger båda som limit och limit_without_keywords.

Orsaken är tiden vid push. Ett mönster med nyckelord körs bara på innehåll som innehåller något av dem, så det kostar nästan ingenting. Ett mönster utan nyckelord körs på varje del av varje push. Uppmätt med vår push-hook tog 200 mönster utan nyckelord en push med 100 commits från ungefär 2 sekunder till 17. Ett nyckelord är oftast hemlighetens fasta prefix.

När du sparar eller tar bort ett mönster köas en ny skanning av hela historiken i varje repo, så att ett nytt mönster även hittar det som redan är incheckat. Det tar oftast upp till 15 minuter. Ändringar loggas i granskningsloggen som code-security.secret_scan.custom_pattern.created, .updated och .deleted.

Om mönstren inte kan läsas in vid push, till exempel medan api:et en kort stund inte kan nås, skannas pushen ändå med de inbyggda reglerna, och en rad i granskningsloggen registrerar att de egna mönstren inte tillämpades. Genomsökningen av historiken hittar sedan det som missades när den når standard-branchen.

Giltighetskontroller

En hemlighet som fortfarande fungerar är mer brådskande än en som redan har roterats. En giltighetskontroll frågar den tjänst som utfärdade en upptäckt hemlighet om den fortfarande är aktiv, och märker fyndet Aktiv, Inaktiv eller Okänd. Aktiva fynd listas först, i konsolen och i API:t (validity, validity_checked_at).

Varje leverantör är en egen inställning under Säkerhet › Policyer › Push-skydd › Giltighetskontroller, eller PUT /_app/api/v1/orgs/{org}/code-security/secrets/validity-settings/{provider} med {"enabled": true} (policy:write). Innan du slår på en anger sidan vilken värd kontrollen kontaktar och om leverantören är USA-driven, EU-driven, Storbritannien-driven eller Kanada-driven. API:t rapporterar detsamma som operator_jurisdiction (us, eu, uk, ca, eller null för den interna kontrollen). Storbritannien och Kanada har båda ett beslut om adekvat skyddsnivå från EU; ingen leverantör som drivs från något annat land utanför EU erbjuds i GET .../validity-settings.

Den här tabellen är den lista över leverantörer som personuppgiftsbiträdesavtalet (bilaga B §B.10) hänvisar till. fremforge erbjuder en kontroll bara för en leverantör i den, var och en med en skrivskyddad förfrågan till en fast värd, eller, där en leverantör levererar sina nycklar från regionala värdar (SendGrid, Mailgun, Datadog, Intercom, Postman, Square, HCP Terraform, Typeform), till en fast lista med värdar som tillfrågas i tur och ordning; du kan inte lägga till en egen URL. En leverantör som läggs till senare börjar avstängd.

LeverantörRegler som kontrollerasVart kontrollen gårFörfråganDrivsStandard
fremshAPI-tokens för frem.sh (ffp_)Inom frem.sh. Inget externt anropTokens hash mot frem.sh:s tokenlager—På
githubGitHub-tokensapi.github.comGET /rate_limitUSA-drivenAv
gitlabPersonliga åtkomsttokens för GitLab.com (en token från en egen server blir Okänd)gitlab.comGET /api/v4/personal_access_tokens/selfUSA-drivenAv
awsAWS-åtkomstnycklarsts.amazonaws.comGetCallerIdentity, som inte kräver någon behörighetUSA-drivenAv
slackSlack-tokensslack.comPOST /api/auth.test, utan innehållUSA-drivenAv
stripeStripe API-nycklarapi.stripe.comGET /v1/balanceUSA-drivenAv
hetznerAPI-tokens för Hetzner Cloudapi.hetzner.cloudGET /v1/locationsEU-drivenAv
scalewayHemliga nycklar för Scalewayapi.scaleway.comGET /account/v3/projects?page_size=1EU-drivenAv
ionosAPI-tokens för IONOS Cloudapi.ionos.comGET /cloudapi/v6/EU-drivenAv
npmnpm-åtkomsttokensregistry.npmjs.orgGET /-/whoamiUSA-drivenAv
openaiOpenAI API-nycklarapi.openai.comGET /v1/modelsUSA-drivenAv
anthropicAnthropic API-nycklar (inte Admin API-nycklar)api.anthropic.comGET /v1/modelsUSA-drivenAv
huggingfaceÅtkomsttokens för Hugging Face (inte äldre api_org_-tokens)huggingface.coGET /api/whoami-v2USA-drivenAv
digitaloceanDigitalOcean-tokensapi.digitalocean.comGET /v2/accountUSA-drivenAv
sendgridSendGrid API-nycklarapi.sendgrid.com, sedan api.eu.sendgrid.com, tills en svararGET /v3/scopesUSA-drivenAv
mailgunPrivata Mailgun API-nycklarapi.mailgun.net, sedan api.eu.mailgun.net, tills en svararGET /v3/domainsUSA-drivenAv
datadogDatadog API-nycklarDatadogs sex sajter i den här ordningen, tills en svarar: api.datadoghq.com, api.datadoghq.eu, api.us3.datadoghq.com, api.us5.datadoghq.com, api.ap1.datadoghq.com, api.ddog-gov.comGET /api/v1/validateUSA-drivenAv
azuredevopsPersonliga åtkomsttokens för Azure DevOps. Bara Aktiv eller Okändapp.vssps.visualstudio.comGET /_apis/profile/profiles/meUSA-drivenAv
ovhAPI-inloggningsuppgifter för OVHcloud. Bara Aktiv eller Okändeu.api.ovh.comGET /1.0/auth/currentCredential, signeradEU-drivenAv
adafruitAdafruit IO-nycklario.adafruit.comGET /api/v2/userUSA-drivenAv
airtablePersonliga åtkomsttokens för Airtableapi.airtable.comGET /v0/meta/whoamiUSA-drivenAv
asanaPersonliga åtkomsttokens för Asanaapp.asana.comGET /api/1.0/users/meUSA-drivenAv
dopplerPersonliga Doppler-tokensapi.doppler.comGET /v3/meUSA-drivenAv
dropboxDropbox-åtkomsttokensapi.dropboxapi.comPOST /2/users/get_current_account, som läser kontotUSA-drivenAv
easypostEasyPost API-nycklarapi.easypost.comGET /v2/addresses?page_size=1USA-drivenAv
fastlyFastly API-tokensapi.fastly.comGET /tokens/selfUSA-drivenAv
herokuHeroku API-nycklarapi.heroku.comGET /accountUSA-drivenAv
intercomIntercom-åtkomsttokensapi.intercom.io, sedan api.eu.intercom.io, sedan api.au.intercom.io, tills en svararGET /meUSA-drivenAv
lobLob API-nycklarapi.lob.comGET /v1/addresses?limit=1USA-drivenAv
notionIntegrationstokens för Notionapi.notion.comGET /v1/users/meUSA-drivenAv
postmanPostman API-nycklarapi.getpostman.com, sedan api.eu.postman.com, tills en svararGET /meUSA-drivenAv
readmeReadMe API-nycklardash.readme.comGET /api/v1USA-drivenAv
rubygemsRubyGems API-nycklarrubygems.orgGET /api/v1/gems.jsonUSA-drivenAv
shippoShippo API-tokensapi.goshippo.comGET /addresses/?results=1USA-drivenAv
squareSquare-åtkomsttokensconnect.squareup.com, sedan connect.squareupsandbox.com, tills en svararGET /v2/merchants/meUSA-drivenAv
brevoBrevo (Sendinblue) API-nycklarapi.brevo.comGET /v3/accountEU-drivenAv
gocardlessGoCardless-åtkomsttokens (live)api.gocardless.comGET /creditors?limit=1Storbritannien-drivenAv
duffelDuffel-åtkomsttokensapi.duffel.comGET /air/airlines?limit=1Storbritannien-drivenAv
cohereCohere API-nycklarapi.cohere.comPOST /v1/check-api-key, Coheres egen nyckelkontrollKanada-drivenAv
hcpterraformAPI-tokens för HCP Terraform. Bara Aktiv eller Okändapp.terraform.io, sedan app.eu.terraform.io, tills en svararGET /api/v2/account/detailsUSA-drivenAv
pulumiPulumi-åtkomsttokens. Bara Aktiv eller Okändapi.pulumi.comGET /api/userUSA-drivenAv
sentrySentry-användartokens. Bara Aktiv eller Okändsentry.ioGET /api/0/USA-drivenAv
messagebirdMessageBird-åtkomstnycklar. Bara Aktiv eller Okändrest.messagebird.comGET /balanceEU-drivenAv
typeformPersonliga åtkomsttokens för Typeform. Bara Aktiv eller Okändapi.typeform.com, sedan api.eu.typeform.com, tills en svararGET /meEU-drivenAv

Personliga åtkomsttokens för Azure DevOps, Datadog API-nycklar och personliga åtkomsttokens för Asana hittas av tre regler från fremforge, azure-devops-pat, datadog-api-key och asana-personal-access-token, som körs på alla tre ställena ovan.

Vissa kontroller kan visa att en hemlighet är aktiv, men aldrig att den inte är det. Azure DevOps avvisar en aktiv token som är begränsad till en organisation eller saknar profile-scope, så ett avslag där blir Okänd, aldrig Inaktiv. En förfrågan till OVHcloud måste signeras med applikationsnyckeln, applikationshemligheten och konsumentnyckeln tillsammans. Kontrollen körs bara när genomsökningen av historiken hittar alla tre i samma fil, till exempel en ovh.conf, och alla svar utom ett lyckat blir Okänd. Tokens för HCP Terraform, Pulumi och Sentry kan höra till en egenhostad Terraform Enterprise, Pulumi eller Sentry, som avvisar dem på den publika tjänsten. MessageBird-nycklar från den nyare plattformen Bird kan avvisas av MessageBirds ursprungliga API. En Typeform-token utan account-scope kan avvisas på samma sätt som en död. Därför blir dessa fem Aktiv eller Okänd, aldrig Inaktiv.

En hemlighet är inaktiv bara när alla värdar säger det. En SendGrid-nyckel som är låst till EU-regionen misslyckas på den globala värden, en Datadog-nyckel hör till en av Datadogs sajter, och en nyckel för Intercom, Postman eller Typeform till en av deras regioner; en sandbox-token för Square misslyckas i produktion. Därför frågar kontrollen värdarna i den visade ordningen och stannar vid den första som svarar att hemligheten är aktiv. Den blir Inaktiv bara när alla värdar avvisar den.

Ingen automatisk kontroll: Atlassian, Twilio, Flutterwave, Mailchimp, Telegram, egen GitLab-server och T Cloud. Deras fynd har bara Kontrollera själv. En Atlassian-token kräver även sajten och kontots e-postadress, och en Twilio API-nyckel kräver sitt SID. Flutterwave-regeln hittar bara testnycklar. En Mailchimp-nyckel anger sin egen datacentervärd, så det finns ingen fast värd att kontrollera. Telegram drivs från utanför EU, Storbritannien, Kanada och USA. En egen GitLab-server, eller någon annan värd du väljer, är ett mål som fremforge inte kontaktar för din räkning. T Cloud är det moln som fremforge självt körs på, och dess identitetstjänst kan avsiktligt inte nås från fremforges kontroller. För en T Cloud-nyckel ber kommandot OBS att lista dina buckets: en nyckel som inte är känd svarar InvalidAccessKeyId.

En nyckel som är aktiv men inte får göra kontrollens läsning räknas som Aktiv: en Stripe-nyckel som nekas saldot, en Scaleway-nyckel som nekas projekten, en Anthropic-nyckel som avvisas med permission_error, en OpenAI-nyckel som avvisas för att behörigheter saknas, en Dropbox-token som avvisas med missing_scope, eller en nyckel för Heroku, RubyGems, Square, Asana, GoCardless eller Duffel som avvisas med 403. För de leverantörer som lades till 2026-10-24 blir bara det exakta svar som var och en ger för en nyckel som inte finns Inaktiv; alla andra svar blir Okänd. OpenAI:s invalid_api_key är det enda svaret från OpenAI som läses som Inaktiv. Admin API-nycklar för Anthropic och äldre organisationstokens för Hugging Face kontrolleras inte, eftersom slutpunkterna ovan inte kan avgöra om de är aktiva.

Så fungerar en kontroll, och vad som sparas. Varje kontroll är skrivskyddad. Den frågar vem en token tillhör eller om den är giltig, och ändrar aldrig något hos leverantören. Hemligheten sparas fortfarande aldrig. Medan genomsökningen av historiken läser ett repo krypterar skannern varje matchande värde med en nyckel som api:et skapar för just den skanningen. Api:et öppnar det, kör kontrollen, behåller bara utfallet och när det kontrollerades, och kastar värdet. Nyckeln tas bort när skanningen är klar. Skannern själv har ingen nätverksåtkomst till leverantörerna.

En token för frem.sh kontrolleras mot frem.sh:s eget tokenlager, och dess tillstånd läses direkt: om token återkallas visas fyndet som Inaktiv direkt. För de andra leverantörerna är tillståndet från den senaste genomsökningen som läste hemligheten.

Okänd betyder att leverantören inte gav något tydligt svar, till exempel en timeout eller en hastighetsbegränsning, en AWS-nyckel vars hemliga halva inte hittades inom fem rader från den, eller en OVHcloud-inloggningsuppgift vars tre delar inte hittades tillsammans. Okänd visas aldrig som Inaktiv.

När du slår på en leverantör skannas historiken i varje repo om, eftersom en hittad hemlighets värde bara finns medan genomsökningen läser den. När du stänger av den rensas den leverantörens utfall. Ändringar loggas i granskningsloggen som code-security.secret_scan.validity.updated.

Kontrollera själv och markera sedan

Du behöver inte slå på en giltighetskontroll för att veta om en hemlighet fortfarande fungerar. För en hemlighet som utfärdats av någon av leverantörerna ovan, eller av Atlassian, Twilio, Flutterwave, Mailchimp, Telegram, en egen GitLab-server eller T Cloud, har fyndet Kontrollera själv: leverantörens egen skrivskyddade förfrågan som ett kommando att köra i din terminal, till exempel för en GitHub-token:

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

Kommandot innehåller aldrig hemligheten. Det väntar på att du skriver eller klistrar in den, visar den inte och håller den borta från skalhistoriken. Den går bara till leverantören, aldrig till fremforge. Fyndet anger vad kommandot skriver ut när hemligheten är aktiv (här 200) och när den inte är det (401).

Registrera sedan vad du kom fram till med Markera aktiv eller Markera roterad i fyndets meny, eller PUT /_app/api/v1/orgs/{org}/code-security/secrets/findings/{id}/mark med {"mark": "active"}, {"mark": "rotated"} eller {"mark": null} (findings:write). Ett fynd som markerats aktivt listas med de aktiva. Varje plats markeras separat: en markering hör till ett fynd (en fil, rad och commit) och behålls mellan genomsökningar av historiken, precis som ett avfärdande. Om samma hemlighet hittades i två commits, markera båda. fremforge sparar inget som härletts från hemligheten och som skulle kunna knyta ihop platserna. En markering avfärdar inte fyndet. Varje markering loggas i granskningsloggen som code-security.secrets.marked. Findings API returnerar markeringen som mark och kommandot som self_check.

Rotera som standard, och vilka som ska roteras först

Behandla varje hemlighet som hittas här som komprometterad, och rotera den, om inte dess leverantör eller du har bekräftat att den inte längre fungerar. Att ta bort en hemlighet ur koden återkallar den inte: den finns kvar i historiken, där alla med läsåtkomst kan hitta den.

För att hjälpa dig avgöra vilka som ska roteras först när ingen leverantör har svarat ordnas fynden efter hur sannolikt det är att hemligheten fortfarande är aktiv. Uppskattningen använder bara det som fremforge redan vet, aldrig själva hemligheten, och kontaktar ingen:

SignalEffekt
Exakt samma rad finns fortfarande i standard-branchens nuvarande kodTroligen aktiv
Push-skydd blockerade samma sorts hemlighet i det här repot de senaste 90 dagarnaTroligen aktiv
Raden ändrades eller togs bort senare på standard-branchenMöjligen aktiv: att ta bort den återkallade den inte
Commiten finns bara på en annan branch än standard-branchenMöjligen aktiv
Incheckad de senaste 90 dagarnaHöjer uppskattningen
Incheckad för mer än två år sedan, och inte i den nuvarande kodenMindre troligt aktiv

En leverantörs eget svar (Aktiv eller Inaktiv) och din egen markering har alltid företräde. Uppskattningen visas, med upp till två av sina skäl, på varje fynd som ingen leverantör har svarat på och som du inte har markerat. Signalerna från koden registreras av den veckovisa genomsökningen av historiken, så ett fynd som söktes igenom före den genomsökning som lade till dem visar bara signalen från Push-skydd fram till nästa. Findings API returnerar den som likely_live (level och reasons), tillsammans med committed_at. Den är null när en leverantör har svarat eller fyndet är markerat. Det är en uppskattning, inte en kontroll: “Mindre troligt aktiv” betyder fortfarande att du ska rotera.

Vad som sparas

Bara ett fingeravtryck av träffen sparas, aldrig den matchade texten. Regeln, sökvägen, raden och commiten räcker för att öppna filen i den commiten. En giltighetskontroll lägger till utfallet och dess tidpunkt. För en token för frem.sh sparas också id:t för den matchande tokenposten, aldrig själva token.

När en hemlighet hittas

Rotera inloggningsuppgiften vid källan först. Att ta bort raden gör inte värdet oläckt: alla som har historiken har det fortfarande. Ta sedan bort den ur koden: Öppna fix-PR i fyndets kolumn Åtgärd flyttar en inloggningsuppgift i Go, Python, JavaScript eller TypeScript till en miljövariabel, utan AI; se Regelbaserade fixar. Pull requesten tar inte bort värdet ur historiken, så rotering kommer först i båda fallen.

Se även