fix(gitleaks): compose the centralized and module configs instead of choosing one - #83
Closed
duckhawk wants to merge 1 commit into
Closed
fix(gitleaks): compose the centralized and module configs instead of choosing one#83duckhawk wants to merge 1 commit into
duckhawk wants to merge 1 commit into
Conversation
…choosing one The action picked one of the two configs and discarded the other. A module shipping .gitleaks.toml with an [extend] section got its config used verbatim, so the centralized gitleaks.base.toml was thrown away — and with it not only the shared allowlists but the three rules that exist nowhere else: werf-secret-key, hashicorp-vault-token and openbao-token. All 17 storage modules ship [extend] useDefault = true, so none of them were scanned for those secrets at all. Verified against a repo holding a live-format Vault token and a 32-hex .werf_secret_key: the base config reports both, a module-style config reports neither. Compose the two instead. Gitleaks already chains configs through [extend] path, so drop the module's own [extend] section, point a fresh one at the base config copied above, and keep the rest of the module config verbatim. The chain becomes gitleaks defaults <- centralized base config <- module config and all three levels stay active at once: a module's [[rules]] still fire, the base rules fire again, and the base allowlists apply. Doing the composition here rather than in the modules means no module has to change: their .gitleaks.toml stays standalone-valid, so a local gitleaks run keeps working. Pointing each module at the base config instead would need a hardcoded path, and the two CI systems place that file differently ($RUNNER_TEMP here, /tmp in modules-gitlab-ci). The base config is referenced by absolute path, since the merged config is written to $RUNNER_TEMP while the base config sits in the checkout. Two behaviour changes fall out. A module config without an [extend] section is now honoured instead of being discarded with a warning, and a module that declares its own [extend] path gets a warning that the centralized config replaces it. Dry-run across all 17 storage modules from common/modules_list.txt at full scan scope: 0 findings everywhere, so re-enabling the base rules turns nobody red. Paired with the same change in modules-gitlab-ci, so GitHub and GitLab do not diverge. Signed-off-by: v.oleynikov <vasily.oleynikov@flant.com>
This was referenced Jul 28, 2026
Merged
Merged
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closing — the CI does not need changing after all.
The choose-one logic here is deliberate: the base config must stay ours, and a module that wants additions is expected to declare
[extend] useDefault = false+path = <base config>and extend it rather than override it. That is exactly what the header ofgitleaks.base.tomldocuments. My diagnosis attributed the outcome to the CI; the outcome is real, but the cause is that all 17 storage modules wrote[extend] useDefault = truewith nopath, i.e. they extend gitleaks' own defaults and never the centralized config. The modules are misconfigured, not the action.Fixing them module-side gives the same result with no CI change. Verified on a repo holding a Vault token, a
.werf_secret_key, anh1:checksum and a docs placeholder:useDefault = true(today)generic-api-keyonlyuseDefault = false+pathhashicorp-vault-token,werf-secret-keyIn the second case
generic-api-keyalso disappears, because the base allowlist suppresses the checksum — so the whole chain is live.The differing base-config locations turned out not to be a blocker either. The GitHub and GitLab module sets are disjoint (no storage module has both
.github/workflowsand.gitlab-ci.yml), so each module only ever needs the path its own CI uses:gitleaks.base.tomlhere,/tmp/gitleaks.base.tomlin modules-gitlab-ci. My claim that no portable value exists was wrong.The
v17branch cut for this change is deleted.Two things worth fixing separately
grep -q "^\[extend\]"cannot enforce the invariant it was written for. It passes for[extend] useDefault = true, which extends gitleaks' defaults, not the centralized config — so it green-lights precisely the misconfiguration it was meant to catch. That is how 17 modules stayed silently unprotected. Worth replacing with a check that the declaredpathactually resolves to the base config, failing loudly otherwise.gitleaks/config/gitleaks.base.tomltells repositories to usepath = "/home/runner/work/_temp/gitleaks.base.toml", while the action has copied the file to./gitleaks.base.tomlsince Fix relative path for gitleaks config override #80. A module following the documentation verbatim getsFTL failed to load extended config.Also worth noting: all 10 GitHub storage modules pin
gitleaks@v6, which predates the centralized config entirely — nogitleaks/config/directory, and it greps for an undottedgitleaks.tomlthat no module ships. They are being moved to@v16separately.