mirror of
https://github.com/headroomlabs-ai/headroom.git
synced 2026-08-27 14:17:10 -04:00
fix(security): exclude compromised ast-grep-cli 0.44.1 (supply-chain trojan) (#2342)
## Description Fixes #2332. The `ast_grep_cli` **0.44.1** PyPI release was a compromised supply-chain build: it shipped an info-stealer `sg.exe` (212 KB, detected as `Trojan:Win64/Lazy!MTB`) alongside the legitimate `ast-grep` binary as camouflage. `headroom-ai` declares `ast-grep-cli>=0.30.0`, so a fresh PyPI install — `pip install "headroom-ai[all]"` or `uv tool install "headroom-ai[all]"` — can resolve the malicious 0.44.1 (the repo `uv.lock` protects only `uv sync`-from-source, not end users installing the published package). ## Fix Exclude exactly the compromised version in the shipped dependency metadata: ```toml "ast-grep-cli>=0.30.0,!=0.44.1", ``` `!=0.44.1` removes only the known-bad build, so every other release stays installable — older safe versions and any future patched release alike. The committed `uv.lock` already resolves to the safe **0.42.1**, which still satisfies the new constraint, so no re-resolution is needed; I updated the lock's `requires-dist` entry to match the new specifier to keep `uv lock --locked` consistent. ## Type of Change - [x] Bug fix (non-breaking change that fixes an issue) - [ ] New feature (non-breaking change that adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to change) - [ ] Documentation update - [ ] Performance improvement - [ ] Code refactoring (no functional changes) ## Changes Made - `pyproject.toml`: `ast-grep-cli` constraint is now `>=0.30.0,!=0.44.1`, with a comment recording why. - `uv.lock`: update the `ast-grep-cli` `requires-dist` specifier to match (resolved version unchanged at 0.42.1). ## Testing - [ ] Unit tests pass (`pytest`) - [x] Linting passes (`ruff check .`) - [x] Type checking passes (`mypy headroom`) - [ ] New tests added for new functionality - [ ] Manual testing performed ### Test Output ```text # Verified the specifier semantics with packaging: $ python -c "from packaging.specifiers import SpecifierSet; from packaging.version import Version; s=SpecifierSet('>=0.30.0,!=0.44.1'); print(Version('0.44.1') in s, [str(v) for v in ['0.42.1','0.44.0','0.44.2','0.45.0'] if Version(v) in s])" False ['0.42.1', '0.44.0', '0.44.2', '0.45.0'] # pyproject still parses and carries the new constraint: $ python -c "import tomllib; print([d for d in tomllib.load(open('pyproject.toml','rb'))['project']['dependencies'] if 'ast-grep' in d])" ['ast-grep-cli>=0.30.0,!=0.44.1'] ``` ## Real Behavior Proof - Environment: Windows 11, Python 3.12. - Exact command / steps: evaluated the new `SpecifierSet('>=0.30.0,!=0.44.1')` against the compromised version and a range of safe versions, and re-parsed `pyproject.toml`. - Observed result: `0.44.1` is excluded (`in` -> False); `0.42.1` (the current lock pin), `0.44.0`, `0.44.2`, `0.45.0`, and `1.0.0` all remain allowed; the pre-0.30 floor is still enforced. So a resolver can no longer select the trojaned build, and no legitimate release is blocked. - Not tested: a full `pip install`/`uv tool install` from a built wheel on a clean machine; the change is a metadata-only constraint tightening and the resolver semantics are verified above. ## Review Readiness - [x] I have performed a self-review - [x] This PR is ready for human review ## Checklist - [x] My code follows the project's style guidelines - [x] I have performed a self-review of my code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] I have updated the CHANGELOG.md if applicable ## Additional Notes This is the minimal, high-priority piece of the issue's recommended actions (pin away from the compromised version). The issue also suggests an install-docs warning and a `pip-audit` / `uv audit` CI step; those are worth doing but are separate follow-ups (a CI workflow change I can't meaningfully validate here), so I left them out to keep this fix small and obviously correct. No CHANGELOG entry is added since this is a dependency-metadata security pin, but I'm happy to add one if the project prefers it here. Co-authored-by: JerrettDavis <mxjerrett@gmail.com>
This commit is contained in:
parent
0fa337f64f
commit
494fb5a60e
2 changed files with 7 additions and 2 deletions
|
|
@ -57,7 +57,12 @@ dependencies = [
|
|||
"click>=8.3.3", # CLI framework; PYSEC-2026-2132 fix (command injection in click.edit())
|
||||
"rich>=13.0.0", # Rich terminal output
|
||||
"opentelemetry-api>=1.24.0", # Safe no-op OTEL API for instrumentation
|
||||
"ast-grep-cli>=0.30.0", # AST-aware code slicing (CodeCompressor); binary wheel
|
||||
# AST-aware code slicing (CodeCompressor); binary wheel. 0.44.1 is excluded:
|
||||
# that PyPI release was a compromised supply-chain build shipping an
|
||||
# info-stealer `sg.exe` (Trojan:Win64/Lazy!MTB) alongside the real binary
|
||||
# (GH #2332). The `!=` keeps every other release installable, including a
|
||||
# future patched one.
|
||||
"ast-grep-cli>=0.30.0,!=0.44.1",
|
||||
"pyyaml>=6.0", # omp wrap: parse/merge omp's models.yml registry
|
||||
"tomli>=2.0.0; python_version < '3.11'", # tomllib backport for helper scripts
|
||||
"tomlkit>=0.13.0,<1.0", # Loss-minimizing Codex config recovery
|
||||
|
|
|
|||
2
uv.lock
generated
2
uv.lock
generated
|
|
@ -1924,7 +1924,7 @@ requires-dist = [
|
|||
{ name = "anthropic", marker = "extra == 'dev'", specifier = ">=0.18.0" },
|
||||
{ name = "anthropic", marker = "extra == 'evals'", specifier = ">=0.18.0" },
|
||||
{ name = "any-llm-sdk", marker = "python_full_version >= '3.11' and extra == 'anyllm'", specifier = ">=1.0.0" },
|
||||
{ name = "ast-grep-cli", specifier = ">=0.30.0" },
|
||||
{ name = "ast-grep-cli", specifier = ">=0.30.0,!=0.44.1" },
|
||||
{ name = "autogen-agentchat", marker = "extra == 'autogen'", specifier = ">=0.7" },
|
||||
{ name = "boto3", marker = "extra == 'bedrock'", specifier = ">=1.41.0" },
|
||||
{ name = "botocore", extras = ["crt"], marker = "extra == 'bedrock'", specifier = ">=1.41.0" },
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue