Skip to content

[Linting Rule] No Leaked Credentials

github-actions[bot] edited this page Jun 16, 2026 · 1 revision

This document was generated from 'src/documentation/wiki-linter.ts' on 2026-06-16, 07:18:00 UTC presenting an overview of flowR's linter (v2.10.9). Please do not edit this file/wiki page directly.

No Leaked Credentials [overview]

smell security experimental

This rule is a best-effort rule.

Detects hardcoded credentials assigned to variables whose names suggest they hold passwords, tokens, or API keys, or whose values match known credential formats (AWS, GitHub, Slack, Stripe, SSH).
This linting rule is implemented in src/linter/rules/no-leaked-credentials.ts.

Configuration

Linting rules can be configured by passing a configuration object to the linter query as shown in the example below. The no-leaked-credentials rule accepts the following configuration options:

  • credentialNamePattern
    Pattern matched (case-insensitively) against variable names to identify potential credential assignments
  • credentialValuePattern
    Pattern matched against string literal values to detect known credential formats (e.g., AWS access key IDs, GitHub tokens)

Examples

password <- "s3cr3t"

The linting query can be used to run this rule on the above example:

[ { "type": "linter",   "rules": [ { "name": "no-leaked-credentials",     "config": {} } ] } ]

Results (prettified and summarized):

Query: linter (1 ms)
   ╰ No Leaked Credentials (no-leaked-credentials):
       ╰ uncertain:
           ╰ Possible hardcoded credential in password at 1.1-8
       ╰ Metadata: totalChecked: 1, searchTimeMs: 1, processTimeMs: 0
All queries together required ≈1 ms (1ms accuracy, total 1 ms)

Show Detailed Results as Json

The analysis required 0.9 ms (including parsing and normalization and the query) within the generation environment.

In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR. Please consult the Interface wiki page for more information on how to get those.

{
  "linter": {
    "results": {
      "no-leaked-credentials": {
        "results": [
          {
            "certainty": "uncertain",
            "involvedId": 0,
            "variableName": "password",
            "loc": [
              1,
              1,
              1,
              8
            ]
          }
        ],
        ".meta": {
          "totalChecked": 1,
          "searchTimeMs": 1,
          "processTimeMs": 0
        }
      }
    },
    ".meta": {
      "timing": 1
    }
  },
  ".meta": {
    "timing": 1
  }
}

Additional Examples

These examples are synthesized from the test cases in: test/functionality/linter/lint-no-leaked-credentials.test.ts

Test Case: no credentials

Given the following input:

x <- 42

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: password assignment

Given the following input:

password <- "s3cr3t"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'password', loc: [1, 1, 1, 8] }]

See here for the test-case implementation.

Test Case: api_key assignment

Given the following input:

api_key <- "abc123-xyz"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'api_key', loc: [1, 1, 1, 7] }]

See here for the test-case implementation.

Test Case: token assignment

Given the following input:

auth_token <- "Bearer abc123"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'auth_token', loc: [1, 1, 1, 10] }]

See here for the test-case implementation.

Test Case: case insensitive match

Given the following input:

PASSWORD <- "hunter2"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'PASSWORD', loc: [1, 1, 1, 8] }]

See here for the test-case implementation.

Test Case: non-string value not flagged

Given the following input:

password <- getPass()

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: numeric value not flagged

Given the following input:

secret <- 42

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: unrelated variable with plain string not flagged

Given the following input:

greeting <- "hello world"

We expect the linter to report the following:

* no lints

See here for the test-case implementation.

Test Case: multiple assignments

Given the following input:

x <- "hello"
password <- "mypass"
y <- 1

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'password', loc: [2, 1, 2, 8] }]

See here for the test-case implementation.

Test Case: api.key with dot separator

Given the following input:

api.key <- "tok_12345"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'api.key', loc: [1, 1, 1, 7] }]

See here for the test-case implementation.

Test Case: custom name pattern

Given the following input:

mysupersecretvar <- "secret"

And using the following configuration:

{ credentialNamePattern: 'mysupersecretvar' }

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'mysupersecretvar', loc: [1, 1, 1, 16] }]

See here for the test-case implementation.

Test Case: aws access key id detected by value

Given the following input:

x <- "AKIAIOSFODNN7EXAMPLE"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'x', loc: [1, 1, 1, 1] }]

See here for the test-case implementation.

Test Case: github pat detected by value

Given the following input:

connection <- "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'connection', loc: [1, 1, 1, 10] }]

See here for the test-case implementation.

Test Case: pem private key detected by value

Given the following input:

data <- "-----BEGIN RSA PRIVATE KEY-----"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'data', loc: [1, 1, 1, 4] }]

See here for the test-case implementation.

Test Case: slack token detected by value

Given the following input:

bot <- "xoxb-1234567890-abcdefghijklmn"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'bot', loc: [1, 1, 1, 3] }]

See here for the test-case implementation.

Test Case: stripe key detected by value

Given the following input:

client <- "sk_live_12345abcdefghijklmnopqrs"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'client', loc: [1, 1, 1, 6] }]

See here for the test-case implementation.

Test Case: name and value both match

Given the following input:

api_key <- "AKIAIOSFODNN7EXAMPLE"

We expect the linter to report the following:

[{ certainty: LintingResultCertainty.Uncertain, variableName: 'api_key', loc: [1, 1, 1, 7] }]

See here for the test-case implementation.

Clone this wiki locally