Skip to content

fix(B614): suppress false positive on non-literal weights_only; add torch.jit.load regression coverage#1441

Open
DevamShah wants to merge 1 commit into
PyCQA:mainfrom
DevamShah:fix-b614-weights-only-fp
Open

fix(B614): suppress false positive on non-literal weights_only; add torch.jit.load regression coverage#1441
DevamShah wants to merge 1 commit into
PyCQA:mainfrom
DevamShah:fix-b614-weights-only-fp

Conversation

@DevamShah

Copy link
Copy Markdown

Summary

Improves the B614 ("unsafe PyTorch load") check on two fronts, both reducing false positives:

  1. Suppress B614 when weights_only is a non-literal expression (a variable, attribute, subscript, call, etc.). When the value cannot be resolved statically, the check now gives the caller the benefit of the doubt rather than emitting a finding — mirroring the existing behaviour of B615 (huggingface_unsafe_download), which uses the same weights_only / non-literal handling.
  2. Regression coverage that torch.jit.load is not flagged (refs B614 False Positive when using torch.jit.load #1293). torch.jit.load uses TorchScript serialization, not pickle, and is correctly outside B614's matched set (torch.load / torch.serialization.load). The example file now documents this so the behaviour reported in B614 False Positive when using torch.jit.load #1293 is locked in by a test fixture.

Problem / motivation

  • Non-literal weights_only (the substantive fix): today torch.load(f, weights_only=flag) is flagged because the check only treats the literal True / "True" as safe. Real code frequently passes weights_only as a computed value (config flag, function arg), and flagging those is a false positive. B615 already solved the identical problem the same way; this brings B614 into line.
  • torch.jit.load (B614 False Positive when using torch.jit.load #1293): users reported B614 firing on torch.jit.load. On current main its qualified name (torch.jit.load) is not in B614's matched set, so it is already not flagged — this PR adds explicit example coverage so that stays true.

Change

  • bandit/plugins/pytorch_load.py: when the matched call (torch.load / torch.serialization.load) passes weights_only as a non-ast.Constant value, return without a finding. The existing weights_only == True/"True" safe-path and the genuine-unsafe path are unchanged. Uses the same context._context.get("call") keyword-inspection idiom as the merged B615 plugin.
  • examples/pytorch_load.py: adds non-triggering cases — torch.jit.load (with and without map_location) and a non-literal weights_only — alongside the existing genuinely-unsafe calls.

Trade-off (intentional, precedented)

Suppressing on a non-literal weights_only means torch.load(f, weights_only=flag) where flag is False at runtime will not be flagged (a false negative). This matches B615's deliberate "benefit of the doubt" stance for unresolvable arguments — favouring precision over recall for low-confidence static cases. The version-aware behaviour also requested in #1293 (treating weights_only as defaulting to True on torch ≥ 2.6) is intentionally out of scope here and left for a follow-up, since it requires version detection.

Testing / validation

  • tests/functional/test_functional.py::FunctionalTests::test_pytorch_load passes with the unchanged expectation (MEDIUM: 3, HIGH: 3) — the added cases correctly yield zero new findings.
  • Direct run on examples/pytorch_load.py: B614 fires only on the three genuinely-unsafe torch.load calls; it does not fire on torch.jit.load or the non-literal weights_only case.
  • Adjacent functional tests pass; no regressions.

…orch.jit.load regression coverage

B614 only treated literal weights_only=True/"True" as safe, so
torch.load(f, weights_only=flag) with a computed value was a false positive.
Suppress the finding when weights_only is a non-ast.Constant expression, giving
the benefit of the doubt for statically-unresolvable values — mirroring the
existing B615 (huggingface_unsafe_download) behaviour. Adds example coverage that
torch.jit.load (TorchScript, not pickle; outside B614's matched set) is not
flagged, locking in the behaviour reported in PyCQA#1293. The genuine-unsafe path and
the weights_only==True safe path are unchanged.

Refs PyCQA#1293

Signed-off-by: Devam Shah <devamshah91@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant