From cfcfc0ffdea5ac0eb4e7922bba1692f30d95cf62 Mon Sep 17 00:00:00 2001 From: chopratejas Date: Tue, 7 Apr 2026 19:39:00 -0700 Subject: [PATCH] Fix 4 bugs from code review: audit artifacts, unbound var, noisy log, dead code - Remove bandit_result.txt, pip_audit_result.txt, reqs.txt, ruff_result.txt from repo (security risk: bandit output lists exact vuln locations) + gitignore - Fix unbound original_tokens in batch handler except block (crash on first batch request failure) - Downgrade temporary cache debug log from INFO to DEBUG (fires on every streaming request, polluting production logs) - Remove duplicate _extract_anthropic_cache_ttl_metrics from AnthropicHandlerMixin (StreamingMixin version wins via MRO, duplicate was dead code) --- .gitignore | 6 + bandit_result.txt | 544 --------------------------- headroom/proxy/handlers/anthropic.py | 20 +- headroom/proxy/handlers/streaming.py | 3 +- pip_audit_result.txt | 0 reqs.txt | 31 -- ruff_result.txt | 1 - 7 files changed, 10 insertions(+), 595 deletions(-) delete mode 100644 bandit_result.txt delete mode 100644 pip_audit_result.txt delete mode 100644 reqs.txt delete mode 100644 ruff_result.txt diff --git a/.gitignore b/.gitignore index f5113bde4..0066d5014 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,12 @@ scripts/ # Swift SDK (separate repo) swift/ +# Audit/scan outputs (contain security findings — never commit) +bandit_result.txt +pip_audit_result.txt +ruff_result.txt +reqs.txt + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/bandit_result.txt b/bandit_result.txt deleted file mode 100644 index 555ab3b7d..000000000 --- a/bandit_result.txt +++ /dev/null @@ -1,544 +0,0 @@ -Working... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:02 -Run started:2026-04-07 07:00:45.850410+00:00 - -Test results: ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/cache/base.py:323:15 -322 -323 return hashlib.md5(content.encode()).hexdigest()[:12] -324 - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/cache/compression_cache.py:138:15 -137 raw = content -138 return hashlib.md5(raw.encode("utf-8")).hexdigest()[:16] -139 - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/cache/compression_store.py:209:19 -208 # - 96 bits: ~280 trillion entries for 50% collision -209 hash_key = hashlib.md5(original.encode()).hexdigest()[:24] -210 - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/cache/prefix_tracker.py:308:15 -307 key = f"{model}:{system_content}" -308 return hashlib.md5(key.encode()).hexdigest()[:16] -309 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:74:9 -73 -74 ds = load_dataset("hotpotqa/hotpot_qa", "fullwiki", split=split) -75 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:126:9 -125 -126 ds = load_dataset("google-research-datasets/natural_questions", "default", split=split) -127 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:203:9 -202 -203 ds = load_dataset("trivia_qa", subset, split=split) -204 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:274:9 -273 -274 ds = load_dataset("microsoft/ms_marco", "v2.1", split=split) -275 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:342:9 -341 -342 ds = load_dataset("rajpurkar/squad_v2", split=split) -343 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:404:13 -403 try: -404 ds = load_dataset("THUDM/LongBench", task, split="test") -405 except Exception as e: - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:463:9 -462 -463 ds = load_dataset("deepmind/narrativeqa", split=split) -464 - --------------------------------------------------- ->> Issue: [B310:blacklist] Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. - Severity: Medium Confidence: High - CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b310-urllib-urlopen - Location: headroom/evals/datasets.py:543:14 -542 try: -543 raw = urllib.request.urlopen(f"{base_url}/{data_file}").read().decode("utf-8") -544 items = [json.loads(line) for line in raw.strip().split("\n") if line.strip()] - --------------------------------------------------- ->> Issue: [B310:blacklist] Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. - Severity: Medium Confidence: High - CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b310-urllib-urlopen - Location: headroom/evals/datasets.py:551:17 -550 try: -551 gt_raw = urllib.request.urlopen(f"{base_url}/{gt_file}").read().decode("utf-8") -552 for line in gt_raw.strip().split("\n"): - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:627:13 -626 try: -627 ds = load_dataset("ToolBench/ToolBench", category, split="test") -628 except Exception as e: - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:710:13 -709 try: -710 ds = load_dataset("code_search_net", language, split=split) -711 except Exception as e: - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/datasets.py:765:9 -764 -765 ds = load_dataset("openai_humaneval", split="test") -766 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/html_oss_benchmarks.py:158:14 -157 logger.info("Loading Scrapinghub article extraction benchmark...") -158 dataset = load_dataset("allenai/scrapinghub-article-extraction-benchmark") -159 samples = dataset["train"] - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/html_oss_benchmarks.py:290:18 -289 if dataset_name == "squad": -290 dataset = load_dataset("rajpurkar/squad_v2", split="validation") -291 elif dataset_name == "hotpotqa": - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in load_dataset() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/evals/html_oss_benchmarks.py:292:18 -291 elif dataset_name == "hotpotqa": -292 dataset = load_dataset("hotpotqa/hotpot_qa", "fullwiki", split="validation") -293 else: - --------------------------------------------------- ->> Issue: [B310:blacklist] Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. - Severity: Medium Confidence: High - CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b310-urllib-urlopen - Location: headroom/evals/memory/locomo.py:235:4 -234 logger.info(f"Downloading LoCoMo dataset from {LOCOMO_URL}...") -235 urllib.request.urlretrieve(LOCOMO_URL, cache_path) -236 logger.info(f"Downloaded to {cache_path}") - --------------------------------------------------- ->> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory. - Severity: Medium Confidence: Medium - CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html - Location: headroom/evals/memory/runner_v2.py:386:52 -385 # Default to LocalBackend -386 db_path = self._config.db_path or f"/tmp/locomo_v2_{uuid.uuid4().hex[:8]}.db" -387 backend_config = LocalBackendConfig(db_path=db_path) - --------------------------------------------------- ->> Issue: [B108:hardcoded_tmp_directory] Probable insecure usage of temp file/directory. - Severity: Medium Confidence: Medium - CWE: CWE-377 (https://cwe.mitre.org/data/definitions/377.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b108_hardcoded_tmp_directory.html - Location: headroom/evals/memory/runner_v3.py:264:52 -263 else: -264 db_path = self._config.db_path or f"/tmp/locomo_v3_{uuid.uuid4().hex[:8]}.db" -265 self._backend = LocalBackend(LocalBackendConfig(db_path=db_path)) - --------------------------------------------------- ->> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. - Severity: Medium Confidence: Medium - CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html - Location: headroom/memory/adapters/fts5.py:239:20 -238 cursor = conn.execute( -239 f""" -240 SELECT memory_id, content, user_id, session_id, category, -241 bm25(memory_fts) as rank -242 FROM memory_fts -243 WHERE {where_sql} -244 ORDER BY rank -245 LIMIT ? -246 """, -247 params, - --------------------------------------------------- ->> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. - Severity: Medium Confidence: Medium - CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html - Location: headroom/memory/adapters/sqlite.py:334:18 -333 cursor = conn.execute( -334 f"SELECT * FROM memories WHERE id IN ({placeholders})", -335 memory_ids, - --------------------------------------------------- ->> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. - Severity: Medium Confidence: Medium - CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html - Location: headroom/memory/adapters/sqlite.py:373:18 -372 cursor = conn.execute( -373 f"DELETE FROM memories WHERE id IN ({placeholders})", -374 memory_ids, - --------------------------------------------------- ->> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. - Severity: Medium Confidence: Medium - CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html - Location: headroom/memory/adapters/sqlite.py:745:18 -744 cursor = conn.execute( -745 f"DELETE FROM memories WHERE {where_clause}", -746 params, - --------------------------------------------------- ->> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. - Severity: Medium Confidence: Medium - CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html - Location: headroom/memory/adapters/sqlite_graph.py:372:22 -371 cursor = conn.execute( -372 f"SELECT * FROM relationships WHERE {where_clause}", -373 params, - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/memory/backends/direct_mem0.py:278:24 -277 "created_at": _utcnow().isoformat(), -278 "hash": hashlib.md5(fact.encode()).hexdigest(), -279 **(metadata or {}), - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/models/ml_models.py:151:24 -150 -151 model = AutoModel.from_pretrained(model_name) -152 processor = AutoProcessor.from_pretrained(model_name) - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/models/ml_models.py:152:28 -151 model = AutoModel.from_pretrained(model_name) -152 processor = AutoProcessor.from_pretrained(model_name) -153 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/models/ml_models.py:239:28 -238 -239 tokenizer = AutoTokenizer.from_pretrained(model_path) -240 model = AutoModelForSequenceClassification.from_pretrained(model_path) - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/models/ml_models.py:240:24 -239 tokenizer = AutoTokenizer.from_pretrained(model_path) -240 model = AutoModelForSequenceClassification.from_pretrained(model_path) -241 - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/parser.py:36:11 -35 """Compute hash of text, truncated to 16 chars.""" -36 return hashlib.md5(text.encode()).hexdigest()[:16] -37 - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/prediction/feature_extractor.py:2141:31 -2140 # Prompt hash -2141 features.prompt_hash = hashlib.md5(text.encode()).hexdigest()[:16] -2142 features.prompt_signature = self._compute_signature(text) - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/prediction/feature_extractor.py:2327:20 -2326 # Check cache -2327 cache_key = hashlib.md5(f"{prompt}:{model}:{system_prompt}".encode()).hexdigest() -2328 - --------------------------------------------------- ->> Issue: [B310:blacklist] Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. - Severity: Medium Confidence: High - CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b310-urllib-urlopen - Location: headroom/rtk/installer.py:79:17 -78 try: -79 with urlopen(url, timeout=30) as response: -80 data = response.read() - --------------------------------------------------- ->> Issue: [B310:blacklist] Audit url open for permitted schemes. Allowing use of file:/ or custom schemes is often unexpected. - Severity: Medium Confidence: High - CWE: CWE-22 (https://cwe.mitre.org/data/definitions/22.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_calls.html#b310-urllib-urlopen - Location: headroom/rtk/installer.py:86:21 -85 ctx.verify_mode = ssl.CERT_NONE -86 with urlopen(url, timeout=30, context=ctx) as response: -87 data = response.read() - --------------------------------------------------- ->> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction. - Severity: Medium Confidence: Medium - CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html - Location: headroom/storage/sqlite.py:233:16 -232 cursor.execute( -233 f""" -234 SELECT -235 COUNT(*) as total_requests, -236 SUM(tokens_input_before) as total_tokens_before, -237 SUM(tokens_input_after) as total_tokens_after, -238 SUM(tokens_input_before - tokens_input_after) as total_tokens_saved, -239 AVG(tokens_input_before - tokens_input_after) as avg_tokens_saved, -240 AVG(cache_alignment_score) as avg_cache_alignment, -241 SUM(CASE WHEN mode = 'audit' THEN 1 ELSE 0 END) as audit_count, -242 SUM(CASE WHEN mode = 'optimize' THEN 1 ELSE 0 END) as optimize_count -243 FROM requests -244 {where_clause} -245 """, -246 params, - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/tokenizers/huggingface.py:119:15 -118 try: -119 return AutoTokenizer.from_pretrained( -120 tokenizer_name, -121 trust_remote_code=True, -122 ) -123 except Exception as e: - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/transforms/anchor_selector.py:337:11 -336 content = str(item) -337 return hashlib.md5(content.encode()).hexdigest()[:16] -338 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/transforms/kompress_compressor.py:82:27 -81 super().__init__() -82 self.encoder = AutoModel.from_pretrained(model_name, attn_implementation="eager") -83 hidden_size = self.encoder.config.hidden_size # 768 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in hf_hub_download() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/transforms/kompress_compressor.py:180:20 -179 logger.info("Downloading Kompress ONNX model from %s ...", HF_MODEL_ID) -180 onnx_path = hf_hub_download(HF_MODEL_ID, "onnx/kompress-int8.onnx") -181 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/transforms/kompress_compressor.py:184:20 -183 model = _OnnxModel(session) -184 tokenizer = AutoTokenizer.from_pretrained("answerdotai/ModernBERT-base") -185 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in hf_hub_download() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/transforms/kompress_compressor.py:207:23 -206 logger.info("Downloading Kompress PyTorch model from %s ...", HF_MODEL_ID) -207 weights_path = hf_hub_download(HF_MODEL_ID, "model.safetensors") -208 - --------------------------------------------------- ->> Issue: [B615:huggingface_unsafe_download] Unsafe Hugging Face Hub download without revision pinning in from_pretrained() - Severity: Medium Confidence: High - CWE: CWE-494 (https://cwe.mitre.org/data/definitions/494.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b615_huggingface_unsafe_download.html - Location: headroom/transforms/kompress_compressor.py:228:20 -227 -228 tokenizer = AutoTokenizer.from_pretrained("answerdotai/ModernBERT-base") -229 - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/transforms/smart_crusher.py:1765:28 -1764 content = str(item) -1765 item_hash = hashlib.md5(content.encode()).hexdigest()[:16] -1766 except (TypeError, ValueError, RecursionError) as e: - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/transforms/smart_crusher.py:1835:36 -1834 content = str(item) -1835 seen_hashes.add(hashlib.md5(content.encode()).hexdigest()[:16]) -1836 except (TypeError, ValueError, RecursionError): - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/transforms/smart_crusher.py:1868:32 -1867 content = str(item) -1868 item_hash = hashlib.md5(content.encode()).hexdigest()[:16] -1869 except (TypeError, ValueError, RecursionError): - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/transforms/smart_crusher.py:3339:27 -3338 msg = str(item.get(message_field, ""))[:50] -3339 msg_hash = hashlib.md5(msg.encode()).hexdigest()[:8] -3340 if msg_hash not in clusters: - --------------------------------------------------- ->> Issue: [B324:hashlib] Use of weak MD5 hash for security. Consider usedforsecurity=False - Severity: High Confidence: High - CWE: CWE-327 (https://cwe.mitre.org/data/definitions/327.html) - More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b324_hashlib.html - Location: headroom/utils.py:43:11 -42 data = data.encode("utf-8") -43 return hashlib.md5(data).hexdigest()[:length] -44 - --------------------------------------------------- - -Code scanned: - Total lines of code: 82757 - Total lines skipped (#nosec): 0 - Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 0 - -Run metrics: - Total issues (by severity): - Undefined: 0 - Low: 105 - Medium: 38 - High: 14 - Total issues (by confidence): - Undefined: 0 - Low: 2 - Medium: 10 - High: 145 -Files skipped (0): diff --git a/headroom/proxy/handlers/anthropic.py b/headroom/proxy/handlers/anthropic.py index 6f32729f7..064a6683a 100644 --- a/headroom/proxy/handlers/anthropic.py +++ b/headroom/proxy/handlers/anthropic.py @@ -40,23 +40,8 @@ class AnthropicHandlerMixin: canonical = str(tool) return (name, canonical) - @staticmethod - def _extract_anthropic_cache_ttl_metrics(usage: dict[str, Any] | None) -> tuple[int, int]: - """Extract observed Anthropic cache-write TTL bucket usage. - - Returns (cache_write_5m_tokens, cache_write_1h_tokens) from provider usage. - These are observational metrics only; they do not imply configured or - remaining TTL. - """ - if not isinstance(usage, dict): - return (0, 0) - cache_creation = usage.get("cache_creation") - if not isinstance(cache_creation, dict): - return (0, 0) - return ( - int(cache_creation.get("ephemeral_5m_input_tokens", 0) or 0), - int(cache_creation.get("ephemeral_1h_input_tokens", 0) or 0), - ) + # _extract_anthropic_cache_ttl_metrics is defined in StreamingMixin + # (which takes precedence via MRO). Do not duplicate here. @classmethod def _sort_tools_deterministically( @@ -1580,6 +1565,7 @@ class AnthropicHandlerMixin: continue # Apply optimization + original_tokens = 0 # Initialize before try to prevent UnboundLocalError try: context_limit = self.anthropic_provider.get_context_limit(model) frozen_message_count = ( diff --git a/headroom/proxy/handlers/streaming.py b/headroom/proxy/handlers/streaming.py index 09da2f20f..193bcda9a 100644 --- a/headroom/proxy/handlers/streaming.py +++ b/headroom/proxy/handlers/streaming.py @@ -173,8 +173,7 @@ class StreamingMixin: ) usage_found["cache_creation_ephemeral_5m_input_tokens"] = cache_write_5m usage_found["cache_creation_ephemeral_1h_input_tokens"] = cache_write_1h - # INFO logging for cache token tracking (temporary for debugging) - logger.info( + logger.debug( f"[CACHE] Anthropic usage: input={usage_found.get('input_tokens')}, " f"cache_read={usage_found.get('cache_read_input_tokens')}, " f"cache_write={usage_found.get('cache_creation_input_tokens')}" diff --git a/pip_audit_result.txt b/pip_audit_result.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/reqs.txt b/reqs.txt deleted file mode 100644 index 73da69b10..000000000 --- a/reqs.txt +++ /dev/null @@ -1,31 +0,0 @@ -bandit==1.9.4 -boolean.py==5.0 -CacheControl==0.14.4 -certifi==2026.2.25 -charset-normalizer==3.4.7 -cyclonedx-python-lib==11.7.0 -defusedxml==0.7.1 -filelock==3.25.2 -idna==3.11 -license-expression==30.4.4 -markdown-it-py==4.0.0 -mdurl==0.1.2 -msgpack==1.1.2 -packageurl-python==0.17.6 -packaging==26.0 -pip-api==0.0.34 -pip-requirements-parser==32.0.1 -pip_audit==2.10.0 -platformdirs==4.9.4 -py-serializable==2.1.0 -Pygments==2.20.0 -pyparsing==3.3.2 -PyYAML==6.0.3 -requests==2.33.1 -rich==14.3.3 -ruff==0.15.9 -sortedcontainers==2.4.0 -stevedore==5.7.0 -tomli==2.4.1 -tomli_w==1.2.0 -urllib3==2.6.3 diff --git a/ruff_result.txt b/ruff_result.txt deleted file mode 100644 index 1f5f344d0..000000000 --- a/ruff_result.txt +++ /dev/null @@ -1 +0,0 @@ -All checks passed!