Skip to content

fix(pickle): bound legacy PyTorch control streams - #1619

Merged
mldangelo-oai merged 3 commits into
mainfrom
mdangelo/codex/fix-legacy-pytorch-stream-boundaries
Jun 10, 2026
Merged

mldangelo-oai merged 3 commits into
mainfrom
mdangelo/codex/fix-legacy-pytorch-stream-boundaries

Conversation

@mldangelo-oai

Copy link
Copy Markdown
Contributor

Summary

  • recognize the canonical five-stream legacy PyTorch container prefix
  • scan only executable pickle control streams, excluding opaque tensor storage
  • use the final control-stream boundary for truncation, binary-tail, and CVE coverage accounting
  • retain critical detection in malicious object streams and fail closed on truncated control streams

This fixes the campaign's known_stream_truncated, binary-tail, 64-stream CVE coverage, and storage-byte EXT1/EXT2 false positives as one container-boundary root cause.

Tests

  • pytest tests/scanners/test_pickle_scanner.py -q (154 passed)
  • ruff check modelaudit/scanners/pickle_scanner.py tests/scanners/test_pickle_scanner.py
  • ruff format --check modelaudit/scanners/pickle_scanner.py tests/scanners/test_pickle_scanner.py
  • mypy modelaudit/scanners/pickle_scanner.py tests/scanners/test_pickle_scanner.py
  • git diff --check

@github-actions

github-actions Bot commented Jun 10, 2026 •

Copy link
Copy Markdown
Contributor

Workflow run and artifacts

Performance Benchmarks

Compared 12 shared benchmarks with a regression threshold of 15%.
Status: 0 regressions, 1 improved, 11 stable, 0 new, 0 missing.
Aggregate shared-benchmark median: 1.439s -> 1.429s (-0.7%).

Top improvements:

  • tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_padded_multi_stream_upload -19.8% (660.8us -> 529.9us, padded-multi-stream-upload, multi_stream_padded, size=4.1 KiB, files=1)
Workload Benchmark Target Size Files Baseline Current Change Status
padded-multi-stream-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_padded_multi_stream_upload multi_stream_padded 4.1 KiB 1 660.8us 529.9us -19.8% improved
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_raw] nested_raw 78 B 1 498.3us 472.7us -5.1% stable
mixed-model-repository tests/benchmarks/test_scan_benchmarks.py::test_scan_release_candidate_repository release-candidate 547.3 KiB 32 498.32ms 481.18ms -3.4% stable
warm-cache-rescan tests/benchmarks/test_scan_benchmarks.py::test_scan_warm_cached_repository_rescan release-candidate 547.3 KiB 32 94.62ms 97.61ms +3.2% stable
direct-malicious-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_direct_malicious_upload malicious_reduce 52 B 1 449.1us 435.4us -3.1% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_hex] nested_hex 130 B 1 506.0us 497.1us -1.8% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_base64] nested_base64 98 B 1 478.5us 470.2us -1.7% stable
suspicious-pickle-intake tests/benchmarks/test_scan_benchmarks.py::test_scan_suspicious_pickle_intake suspicious-intake 183.8 KiB 4 142.86ms 144.10ms +0.9% stable
duplicate-heavy-registry tests/benchmarks/test_scan_benchmarks.py::test_scan_duplicate_registry_snapshot registry-snapshot 915.2 KiB 13 399.88ms 402.07ms +0.5% stable
chunked-upload-stream tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_chunked_upload_stream chunked_stream 278.2 KiB 1 115.19ms 115.73ms +0.5% stable
single-checkpoint-preflight tests/benchmarks/test_scan_benchmarks.py::test_scan_single_checkpoint_before_load single_checkpoint.pkl 183.0 KiB 1 73.08ms 73.28ms +0.3% stable
clean-training-checkpoint tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_clean_training_checkpoint safe_large 278.2 KiB 1 112.17ms 112.39ms +0.2% stable

@chatgpt-codex-connector chatgpt-codex-connector Bot 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9affa2894d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread modelaudit/scanners/pickle_scanner.py Outdated
Comment on lines +2216 to +2217
if result.metadata.get("legacy_pytorch_container") is True:
return None

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't skip storage-less legacy tails

When legacy_pytorch_container is true but storage_key_count is 0, a valid legacy PyTorch file has no storage payload after pickle_end; appended ELF/PE/shell bytes should still hit the binary-tail detector. This early return skips that coverage, weakening detections. guidance

Useful? React with 👍 / 👎.

Comment thread modelaudit/scanners/pickle_scanner.py Outdated
Comment on lines +2998 to +3000
if legacy_layout is not None:
result = self._scan_standalone_bytes(payload[: legacy_layout.pickle_end], source=source)
self._annotate_legacy_pytorch_layout(result, legacy_layout)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Don't fail non-seekable legacy storage reads

For non-seekable streams whose legacy control pickles fit in the buffer but tensor storage extends past max_known_stream_read_bytes, this branch still falls through to _add_stream_truncation_check, so the scan is marked inconclusive with non_seekable_stream_truncated even though only raw tensor storage was omitted. That keeps large legacy PyTorch streams failing the coverage check that this path is meant to avoid.

Useful? React with 👍 / 👎.

Comment thread modelaudit/scanners/pickle_scanner.py Outdated
Comment on lines +2987 to +2988
result = self._scan_standalone_bytes(raw_data[: legacy_layout.pickle_end], source=source)
self._annotate_legacy_pytorch_layout(result, legacy_layout, position_offset=start_position)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3 Badge Preserve stream offsets for legacy results

When scan_stream is called on a seekable stream that is already positioned after a wrapper prefix, this fallback replaces the native scan_stream result with scan_bytes, which has no position_offset. Any malicious globals in the legacy control pickles are still detected, but their reported positions/import-reference metadata are shifted back to zero, unlike the normal stream path that reports offsets relative to the actual stream position.

Useful? React with 👍 / 👎.

@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex review

Please review current head 85c9f3d0b64ecc0c7b9f8db54ec6acdcabd4eb22.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@mldangelo-oai
mldangelo-oai enabled auto-merge (squash) June 10, 2026 15:05
@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex review

Re-requesting review for current head 85c9f3d0b64ecc0c7b9f8db54ec6acdcabd4eb22; the prior request completed without a review or reaction.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Nice work!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@mldangelo-oai
mldangelo-oai merged commit e407fb4 into main Jun 10, 2026
29 checks passed
@mldangelo-oai
mldangelo-oai deleted the mdangelo/codex/fix-legacy-pytorch-stream-boundaries branch June 10, 2026 15:27
@github-actions github-actions Bot mentioned this pull request Jun 24, 2026
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