Repository navigation
Scan each change for secrets with gitleaks #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
sasha-s
wants to merge
2
commits into
main
Choose a base branch
from
sl/lane_gitleaks_sweep/pos3
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| name: gitleaks | ||
|
|
||
| on: | ||
| pull_request: | ||
| push: | ||
| branches: [main, main-positronic] # owner-free: allow | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| # A push run is keyed on its own sha: each push scans only its own commits, so none may be dropped. | ||
| concurrency: | ||
| group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'push' && github.sha || 'pr' }} | ||
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | ||
|
|
||
| jobs: | ||
| gitleaks: | ||
| # Commit of Positronic-Robotics/secret-scanning to run; .gitleaks.toml is a copy of its gitleaks.toml. Public, not a secret. | ||
| # To move it, follow "Upgrading the rules or gitleaks" in that repository's README. | ||
| uses: Positronic-Robotics/secret-scanning/.github/workflows/gitleaks.yml@17271b2ddeb36438a2650e53a6e0f335832dc87e # owner-free: allow |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # Shared gitleaks rules from Positronic-Robotics/secret-scanning. A repository holds a byte-for-byte copy as | ||
| # `.gitleaks.toml`, and the reusable workflow fails when the copy differs. Edit the file in that repository, | ||
| # then follow its README upgrade steps; a copy edited elsewhere fails the check. | ||
| title = "shared gitleaks rules" | ||
|
|
||
| [extend] | ||
| useDefault = true | ||
|
|
||
| # Credential shapes the default rules miss. Each has a canary in that repository's canary_test.py. | ||
| # Deleting this section falls back to the default rules. | ||
|
|
||
| # Matches a Nebius IAM token: ne1 followed by 100 or more letters, digits, dots, dashes or underscores. | ||
| # Shape: ne1<100+ letters, digits, . - _> | ||
| [[rules]] | ||
| id = "nebius-iam-token" | ||
| description = "Nebius IAM access token (ne1 prefix)" | ||
| regex = '''\b(ne1[A-Za-z0-9][A-Za-z0-9_\-.]{99,})''' | ||
| secretGroup = 1 | ||
| entropy = 4.0 | ||
| keywords = ["ne1"] | ||
|
|
||
| # Matches an Anthropic OAuth token: sk-ant-oat or sk-ant-ort, two digits, a dash, then 80 or more | ||
| # letters, digits, dashes or underscores. Shape: sk-ant-oat01-<80+ letters, digits, - _> | ||
| [[rules]] | ||
| id = "anthropic-oauth-token" | ||
| description = "Anthropic OAuth access or refresh token" | ||
| regex = '''\b(sk-ant-o[a-z]t\d{2}-[A-Za-z0-9_\-]{80,})''' | ||
| secretGroup = 1 | ||
| keywords = ["sk-ant-oat", "sk-ant-ort"] | ||
|
|
||
| # Matches a Tailscale key: tskey-, a lowercase kind such as auth or client, then two dash-separated | ||
| # runs of letters and digits. Shape: tskey-<kind>-<6+ letters, digits>-<16+ letters, digits> | ||
| [[rules]] | ||
| id = "tailscale-key" | ||
| description = "Tailscale auth, API, OAuth client or webhook key" | ||
| regex = '''\b(tskey-[a-z]+-[A-Za-z0-9]{6,}-[A-Za-z0-9]{16,})''' | ||
| secretGroup = 1 | ||
| keywords = ["tskey-"] | ||
|
|
||
| # Matches a literal value of 16 or more characters given to a flag whose name ends in token, api key, | ||
| # password, passwd, secret, access key or auth key. Shape: --api-key=<16+ characters> or --hf-token <16+ characters> | ||
| [[rules]] | ||
| id = "cli-flag-secret" | ||
| description = "Credential passed as a command-line flag value" | ||
| # The flag name must end in the credential word, so --token-file and --password-stdin never match. | ||
| # A value starting with $ < { / . ~ or a quote is a variable, placeholder or path, not a literal. | ||
| # Inside quotes the rest of the value may hold any punctuation up to a space or the closing quote, | ||
| # except $ inside double quotes, where the shell expands it. The secret is the first group that matched. | ||
| regex = '''(?i)--(?:[a-z0-9]+[-_])*(?:token|api[-_]?key|password|passwd|secret|secret[-_]key|access[-_]key|auth[-_]?key)(?:=|[ \t]+)(?:'([^\s'$<{/.~][^\s']{15,})|"([^\s"$<{/.~][^\s"$]{15,})|([A-Za-z0-9_\-+=!@#%^&*:,][A-Za-z0-9_\-+/=.!@#%^&*~:,]{15,}))''' | ||
| entropy = 3.0 | ||
| keywords = ["token", "key", "password", "passwd", "secret"] | ||
|
|
||
| # `lpass show --password <item>` names the field to read; the value after it is a vault item path. | ||
| # The line may hold no other `--` outside that command, so a literal flag beside it is still caught. | ||
| [[rules.allowlists]] | ||
| regexTarget = "line" | ||
| regexes = ['''^(?:[^-]|-[^-])*\blpass\s+show\s+(?:--?[a-z][a-z-]*(?:=\S*)?\s+)*--password\s+(?:"[^"]*"|'[^']*'|\S+)(?:[^-]|-[^-])*$'''] | ||
|
|
||
| # Values that say where a secret lives rather than hold it: `--auth-key=file:<path>`, docker | ||
| # `--secret id=<name>,src=<path>`, and `--env-secret NAME=<secret-name>` references. | ||
| [[rules.allowlists]] | ||
| regexes = ['''^(?:file:|id=|env=)''', '''^[A-Z][A-Z0-9_]*=[a-z0-9]+(?:-[a-z0-9]+)*$'''] | ||
|
|
||
| # The default curl-auth-user rule flags `curl -u "$USER:"`. A value made only of shell variables, such as | ||
| # `$USER:` or `${USER}:${PASS}`, names where the credential comes from; a literal password after a variable is | ||
| # still caught. | ||
| [[allowlists]] | ||
| targetRules = ["curl-auth-user"] | ||
| regexes = ['''^["']?\$\{?[A-Za-z_][A-Za-z0-9_]*\}?:(?:\$\{?[A-Za-z_][A-Za-z0-9_]*\}?)?["']?$'''] | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gitleaks uses capture group 0 (the entire
--flag=valuematch) whensecretGroupis unset, and an allowlist withoutregexTargettests that extracted secret. Consequently, the value-anchored allowlists below can never match: intended exemptions such as--auth-key=file:/tmp/abcdefghijklmnopand--secret id=my-build-secret-sourceexceed the entropy threshold and fail both pre-commit and CI. The entropy check likewise measures the flag plus value rather than the credential. Restructure the alternatives around one capture group and setsecretGroup, or target the full match explicitly.Useful? React with 馃憤聽/ 馃憥.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not reproduced with gitleaks 8.30.1. When
secretGroupis unset and the regex has capture groups, gitleaks uses the first group that matched as the secret, not group 0. Each of the three value alternatives here is a capture group.Checked with this branch's
.gitleaks.toml:--auth-key=file:/run/secrets/service-token,--auth-key=file:/tmp/abcdefghijklmnop,--secret id=my-build-secret-source,src=/tmp/abcdefghijklmnopand--env-secret API_TOKEN=my-secret-name-for-buildare not reported. With this allowlist removed, all four are reported, and the reported secret starts atfile:,id=orAPI_TOKEN=, without the flag. A literal such as--password=<random 24 characters>is still reported with the allowlist in place.