Skip to content

carabiner v0.2.0

Choose a tag to compare

@MaXiMo000 MaXiMo000 released this 23 Aug 06:57
· 16 commits to main since this release
pip install carabiner-sec

Two 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.

  • JEN001 Groovy 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.
  • JEN002 a literal credential assigned in a pipeline
  • CIR001 an orb pinned to @volatile, which always resolves to the newest publish
  • CIR002 a pipeline parameter substituted into a run step
  • AZP001 a 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? A dependabot.yml in 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.