From 9f345e8c2ecb03620ad96e5ef548e63fe86139f2 Mon Sep 17 00:00:00 2001 From: duriantaco Date: Wed, 27 May 2026 23:14:04 +0800 Subject: [PATCH] fix(scanner): clean dead-code warnings Remove unused pickle scan symbols and make eval config AST scanning explicit while preserving assignment coverage. --- ceres/analyzers/eval/safety_config.py | 15 ++++----------- ceres/analyzers/model/pickle_static.py | 10 +++++----- tests/test_correctness_regressions.py | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/ceres/analyzers/eval/safety_config.py b/ceres/analyzers/eval/safety_config.py index bbb1e92..e3fdc94 100644 --- a/ceres/analyzers/eval/safety_config.py +++ b/ceres/analyzers/eval/safety_config.py @@ -134,28 +134,21 @@ def _scan_python_file(path: Path, ctx: AnalyzerContext) -> list[Finding]: rel = ctx.rel(path) findings: list[Finding] = [] - class Visitor(ast.NodeVisitor): - def visit_Assign(self, node: ast.Assign) -> None: + for node in ast.walk(tree): + if isinstance(node, ast.Assign): for target in node.targets: key = _target_name(target) if key: _check_key_value(key, _literal(node.value), rel, [key], node.lineno, findings, ctx) - self.generic_visit(node) - - def visit_AnnAssign(self, node: ast.AnnAssign) -> None: + elif isinstance(node, ast.AnnAssign): key = _target_name(node.target) if key: _check_key_value(key, _literal(node.value), rel, [key], node.lineno, findings, ctx) - self.generic_visit(node) - - def visit_Dict(self, node: ast.Dict) -> None: + elif isinstance(node, ast.Dict): for key_node, value_node in zip(node.keys, node.values): key = _literal(key_node) if isinstance(key, str): _check_key_value(key, _literal(value_node), rel, [key], getattr(node, "lineno", None), findings, ctx) - self.generic_visit(node) - - Visitor().visit(tree) return findings diff --git a/ceres/analyzers/model/pickle_static.py b/ceres/analyzers/model/pickle_static.py index 64af5c3..4352fbc 100644 --- a/ceres/analyzers/model/pickle_static.py +++ b/ceres/analyzers/model/pickle_static.py @@ -1,8 +1,8 @@ from __future__ import annotations +import pickle import pickletools import zipfile -import pickle from dataclasses import dataclass from pathlib import Path @@ -62,7 +62,7 @@ def scan_pickle_bytes(data: bytes) -> PickleScanResult: count = 0 truncated = False try: - for op, arg, _pos in pickletools.genops(data[:_MAX_BYTES]): + for op, arg, _ in pickletools.genops(data[:_MAX_BYTES]): count += 1 if count > _MAX_OPS: truncated = True @@ -76,17 +76,17 @@ def scan_pickle_bytes(data: bytes) -> PickleScanResult: continue ref = arg if isinstance(arg, str) else " ".join(arg) if arg else "" ref_norm = ref.replace(" ", ".") - if _matches_any(ref_norm, _SUSPICIOUS_GLOBALS): + if _matches_any(ref_norm): suspicious.append(ref_norm) if name in {"INST", "OBJ"}: - if isinstance(arg, str) and _matches_any(arg.replace(" ", "."), _SUSPICIOUS_GLOBALS): + if isinstance(arg, str) and _matches_any(arg.replace(" ", ".")): suspicious.append(arg) except Exception as e: # noqa: BLE001 return PickleScanResult(suspicious, has_reduce, count, truncated, error=str(e)) return PickleScanResult(suspicious, has_reduce, count, truncated) -def _matches_any(ref: str, fragments: set[str]) -> bool: +def _matches_any(ref: str) -> bool: if ref in _SUSPICIOUS_EXACT: return True return any(ref.startswith(prefix) for prefix in _SUSPICIOUS_PREFIXES) diff --git a/tests/test_correctness_regressions.py b/tests/test_correctness_regressions.py index 3d3036c..eefd3d8 100644 --- a/tests/test_correctness_regressions.py +++ b/tests/test_correctness_regressions.py @@ -139,3 +139,20 @@ def test_root_temperature_without_ai_context_is_not_flagged(tmp_path): cfg.write_text("temperature: 1.4\n") findings, _suppressed, _counts, _passed, _inv = run_scan(repo, Policy(), None, None) assert "ceres.eval.generation_temperature_high" in _rule_ids(findings) + + +def test_eval_safety_python_assignments_are_scanned(tmp_path): + repo = tmp_path / "repo" + src = repo / "src" + src.mkdir(parents=True) + (src / "eval_config.py").write_text( + "skip_safety_eval = True\n" + "enable_content_filter: bool = False\n" + "generation_config = {'temperature': 1.4}\n" + ) + + findings, _suppressed, _counts, _passed, _inv = run_scan(repo, Policy(), None, None) + rule_ids = _rule_ids(findings) + assert "ceres.eval.safety_eval_disabled" in rule_ids + assert "ceres.eval.safety_filter_disabled" in rule_ids + assert "ceres.eval.generation_temperature_high" in rule_ids