Skip to content

Add cloudpickle to pickle blacklists (B403/B301) - #1462

Open
rayair250-droid wants to merge 2 commits into
PyCQA:mainfrom
rayair250-droid:feat/blacklist-cloudpickle
Open

Add cloudpickle to pickle blacklists (B403/B301)#1462
rayair250-droid wants to merge 2 commits into
PyCQA:mainfrom
rayair250-droid:feat/blacklist-cloudpickle

Conversation

@rayair250-droid

Copy link
Copy Markdown

Closes #1236.

What

cloudpickle extends pickle to serialize arbitrary Python objects (lambdas, closures, dynamically-defined classes). That makes deserializing untrusted cloudpickle data an arbitrary-code-execution risk, exactly like pickle and dill — but bandit's pickle blacklists didn't cover it, while they already cover pickle, cPickle, dill, shelve, jsonpickle and pandas.read_pickle.

Changes

  • B403 (import_pickle): add cloudpickle to the flagged imports.
  • B301 (pickle): add cloudpickle.loads, cloudpickle.load, cloudpickle.Unpickler to the flagged calls.
  • Updated both inline doc tables.
  • Added examples/cloudpickle.py (mirroring examples/dill.py) and a test_cloudpickle functional test.

Verification

$ bandit examples/cloudpickle.py
>> Issue: [B403:blacklist] ... cloudpickle module.   Severity: Low    Confidence: High
>> Issue: [B301:blacklist] Pickle and modules that wrap it ...   Severity: Medium Confidence: High   (x3)

Findings match the dill case exactly — 1 LOW import + 3 MEDIUM calls, all HIGH confidence. test_cloudpickle passes and the full functional suite is green (80 passed) with no regressions.

cloudpickle extends pickle's serialization to arbitrary Python objects, so
deserializing untrusted cloudpickle data is an arbitrary-code-execution risk,
exactly like pickle/dill. bandit already flags pickle, cPickle, dill, shelve,
jsonpickle and pandas.read_pickle but not cloudpickle.

- B403: add 'cloudpickle' to the flagged imports.
- B301: add cloudpickle.loads / cloudpickle.load / cloudpickle.Unpickler to
  the flagged calls.
- Add examples/cloudpickle.py and a functional test mirroring the dill case
  (1 LOW import + 3 MEDIUM calls, all HIGH confidence).

Closes PyCQA#1236.

@noqt noqt left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested this exact head for NOQT. The load and loads additions work across normal, aliased, and from imports, and serialization-only calls stay clear.

One repair is needed: cloudpickle 3.1.2 explicitly says it has no unpickler, and its public exports include Pickler/CloudPickler, load, and loads—not Unpickler. The new syntax-only example never executes, so cloudpickle.Unpickler(...) looks covered even though that API doesn't exist.

Please remove cloudpickle.Unpickler from the B301 table/config/example and reduce the expected MEDIUM/HIGH counts accordingly. The targeted test passes; the broader file is 78/80 on Windows, with the same two unrelated fixture failures on upstream main. git diff --check passes. The remaining load/loads coverage looks good.

cloudpickle 3.1.2 has no Unpickler class -- its public exports are
Pickler/CloudPickler, load, and loads. Drop it from the B301 table,
config list, and example; adjust test_cloudpickle's expected counts
(MEDIUM 3->2, HIGH confidence 4->3) to match.

Addresses review feedback from @noqt on PR PyCQA#1462.
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.

blacklist cloudpickle in pickle blacklist

2 participants