Skip to content

Security: mick-gsk/drift

Security

SECURITY.md

Security Policy

Supported Versions

Version Supported
2.49.x
2.48.x
2.47.x
2.46.x
2.45.x
2.44.x
2.43.x
2.42.x
2.41.x
2.40.x
2.39.x
2.38.x
2.35.x
2.34.x
2.33.x
2.32.x
2.31.x
2.30.x
2.29.x
2.28.x
2.27.x
2.26.x
2.25.x
2.24.x
2.23.x
2.22.x
2.21.x
2.20.x
2.19.x
2.18.x
2.17.x
2.16.x
2.15.x
2.14.x
2.13.x
2.12.x
2.11.x
2.10.x
2.9.x
2.7.x
2.6.x
2.4.x
< 2.4

Current release line: v2.49.0.

Reporting a Vulnerability

If you discover a security vulnerability in drift, please do not open a public issue.

Instead, report it privately:

  1. Email: Send a detailed description to the maintainer via the contact listed on the GitHub profile.
  2. GitHub Security Advisory: Use the private vulnerability reporting feature.

Please include:

  • A description of the vulnerability and its potential impact.
  • Steps to reproduce or a proof-of-concept.
  • The drift version affected.

You will receive an acknowledgment within 72 hours and a resolution timeline within 7 days.

Scope

drift is a static analysis tool that:

  • Parses Python and TypeScript source code using AST modules and tree-sitter.
  • Invokes git log via subprocess to read commit history.
  • Reads file system contents of the target repository.

Security Boundary Controls

The following controls are implemented in runtime code and treated as part of the security baseline:

  • Path normalization: repository roots are resolved to absolute paths before file traversal.
  • Symlink policy: symlink files are skipped during file discovery.
  • File size guardrail: files larger than 5 MB are skipped.
  • Git subprocess hardening: git commands are invoked with argument lists (no shell interpolation) and fixed command templates.
  • Git timeout guardrail: git history parsing uses a 60 second subprocess timeout.
  • Safe config parsing: configuration is loaded via yaml.safe_load and validated via strict Pydantic schemas (extra="forbid").
  • Non-executing parsing: source files are parsed via ast.parse or tree-sitter; no analyzed source is executed.

Known Attack Surface

Vector Description Mitigation
Git history parsing drift calls git log via subprocess on the target repo. A crafted .git directory could theoretically influence output. drift passes only hardcoded git log format strings — no user-controlled arguments are interpolated into shell commands.
Arbitrary file read drift reads all .py and .ts files in the target directory tree. No file contents are executed. Parsing is done via Python ast.parse() which does not execute code.
CI environment When run in CI (e.g., GitHub Actions), drift has access to the runner's environment. drift does not read environment variables, secrets, or network resources beyond the local repository.

Residual Risks and Operational Guidance

Even with the controls above, drift may still consume significant resources on very large or adversarial repositories (for example, huge numbers of small files or expensive parser workloads).

Recommended operational posture:

  1. Run drift in isolated CI runners for untrusted repositories.
  2. Use report-only mode first (fail-on: none) before enforcing hard gates.
  3. Keep clone depth and analysis scope aligned with your risk and runtime budget.
  4. Treat optional dependency sets as an expanded supply-chain surface and pin versions in controlled environments.

Trust Model

drift operates under the same trust level as local shell access:

  • It reads files and Git history from the local file system only.
  • It does not make network requests, access remote APIs, or exfiltrate data.
  • It does not execute any analyzed source code.
  • The user invoking drift must already have read access to the target repository.

Consequently, an attacker who can modify files in the target repository already has equal or greater privileges than drift itself. Findings that require prior write access to the repository are not considered vulnerabilities in drift.

Out of Scope

The following are explicitly not security issues in drift:

Category Example Reason
Privileged file-system crafting Malicious .py files causing misleading findings Attacker already has write access — same trust boundary.
Resource exhaustion on huge repos OOM or long runtime on 100k+ file repositories Operational concern, not a vulnerability. Use --max-files and resource limits.
Static-analysis false positives A signal reports a finding that is not a real problem Signal-quality issue, not a security issue. Report via false-positive template.
Secret-scanning baseline entries .secrets.baseline contains hashed fixture secrets Intentional test fixtures; hashes are not reversible.
Git history tampering Rewritten Git history producing different drift results drift trusts git log output; history integrity is the repository owner's responsibility.

Security Regression Evidence

Security-relevant behavior is covered by dedicated tests, including:

  • tests/test_git_history_safety.py (subprocess argument safety and path handling)
  • tests/test_file_discovery.py (symlink skipping, exclude handling, oversize file handling)
  • tests/test_cache_resilience.py (corrupted cache and concurrent access resilience)

Security Scanning

This repository uses detect-secrets with a tracked baseline (.secrets.baseline) and exclusion reference (.detect-secrets.cfg).

GitHub-native security workflows are enabled:

  • CodeQL (.github/workflows/codeql.yml): scans Python code on pushes and pull requests targeting main, plus a weekly scheduled run.

  • Dependency Review (.github/workflows/dependency-review.yml): reviews dependency changes on pull requests and fails on high severity and above.

  • CI enforcement: .github/workflows/security-hygiene.yml runs blocking gates for detect-private-key, detect-secrets, and actionlint via pre-commit.

  • Advisory (non-blocking) checks in the same workflow: shellcheck and zizmor.

  • Local enforcement: run the same pre-commit hooks before pushing changes.

Local commands:

pip install pre-commit==4.2.0 detect-secrets==1.5.0
pre-commit run --all-files detect-private-key
pre-commit run --all-files detect-secrets
pre-commit run --all-files shellcheck
pre-commit run --all-files actionlint
pre-commit run --all-files zizmor

Baseline refresh flow (after intentional fixture/doc updates):

detect-secrets scan --all-files --baseline .secrets.baseline
detect-secrets audit .secrets.baseline

Disclosure Policy

We follow coordinated disclosure. Vulnerabilities will be patched before public disclosure. Credit will be given to reporters unless they prefer anonymity.

There aren’t any published security advisories