Skip to content

feat(security): detect CVE-2024-27318 ONNX nested path traversal bypass#607

Merged
yash2998chhabria merged 15 commits intomainfrom
feat/cve-2024-27318-detection
Mar 4, 2026
Merged

feat(security): detect CVE-2024-27318 ONNX nested path traversal bypass#607
yash2998chhabria merged 15 commits intomainfrom
feat/cve-2024-27318-detection

Conversation

@mldangelo
Copy link
Copy Markdown
Member

@mldangelo mldangelo commented Feb 27, 2026

Summary

  • Detects CVE-2024-27318: ONNX nested path traversal bypass (e.g. subdir/../../etc/passwd) that evades the lstrip-based CVE-2022-25882 fix
  • Fixes logic bug where path traversal check ran AFTER file existence check, causing traversal to non-existent targets to only report "file not found"
  • Properly attributes nested traversal to CVE-2024-27318 and direct traversal to CVE-2022-25882
  • Adds get_cve_2024_27318_explanation() for vulnerability context

Test plan

  • Nested traversal (subdir/../../etc/passwd) detected as CVE-2024-27318
  • Direct traversal (../../etc/passwd) correctly attributed to CVE-2022-25882
  • Non-existent traversal targets flagged as traversal (not just "file not found")
  • Safe external data (weights.bin) not flagged
  • Check details include CWE-22 and CVSS 7.5
  • Full test suite passes (368 passed, ONNX tests skip locally - will run in CI)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Security

    • Added detection for CVE-2024-27318 (nested path traversal) and CVE-2022-25882 in ONNX models, plus detection for CVE-2025-9906 unsafe-deserialization bypass in Keras ZIPs, with CVE-aware details and remediation guidance.
  • Bug Fixes

    • Hardened scanner stack resolution to prevent deserialization bypasses and corrected external-path validation so nonexistent traversal targets are reported correctly.
  • Tests

    • Added comprehensive ONNX and Keras scanner tests covering traversal, unsafe-deserialization, edge cases, and metadata verification.
  • Documentation

    • Updated changelog with the new security entries.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds nested and direct ONNX external-data path traversal detection (CVE-2024-27318, CVE-2022-25882), a Keras ZIP unsafe-deserialization bypass check (CVE-2025-9906), new tests, a containment helper, and changelog updates; also adds a duplicated explanation function in explanations.py.

Changes

Cohort / File(s) Summary
ONNX scanner logic
modelaudit/scanners/onnx_scanner.py
Added _is_contained_in(child: Path, parent: Path) and rewrote _check_external_data() to detect nested vs direct external-data path traversal, emit CVE-aware checks (CVE-2024-27318, CVE-2022-25882) with CVSS/CWE/details/location/why, and handle non-existent external paths via the traversal-aware flow.
Keras ZIP scanner & explanations
modelaudit/scanners/keras_zip_scanner.py, modelaudit/config/explanations.py
Added CVE-2025-9906 unsafe-deserialization bypass detection in Keras ZIP scans (_check_unsafe_deserialization_bypass, _collect_string_tokens) and a new get_cve_2025_9906_explanation function (note: duplicated definition introduced).
Pickle scanner hardening
modelaudit/scanners/...
Changelog notes a hardening to the pickle scanner stack resolution to properly track STACK_GLOBAL and memoized REDUCE targets (reported in CHANGELOG.md).
Tests (ONNX & Keras)
tests/scanners/test_onnx_scanner.py, tests/scanners/test_keras_zip_scanner.py
Added comprehensive tests: ONNX nested/direct traversal scenarios and edge cases; Keras ZIP tests covering enable_unsafe_deserialization detection, nested config tokens, false-positive avoidance, and CVE metadata validation.
Test config
tests/conftest.py
Permitted new test files (test_onnx_scanner.py, test_keras_zip_scanner.py) in pytest setup gating to enable running the added tests.
Changelog
CHANGELOG.md
Updated Unreleased: Added entries for ONNX nested traversal (CVE-2024-27318), Keras config bypass detection (CVE-2025-9906), and a pickle scanner hardening fix; clarified attribution and previous logic bug behavior.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibble paths and sniff each dot-dot clue,

I hop through zip and model, checking through and through,
I call the CVEs when sneaky strings align,
I drum my paws to guard your model-line,
A carrot, a hop — safe models, that’s the view 🥕🔍

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding detection for CVE-2024-27318 ONNX nested path traversal, which aligns with the main objective and the substantial changes to the ONNX scanner.
Docstring Coverage ✅ Passed Docstring coverage is 92.31% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/cve-2024-27318-detection

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@modelaudit/config/explanations.py`:
- Around line 673-702: The get_cve_2024_27318_explanation function is dead
code—defined but never used—so either delete it or make the scanner use it for
consistent explanations; to fix, remove get_cve_2024_27318_explanation from
modelaudit/config/explanations.py if you want to clean up unused code, or modify
the ONNX scanner (the _check_external_data method in onnx_scanner.py) to import
and call get_cve_2024_27318_explanation(vulnerability_type) instead of the
current hardcoded inline descriptions, ensuring the function name and the
vulnerability_type keys ("nested_traversal", "path_traversal", "onnx_version")
match the scanner’s reported vulnerability types.

In `@modelaudit/scanners/onnx_scanner.py`:
- Line 273: The current containment check using
str(external_path).startswith(str(model_dir)) (assigning escapes_model_dir) is
brittle; update it to resolve paths and use a robust containment test such as:
resolve both external_path and model_dir to absolute paths and then use
Path.is_relative_to (or fallback to comparing os.path.commonpath) to determine
containment. Replace the startswith-based assignment for escapes_model_dir with
a resolved-path check using external_path and model_dir (e.g.,
Path(external_path).resolve().is_relative_to(Path(model_dir).resolve()) or the
commonpath fallback) so paths like /foo/barbaz are not misclassified as inside
/foo/bar.

ℹ️ Review info

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between af4ab28 and f641791.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • modelaudit/config/explanations.py
  • modelaudit/scanners/onnx_scanner.py
  • tests/conftest.py
  • tests/scanners/test_onnx_scanner.py

Comment thread modelaudit/config/explanations.py
Comment thread modelaudit/scanners/onnx_scanner.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@modelaudit/scanners/onnx_scanner.py`:
- Around line 281-285: The raw substring check has_traversal_raw = ".." in
location produces false positives; instead detect actual path-segment traversal
by splitting the path into segments and checking for any segment equal to ".."
(e.g., compute has_traversal_raw = any(part == ".." for part in
Path(location).parts) using pathlib.Path or PurePath), then proceed with the
existing escapes_model_dir check via _is_contained_in(external_path, model_dir);
update imports if needed and replace the substring-based logic in the block
containing has_traversal_raw, _is_contained_in, location, external_path, and
model_dir.

ℹ️ Review info

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f641791 and 7696d69.

📒 Files selected for processing (1)
  • modelaudit/scanners/onnx_scanner.py

Comment thread modelaudit/scanners/onnx_scanner.py Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@modelaudit/scanners/onnx_scanner.py`:
- Around line 281-336: The scanner currently flags any location containing '..'
(has_traversal_raw) even when the resolved external_path remains inside
model_dir, causing false positives and CVE misattribution; change the logic to
only report a traversal CVE when escapes_model_dir is true (i.e., external_path
is actually outside model_dir), keep has_traversal_raw for diagnostics only, and
refine the direct-vs-nested classification by normalizing the location (strip
leading './' and use path.parts) to detect whether the first path component is
'..' (direct traversal) versus '..' appearing later (nested traversal); update
the block around variables
has_traversal_raw/escapes_model_dir/external_path/model_dir and the
result.add_check calls (including tensor.name) accordingly and add a regression
test case asserting that 'subdir/../weights.bin' does not produce a critical
traversal finding.

ℹ️ Review info

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7696d69 and 581761d.

📒 Files selected for processing (1)
  • modelaudit/scanners/onnx_scanner.py

Comment thread modelaudit/scanners/onnx_scanner.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/scanners/test_onnx_scanner.py`:
- Around line 180-193: Add a short clarifying comment in the
test_normalized_in_dir_path_with_dotdot_no_traversal_flag function explaining
the setup: that weights.bin is created under tmp_path but create_onnx_model is
called with external=True and external_path="subdir/../weights.bin" plus
missing_external=True to simulate an external reference that resolves inside the
model directory; mention why both creating the file and using
missing_external=True are used (to ensure the scanner sees an external reference
while the actual file exists in-dir) so future maintainers understand the intent
around OnnxScanner().scan and create_onnx_model parameters.

ℹ️ Review info

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 581761d and 330a605.

📒 Files selected for processing (2)
  • modelaudit/scanners/onnx_scanner.py
  • tests/scanners/test_onnx_scanner.py

Comment thread tests/scanners/test_onnx_scanner.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@modelaudit/scanners/keras_zip_scanner.py`:
- Around line 267-280: The current broad token-based detection (using
_collect_string_tokens, has_enable_unsafe and has_keras_config_context) can
false-positive across unrelated entries; replace it with a scoped recursive
check (e.g. implement a helper like _has_unsafe_deserialization_reference) that
walks the model_config structure (dicts/lists), inspects string values within
the same object entry, and returns True only when it finds either a
fully-qualified reference ("keras.config.enable_unsafe_deserialization" or
"keras.src.config.enable_unsafe_deserialization") or a combination in the same
dict of "enable_unsafe_deserialization" together with "keras.config" /
"keras.src.config"; then call that helper on model_config instead of the current
token-wide any(...) logic to ensure matches are correlated to the same object.

In `@tests/scanners/test_keras_zip_scanner.py`:
- Around line 425-431: The helper _make_keras_zip has an untyped tmp_path
parameter; add a type hint (use pathlib.Path) to tmp_path (e.g., tmp_path:
pathlib.Path or Path) and ensure Path is imported where tests live so the
signature becomes def _make_keras_zip(self, config_str: str, tmp_path: Path) ->
str: to satisfy repo typing rules while leaving behavior unchanged.

ℹ️ Review info

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 330a605 and 38d848c.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • modelaudit/config/explanations.py
  • modelaudit/scanners/keras_zip_scanner.py
  • tests/conftest.py
  • tests/scanners/test_keras_zip_scanner.py
  • tests/scanners/test_onnx_scanner.py

Comment thread modelaudit/scanners/keras_zip_scanner.py Outdated
Comment thread tests/scanners/test_keras_zip_scanner.py Outdated
@mldangelo mldangelo closed this Feb 28, 2026
@mldangelo mldangelo reopened this Feb 28, 2026
@yash2998chhabria yash2998chhabria force-pushed the feat/cve-2024-27318-detection branch from 7115d66 to 7f02fc8 Compare March 4, 2026 20:00
mldangelo and others added 14 commits March 4, 2026 14:47
CVE-2024-27318 bypasses the CVE-2022-25882 fix (which used lstrip) via
nested path traversal like "subdir/../../etc/passwd" that starts with
a legitimate directory name.

- Check raw location for ".." BEFORE file existence to catch traversal
  even for non-existent targets (fixes logic bug in check ordering)
- Attribute nested traversal to CVE-2024-27318, direct to CVE-2022-25882
- Add get_cve_2024_27318_explanation() with nested_traversal/onnx_version
- Add 5 tests: nested detection, direct attribution, non-existent target,
  safe data, CWE/CVSS details

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace str().startswith() with proper Path.relative_to() to prevent
path containment bypass where /tmp/model_evil would incorrectly match
/tmp/model via string prefix comparison.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace substring check with segment splitting to avoid false positives
on legitimate filenames like "..hidden" or "file..backup".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ion config bypass

config.json in .keras archives can reference enable_unsafe_deserialization
to disable safe_mode from within the loading process, then load malicious
Lambda layers. Adds raw string scanning of config.json content.

- Add _check_unsafe_deserialization_bypass() to keras_zip_scanner
- Flag enable_unsafe_deserialization in config as CRITICAL
- Add explanation function for CVE-2025-9906
- 4 new tests (detection, nested value, no false positive, attribution)

Co-Authored-By: Claude <noreply@anthropic.com>
Replace `not c.passed` with `c.status == CheckStatus.FAILED` in
test_onnx_scanner.py (two occurrences) and import CheckStatus from
modelaudit.scanners.base. The Check model has no `passed` attribute;
status is tracked via the CheckStatus enum.

Co-Authored-By: Claude <noreply@anthropic.com>
The CVE Detection Checklist requires explanation functions in
explanations.py for each CVE. This was missing for CVE-2024-27318.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add traversal_files tracking alongside read-CVE checks so the per-file
  CVE-2025-51480 write-traversal block fires correctly.
- Add Path type annotation to _make_keras_zip tmp_path parameter.
- Apply ruff formatting fixes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add code comment explaining why unsafe deserialization token detection
scans document-wide rather than per-object. This is deliberate: payloads
can split indicator tokens across sibling config keys.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@yash2998chhabria yash2998chhabria force-pushed the feat/cve-2024-27318-detection branch from 2ffc87d to acec47e Compare March 4, 2026 22:52
@yash2998chhabria yash2998chhabria merged commit fe8837c into main Mar 4, 2026
6 checks passed
@yash2998chhabria yash2998chhabria deleted the feat/cve-2024-27318-detection branch March 4, 2026 23:24
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.

2 participants