Skip to content

fix(ggml): detect embedded ZIP polyglot payloads - #1780

Open
mldangelo-oai wants to merge 7 commits into
mainfrom
fix/ggml-zip-polyglot-coverage
Open

fix(ggml): detect embedded ZIP polyglot payloads#1780
mldangelo-oai wants to merge 7 commits into
mainfrom
fix/ggml-zip-polyglot-coverage

Conversation

@mldangelo-oai

Copy link
Copy Markdown
Contributor

Summary

  • close a clean-scan security bypass affecting all five supported legacy GGML model signatures
  • reuse the existing bounded ZIP preflight, nested pickle analysis, scanner-selection handling, and S908 polyglot reporting
  • add failing-first malicious-pickle/path-traversal regressions plus a benign invalid-ZIP near match

Validation

  • 876 passed: GGUF, Llamafile, and Joblib scanner suites
  • 131 passed: release workflow regression suite
  • 8 passed: targeted new GGML and existing ZIP policy/preflight regressions
  • repository-wide Ruff lint and formatting checks pass
  • changed-file mypy passes

The broader scanner run also reaches one unrelated compressed-wrapper cache baseline failure, and full local macOS mypy reports existing out-of-scope platform/type errors; current-main GitHub Python CI and Type Check are green.

Copilot AI review requested due to automatic review settings July 22, 2026 22:11
@mldangelo-oai mldangelo-oai added codex security Security-related issues and vulnerabilities codex-automation labels Jul 22, 2026
@github-actions

github-actions Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Workflow run and artifacts

Performance Benchmarks

Compared 13 shared benchmarks with a regression threshold of 15%.
Status: 0 regressions, 0 improved, 13 stable, 0 new, 0 missing.
Aggregate shared-benchmark median: 4.215s -> 4.149s (-1.5%).

Workload Benchmark Target Size Files Baseline Current Change Status
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_raw] nested_raw 78 B 1 245.5us 258.1us +5.1% stable
rejected-basic-auth-candidates tests/benchmarks/test_scan_benchmarks.py::test_rejected_basic_auth_candidates_scan_linearly - 371.1 KiB 1 2.358s 2.293s -2.8% stable
padded-multi-stream-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_padded_multi_stream_upload multi_stream_padded 4.1 KiB 1 307.4us 304.5us -0.9% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_hex] nested_hex 130 B 1 269.3us 267.6us -0.6% stable
direct-malicious-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_direct_malicious_upload malicious_reduce 52 B 1 193.8us 192.7us -0.6% stable
clean-training-checkpoint tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_clean_training_checkpoint safe_large 278.2 KiB 1 115.19ms 114.62ms -0.5% stable
chunked-upload-stream tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_chunked_upload_stream chunked_stream 278.2 KiB 1 118.25ms 117.67ms -0.5% stable
suspicious-pickle-intake tests/benchmarks/test_scan_benchmarks.py::test_scan_suspicious_pickle_intake suspicious-intake 183.8 KiB 4 148.36ms 148.83ms +0.3% stable
single-checkpoint-preflight tests/benchmarks/test_scan_benchmarks.py::test_scan_single_checkpoint_before_load single_checkpoint.pkl 183.0 KiB 1 105.99ms 106.29ms +0.3% stable
mixed-model-repository tests/benchmarks/test_scan_benchmarks.py::test_scan_release_candidate_repository release-candidate 547.3 KiB 32 643.58ms 644.29ms +0.1% stable
warm-cache-rescan tests/benchmarks/test_scan_benchmarks.py::test_scan_warm_cached_repository_rescan release-candidate 547.3 KiB 32 140.32ms 140.22ms -0.1% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_base64] nested_base64 98 B 1 256.8us 256.6us -0.1% stable
duplicate-heavy-registry tests/benchmarks/test_scan_benchmarks.py::test_scan_duplicate_registry_snapshot registry-snapshot 915.2 KiB 13 583.39ms 583.25ms -0.0% stable

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Closes a security bypass in the GGUF/GGML scanner by ensuring legacy GGML variants also trigger the existing ZIP-polyglot preflight and embedded-archive inspection path, with regressions to prevent recurrence.

Changes:

  • Extend GGUF ZIP polyglot inspection helper to support GGML context labeling and invoke it from GGML scans.
  • Add regression tests covering embedded ZIP polyglots across all legacy GGML magic variants plus an invalid-ZIP near match.
  • Document the security fix in the Unreleased changelog.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
modelaudit/scanners/gguf_scanner.py Parameterizes ZIP polyglot detection labeling and enables it for GGML scans.
tests/scanners/test_gguf_scanner.py Adds malicious polyglot regressions for GGML variants and a benign invalid-ZIP near-match test.
CHANGELOG.md Notes the GGML ZIP/pickle inspection security hardening under Unreleased.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@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: a8ee962c4c

ℹ️ 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/gguf_scanner.py
Comment thread modelaudit/scanners/gguf_scanner.py
Copilot AI review requested due to automatic review settings August 1, 2026 13:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (1)

modelaudit/scanners/gguf_scanner.py:1053

  • _scan_ggml() always reports ZIP polyglot findings as "GGML …" even for other GGML-variant magics (e.g., GGMF/GGJT/GGLA/GGSA). Since result.metadata["magic"] is already set from the real header, the check name/message can become misleading for users triaging alerts on those variant files.
        result.metadata["format"] = "ggml"
        result.metadata["magic"] = magic.decode("ascii", "ignore")
        self._scan_zip_polyglot(result, format_name="GGML")

The main merge joined the new Security section directly onto Bug Fixes, which
fails the documentation formatting check.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 1, 2026 13:31
@mldangelo
mldangelo enabled auto-merge (squash) August 1, 2026 13:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (1)

modelaudit/scanners/gguf_scanner.py:767

  • _scan_zip_polyglot calls zipfile.is_zipfile(...) and then delegates to merge_executable_zip_container_findings(...), which (per modelaudit/scanners/archive_dispatch.py:538-540) calls zipfile.is_zipfile(...) again and performs additional imports before returning. With this PR, the double ZIP probe now runs for GGML as well, which is extra overhead and also increases exposure to pathological ZIP central directories being parsed twice.

Consider refactoring so the ZIP validity/preflight is performed once (ideally via the existing bounded ZIP preflight helpers in zip_scanner.py), and then pass that result into merge_executable_zip_container_findings (or restructure it to accept an already-confirmed ZIP) to avoid redundant parsing and heavy imports on non-ZIP files.

    def _scan_zip_polyglot(self, result: ScanResult, *, format_name: str = "GGUF") -> bool:
        """Inspect ZIP members even when GGUF/GGML header parsing fails."""
        if not zipfile.is_zipfile(self.current_file_path):
            return False

zipfile.is_zipfile only proves an end-of-central-directory signature is present:
it returns True for any file whose trailing 64 KiB contains PK\x05\x06 followed
by 18 bytes. Model tensor data hits that by chance, so a benign file was reported
as CRITICAL S908 with an archive carrying zero members.

This was already reachable on main for GGUF; extending the preflight to the five
legacy GGML magics would have widened it to raw tensor blobs. The existing benign
near-match test cannot catch it because it appends PK\x03\x04, a local-file-header
signature that end-of-central-directory scanning never inspects.

A directory that fails to OPEN is deliberately not treated as benign: it falls
through to the preflight so corrupted or truncated archives still fail closed as
incomplete. Guarding on open-failure too silently skipped that path and broke the
corrupted-directory near-match regressions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 1, 2026 14:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

Suppressed comments (1)

tests/scanners/test_gguf_scanner.py:2973

  • The parameterized GGML magic list includes b"GGSN", but the supported legacy GGML variant magic appears to be b"GGSA" (and this file’s other parametrization uses GGSA). Using an unknown magic here can make the test exercise the wrong code path (or fail early) for the 5th variant.
@pytest.mark.parametrize("magic", [b"GGML", b"GGMF", b"GGJT", b"GGLA", b"GGSN"])

@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: 64e076a723

ℹ️ 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/gguf_scanner.py Outdated
Comment thread modelaudit/scanners/gguf_scanner.py Outdated
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T11:22:45.716237Z 4479188 New commits
🔒 Security Review Completed 2026-08-31T11:24:01.150089Z 4479188 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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: 447918801f

ℹ️ 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/gguf_scanner.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex codex-automation security Security-related issues and vulnerabilities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants