Skip to content

fix(picklescan): diagnose Windows call-graph source-stability failures - #1789

Merged
mldangelo-oai merged 6 commits into
mainfrom
fix/picklescan-windows-nested-source-stability
Aug 25, 2026
Merged

fix(picklescan): diagnose Windows call-graph source-stability failures#1789
mldangelo-oai merged 6 commits into
mainfrom
fix/picklescan-windows-nested-source-stability

Conversation

@mldangelo-oai

@mldangelo-oai mldangelo-oai commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Make the recurring Windows call-graph source-stability failure report its own cause, and accept the explicit fail-closed error in the benign nested-constructor matrix.

Why this changed shape

The original PR only widened the benign nested-constructor test matrix to tolerate INCONCLUSIVE when the shared call-graph source snapshot is judged unstable. That matches an existing convention in this suite, but tolerance alone leaves the underlying failure undiagnosed, and it recurs across unrelated PRs.

New evidence narrows it considerably. The PR lane and the nightly lane disagree, and only one thing differs:

lane shards fail-fast result on the joblib/call-graph tests
test.yml Windows (PR) 1 -x --maxfail=1 fails
nightly.yml Windows 2 none passes on main

The latest main nightly's only failure is an unrelated performance test, so these tests pass there. Linux passes with the same 1-shard configuration. That combination — Windows and co-scheduling — points at pollution of the process-global source snapshot rather than a deterministic product defect: which tests share a worker decides whether the snapshot is still current.

-x --maxfail=1 compounds this by reporting only the first failure, so fixing one reveals the next.

What this adds

_shared_source_snapshot_is_current() returned a bare bool, so every occurrence surfaced as an unactionable source changed during shared call-graph analysis. It now delegates to _shared_source_snapshot_staleness_reason(), which names which of seventeen gates invalidated the snapshot:

snapshot_marked_unstable, import_runtime_untrusted, interpreter_import_runtime_changed, source_search_context_changed, resolution_context_changed, read_fingerprint_changed, resolution_fingerprint_changed, module_source_path_changed, loaded_module_source_path_changed, loaded_package_search_path_changed, loaded_package_resolution_context_missing, loaded_package_resolution_context_changed, namespace_package_became_loaded, namespace_package_resolution_context_changed, loaded_interpreter_module_changed, interpreter_import_runtime_untrusted, loaded_interpreter_reference_changed, report_generation_advanced.

The reason rides in the error details as source_stability_reason. The message text is byte-identical_assert_call_graph_source_stability_error matches it exactly, and every existing assertion still holds:

message: Python call-graph analysis could not complete: source changed during shared call-graph analysis
details: {'analysis': 'python_call_graph_source_stability', 'analysis_incomplete': True,
          'source_stability_reason': 'source_search_context_changed'}

The boolean wrapper delegates to the reason function rather than duplicating the gate list, so the two cannot drift.

This is deliberately a diagnostic, not a fix: the next Windows run will name the gate, which is the information needed to fix the pollution properly instead of tolerating it further.

Validation

  • Three new regressions covering gate naming, wrapper/reason agreement, and message stability. All three fail without the change (TypeError: unexpected keyword argument 'stability_reason').
  • Full modelaudit-picklescan suite green.
  • Ruff, format, and mypy clean across src and tests.

Follow-up

The pollution itself is untouched. Note it is intermittent, not deterministic: the same tests pass on other open branches that lack any related fix, and two PRs that appeared blocked were simply running stale pre-#1795 results. Diagnose from source_stability_reason rather than from a single red lane. Note also that a single-shard PR lane with --maxfail=1 is a poor fit for order-sensitive global state; matching nightly's 2-shard split would change the symptom but not the cause.

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

This PR stabilizes modelaudit-picklescan’s benign nested-constructor scan tests by explicitly modeling and asserting the “fail-closed” behavior when the shared call-graph source snapshot changes mid-analysis (an observed flaky condition in Windows/Python 3.11 nightly runs).

Changes:

  • Expands the benign nested-constructor test matrix to include a forced “hex + source changed” scenario via monkeypatch on _ensure_shared_source_snapshot_stable.
  • Updates assertions to accept only the explicit call-graph source-stability failure mode as INCONCLUSIVE/UNKNOWN, while keeping the clean path as COMPLETE/CLEAN.
  • Keeps the original expectations around “no findings” and presence of the correct nested-payload notice across all benign constructor shapes and encodings.

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

@github-actions

github-actions Bot commented Jul 29, 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.402s -> 4.419s (+0.4%).

Workload Benchmark Target Size Files Baseline Current Change Status
direct-malicious-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_direct_malicious_upload malicious_reduce 52 B 1 224.5us 238.0us +6.0% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_base64] nested_base64 98 B 1 296.6us 309.5us +4.3% stable
mixed-model-repository tests/benchmarks/test_scan_benchmarks.py::test_scan_release_candidate_repository release-candidate 547.3 KiB 32 664.56ms 654.67ms -1.5% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_raw] nested_raw 78 B 1 275.0us 278.2us +1.1% stable
warm-cache-rescan tests/benchmarks/test_scan_benchmarks.py::test_scan_warm_cached_repository_rescan release-candidate 547.3 KiB 32 151.28ms 152.89ms +1.1% stable
rejected-basic-auth-candidates tests/benchmarks/test_scan_benchmarks.py::test_rejected_basic_auth_candidates_scan_linearly - 371.1 KiB 1 2.533s 2.559s +1.0% stable
padded-multi-stream-upload tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_padded_multi_stream_upload multi_stream_padded 4.1 KiB 1 342.6us 345.3us +0.8% stable
chunked-upload-stream tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_chunked_upload_stream chunked_stream 278.2 KiB 1 112.42ms 113.22ms +0.7% stable
suspicious-pickle-intake tests/benchmarks/test_scan_benchmarks.py::test_scan_suspicious_pickle_intake suspicious-intake 183.8 KiB 4 149.55ms 148.66ms -0.6% stable
single-checkpoint-preflight tests/benchmarks/test_scan_benchmarks.py::test_scan_single_checkpoint_before_load single_checkpoint.pkl 183.0 KiB 1 105.60ms 106.01ms +0.4% stable
nested-payload-review tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_nested_payload_review[nested_hex] nested_hex 130 B 1 305.9us 307.1us +0.4% stable
clean-training-checkpoint tests/benchmarks/test_picklescan_benchmarks.py::test_picklescan_clean_training_checkpoint safe_large 278.2 KiB 1 109.41ms 109.71ms +0.3% stable
duplicate-heavy-registry tests/benchmarks/test_scan_benchmarks.py::test_scan_duplicate_registry_snapshot registry-snapshot 915.2 KiB 13 574.65ms 573.33ms -0.2% stable

@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@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: 9c18a9594b

ℹ️ 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 packages/modelaudit-picklescan/tests/test_api.py Outdated
@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 9c18a9594b

View security finding report

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

mldangelo and others added 2 commits August 1, 2026 10:10
_shared_source_snapshot_is_current returned a bare bool, so every stability
failure surfaced as an unactionable 'source changed during shared call-graph
analysis'. It now delegates to _shared_source_snapshot_staleness_reason, which
names which of seventeen gates invalidated the snapshot, and the name rides in
the error details as source_stability_reason.

The message text is deliberately byte-identical: _assert_call_graph_source_
stability_error matches it exactly, so changing it would break assertions across
the suite. The boolean wrapper delegates rather than duplicating the gate list,
so the two cannot drift.

This is a diagnostic, not a fix. The PR lane runs Windows on one shard with
-x --maxfail=1 and fails; nightly runs two shards with no fail-fast and passes
on main, and Linux passes with the same single-shard config. Windows plus
co-scheduling points at pollution of the process-global snapshot rather than a
deterministic defect, and the next Windows run will now name the gate instead of
requiring a local reproduction that is not available.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings August 1, 2026 17:13
@mldangelo mldangelo changed the title test(picklescan): stabilize benign nested constructor checks fix(picklescan): diagnose Windows call-graph source-stability failures Aug 1, 2026

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 5 out of 5 changed files in this pull request and generated no new comments.

Report the exact shared-source gate that invalidates call-graph analysis, keep benign nested-constructor controls deterministic, and safely handle unrelated enrichment exceptions.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 25, 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-25T08:58:48.874811Z 0fe78c3 Manual request
🔒 Security Review Completed 2026-08-25T09:00:19.974928Z 0fe78c3 Manual request
ℹ️ 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.

@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 73d8b7b786

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 73d8b7b786

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex review

@mldangelo-oai

Copy link
Copy Markdown
Contributor Author

@codex security review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 0fe78c3f49

ℹ️ 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".

@chatgpt-codex-connector

Copy link
Copy Markdown

Security review completed. No security issues were found in this pull request.

Reviewed commit: 0fe78c3f49

View security finding report

Only the user who started this review can view the report in Codex.

ℹ️ About Codex security reviews in GitHub

This is an experimental Codex feature. Security reviews are triggered when:

  • You comment "@codex security review"
  • A regular code review gets triggered (for example, "@codex review" or when a PR is opened), and you’re opted in so security review runs alongside code review

Once complete, Codex will leave suggestions, or a comment if no findings are found.

Comment thread packages/modelaudit-picklescan/tests/test_api.py
@mldangelo-oai
mldangelo-oai merged commit 89b5024 into main Aug 25, 2026
34 checks passed
@mldangelo-oai
mldangelo-oai deleted the fix/picklescan-windows-nested-source-stability branch August 25, 2026 09:44
@github-actions github-actions Bot mentioned this pull request Aug 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants