Skip to content
BETAGuardrails are in beta. The library, the configuration format and the CLI command can still change.

Guardrails / secrets

No credential the detector found at or above the severity gate

secrets/no-hardcoded-credentials@v1

Every secret the detector reported sits below the severity the team gates on, or is a rule the team has already accepted.

Idsecrets/no-hardcoded-credentials
Versionv1
Categorysecrets
Default severityerror
Interpreterpython3
Timeout30 seconds
Violations tolerated0
Collectssecrets

Collectors

This guardrail gathers nothing itself. It depends on the collectors below, which the CLI runs once per build before any check, and reads what they found out of GUARDRAIL_FACTS. A collector that collects nothing skips this guardrail rather than failing it.

CollectorGathersInputs it is given
secretsSecrets found in the checkout, read from the report a secret scanner already left behind, or collected by running gitleaks or trufflehog when the runner carries one and no report is there. Only the rule, the file, the line and a fingerprint are collected: the matched value never is, because these facts are attached to the run event.none

The inputs above are this guardrail's own, passed straight through. Configuring one in buildnote.json changes what is collected, and two guardrails configured the same way share the one collection.

Configuration

json
{
  "guardrails": {
      "failOn": "error",
      "comment": true,
      "checks": [
          {
              "use": "secrets/no-hardcoded-credentials@v1",
              "severity": "error",
              "with": {
                  "severity": "high",
                  "ignore": ""
              },
              "exemptions": []
          }
      ]
  }
}

Inputs

InputDescriptionDefaultEnvironment variable
severityLowest severity that violates: critical, high, medium, low or info. A detector that verified a credential against the service it belongs to reports critical; an unverified match reports high.highGUARDRAIL_INPUT_SEVERITY
ignoreComma separated rule ids the team has already looked at and accepted, such as generic-api-key. A rule named here is left out of the verdict, so name only the ones somebody judged.``GUARDRAIL_INPUT_IGNORE

How to fix

A credential that reached the repository is compromised from the moment it was pushed, so deleting the line is not the fix. Rotate it first, then take it out of the checkout, then keep it out:

bash
gh secret set STRIPE_API_KEY --body "$(op read op://deploy/stripe/api-key)"
git rm --cached config/app.yaml && echo 'config/app.yaml' >> .gitignore

Read the value from the environment where it is used, so there is nothing left in the repository to detect:

kotlin
val apiKey = System.getenv("STRIPE_API_KEY") ?: error("STRIPE_API_KEY is not set")

Where a match is a fixture rather than a credential, name its rule in ignore and say in the pull request why it is not one. Raising severity to clear the board is not that: it hides every rule at once, and an override nobody can see is the finding auditors report most often.

More in secrets

  • secrets/detector-ran. A secret detector ran, or left a report the build can be judged on, rather than nothing having looked for a credential at all.
  • secrets/gitignore-present. The repository carries a .gitignore, so build output and the local credential files beside it are not committed by the next person who runs git add ..
  • secrets/no-credential-files-committed. None of the well known credential files is in the working tree: no .env, no private key, no keystore, no kubeconfig and no cloud credential file.

All 4 secrets guardrails

Buildnote Limited
Registered in England and Wales, Reg: 16140412