Skip to content

fix: harden Metalink parsing and add plugin CI - #1

Merged
mpiton merged 9 commits into
mainfrom
feat/lot-1
Jul 16, 2026
Merged

fix: harden Metalink parsing and add plugin CI#1
mpiton merged 9 commits into
mainfrom
feat/lot-1

Conversation

@mpiton

@mpiton mpiton commented Jul 15, 2026

Copy link
Copy Markdown
Owner

Summary

  • upgrade quick-xml to 0.41
  • enforce explicit Metalink size, depth, element, attribute and text limits
  • reject malformed CCF and DLC entries without URLs
  • add the pinned reproducible plugin CI and ABI smoke test
  • use upstream Extism 1.30.0 for host-side tests

Validation

  • 63 unit tests, 8 corpus tests and the WASM smoke pass
  • native and WASM Clippy pass with warnings denied
  • release WASM build and cargo audit pass

Linear: MAT-129, MAT-130


Summary by cubic

Hardens Metalink parsing with strict limits and safe text/entity handling (also caps text in ignored nodes), and closes CCF/DLC parsing gaps (reject empty URLs, preserve entity refs/whitespace, omit empty filenames). Adds reproducible plugin CI with pinned verify/release workflows and a WASM ABI smoke test. Addresses Linear: MAT-129, MAT-130.

  • Bug Fixes

    • Enforce Metalink limits with typed errors: input ≤1 MiB, depth ≤64, ≤50k elements, ≤64 attrs/element, text ≤64 KiB.
    • Cap accumulated text in unrecognized elements and across split Text/CDATA/entity refs; normalize attribute and hash type values; clearer XML errors.
    • CCF/DLC: accumulate field text across fragments, trim spaces, reject missing/empty URLs; omit empty DLC filenames; preserve entity refs/spacing.
    • Upgrade quick-xml to 0.41.
  • New Features

    • Pin CI/release to canonical workflows by SHA; restrict releases to repo owner; repin reusable workflows; add release WASM ABI smoke test.
    • Pin dev extism to =1.30.0; add rust-toolchain.toml for reproducible builds; bump crate/plugin to 1.0.1.
    • Document Metalink limits in README.

Written for commit c2dbadd. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added safer Metalink XML processing with limits on input size, nesting, elements, attributes, and text nodes.
    • Improved handling of encoded text, references, CDATA, and escaped hash types.
    • Added clearer errors for malformed XML, unsupported references, and exceeded parsing limits.
  • Bug Fixes

    • Empty or whitespace-only file URLs are now correctly rejected.
    • Improved parsing of CCF and DLC metadata fields.
  • Documentation

    • Documented Metalink parsing limits and error behavior.
  • Chores

    • Updated the release version to 1.0.1 and added automated plugin CI checks.

@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The plugin now centralizes XML decoding, enforces Metalink parsing limits, supports fragmented XML content in CCF and DLC files, rejects empty URLs, updates typed errors, and adds release metadata, toolchain, CI, and WASM smoke-test coverage.

Changes

XML Parsing Hardening

Layer / File(s) Summary
XML decoding and error contracts
src/xml.rs, src/error.rs, src/lib.rs
Shared text/reference decoders and structured limit errors are added and wired into the crate.
Metalink limits and buffered parsing
src/metalink.rs, README.md
Metalink parsing now validates input, depth, element, attribute, and text limits while accumulating decoded XML content. Tests cover limit failures and malformed XML.
CCF and DLC field decoding
src/ccf.rs, src/dlc.rs
Container parsers accumulate text, CDATA, and references before assigning fields and reject empty or whitespace-only URLs.
Plugin JSON return paths
src/plugin_api.rs
detect and decrypt return mapped JSON serialization results directly.

Release and Build Integration

Layer / File(s) Summary
Release metadata and WASM build setup
Cargo.toml, plugin.toml, rust-toolchain.toml
Package versions are updated to 1.0.1, dependencies are adjusted, and the Rust WASI build configuration is pinned.
Plugin CI and WASM ABI validation
.github/workflows/plugin-ci.yml, tests/wasm_smoke.rs
Reusable Plugin CI is configured, and a smoke test loads the WASM artifact and validates exported plugin calls.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant MetalinkDecoder
  participant XMLHelpers
  participant PluginError
  Caller->>MetalinkDecoder: submit Metalink XML
  MetalinkDecoder->>XMLHelpers: decode text and references
  MetalinkDecoder->>MetalinkDecoder: enforce parsing limits
  MetalinkDecoder-->>Caller: parsed files or typed error
  MetalinkDecoder->>PluginError: construct XML or limit error
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes: hardened Metalink parsing and added plugin CI.

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

@socket-security

socket-security Bot commented Jul 15, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedextism@​1.21.0 ⏵ 1.30.08010094100100
Updatedquick-xml@​0.36.2 ⏵ 0.41.010010093100100

View full report

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/plugin-ci.yml:
- Around line 3-7: Update the workflow trigger and permission configuration so
pull_request runs receive only contents: read, while the tag push release path
retains contents: write. Split the reusable job or otherwise scope write
permissions exclusively to push events, preserving PR validation without write
access.

In `@README.md`:
- Around line 35-38: Align the README Metalink parsing guarantee with the actual
enforcement: either apply the 64 KiB text-node limit globally in the XML parsing
logic, or revise the documentation to state that it applies only to selected
Metalink fields. Ensure the documented behavior matches the implementation and
preserves the existing typed-error handling.

In `@src/ccf.rs`:
- Around line 97-100: Disable reader-level text trimming in the XML reader setup
so whitespace surrounding entity references is preserved across separate Text
events. Keep the existing trim operation applied to the fully assembled
field_text when the active field closes, preserving boundary trimming without
collapsing spaces within values such as “Rock & Roll.zip”.

In `@src/metalink.rs`:
- Around line 67-75: Update the Metalink parser handling for Event::Text,
Event::CData, and Event::GeneralRef in src/metalink.rs:67-75 so decoded content
is counted against the documented 64 KiB limit regardless of text_target,
including fragmented references. Add a regression case covering oversized text
in an ignored element at src/metalink.rs:468-497. At README.md:35-38, retain the
global-limit guarantee only after enforcement is global; otherwise document the
narrower field-only behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5d0f0db3-aab7-47a2-896f-4478552bd846

📥 Commits

Reviewing files that changed from the base of the PR and between e3cf285 and a34b466.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • .github/workflows/plugin-ci.yml
  • Cargo.toml
  • README.md
  • plugin.toml
  • rust-toolchain.toml
  • src/ccf.rs
  • src/dlc.rs
  • src/error.rs
  • src/lib.rs
  • src/metalink.rs
  • src/plugin_api.rs
  • src/xml.rs
  • tests/wasm_smoke.rs

Comment thread .github/workflows/plugin-ci.yml
Comment thread README.md Outdated
Comment thread src/ccf.rs
Comment thread src/metalink.rs

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/metalink.rs
Comment thread src/metalink.rs
Comment thread src/dlc.rs

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/metalink.rs Outdated
@mpiton
mpiton merged commit f5952e3 into main Jul 16, 2026
7 checks passed
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