carabiner v0.2.0
pip install carabiner-secTwo new engines, a pre-commit path that is actually fast, and two drills that check controls people assume are on.
--diff — only what the commit touches
The first implementation filtered a full scan afterwards, which saves nothing: the work has already happened, and it measured slower than not using the flag. The engines now avoid the work instead, and secrets uses gitleaks' own --staged mode.
| repository | full tree | --diff |
|---|---|---|
| next.js | 3.92s | 1.80s |
| grafana | 4.25s | 1.97s |
| home-assistant | 6.21s | 1.97s |
kubernetes — native, no wrapper
K8S001 |
hostNetwork / hostPID / hostIPC — the container shares the node's namespaces |
K8S002 |
a privileged container, which is root on the node in all but name |
K8S003 |
allowPrivilegeEscalation, letting a setuid binary regain what the securityContext took away |
K8S004 |
neither runAsNonRoot nor a non-zero runAsUser, so nothing prevents root |
K8S005 |
a literal credential in env — committed in a manifest means committed in your history |
K8S005's first two findings were both wrong. airflow's SECRET_NAME holds the name of a Kubernetes Secret and etcd's INITIAL_CLUSTER_TOKEN is a cluster identifier — both matched on the word alone. It now skips reference-shaped keys (…_NAME, …_PATH, …_ID) and requires the value to carry real entropy: a cluster name scores near 3.2, a credential above 4.
ci — Jenkins, CircleCI and Azure Pipelines
The last host gap. The same vulnerability in three dialects: text somebody else controls reaching a shell without ever becoming data.
JEN001Groovy interpolates${params.X}inside double quotes before the shell ever runs, so the value arrives as code. Single quotes do not, which is why the quote style is the finding.JEN002a literal credential assigned in a pipelineCIR001an orb pinned to@volatile, which always resolves to the newest publishCIR002a pipeline parameter substituted into a run stepAZP001a branch name or commit message substituted into a script step
Deduplicated by resolved path: macOS and Windows are case-insensitive, so Jenkinsfile and jenkinsfile matched as two files and every finding was reported twice.
Jenkinsfiles are Groovy, so that engine is regex-level and shallower than the parsed GitHub and GitLab ones — stated plainly rather than implied.
Two more drills
DRILL017— are Dependabot alerts actually enabled? Adependabot.ymlin the repository does not switch them on.DRILL018— has any SARIF ever arrived? A rejected upload does not fail the job that produced it, so a green pipeline and an empty Security tab look identical from the outside.
57 tests, 218 checks, on Linux and Windows across Python 3.10 and 3.13, plus a Docker build, a wheel install into a clean venv, and carabiner scanning itself — every commit.