Skip to content

fix: reject unsupported MIME types in image blocks - #1961

Merged
edelauna merged 2 commits into
Zoo-Code-Org:mainfrom
WebMad:fix/1950-image-mime-guard
Oct 9, 2026
Merged

edelauna merged 2 commits into
Zoo-Code-Org:mainfrom
WebMad:fix/1950-image-mime-guard

Conversation

@WebMad

@WebMad WebMad commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Related GitHub Issue

Part of #1948. Extracted from #1950 as a standalone prerequisite bugfix; this PR does not close the issue or implement bounded batch reading.

Description

The existing shared formatter accepts BMP, TIFF, ICO, AVIF, SVG, and arbitrary MIME values, then hides the SDK contract violation behind a type assertion. This PR rejects those sources explicitly before returning an image payload.

The production changes are byte-identical to the two selected production hunks at #1950 head 1101a85. The branch starts from freshly fetched upstream main 2baac5e, not the reader-refactoring branch.

Exactly three files change:

JPEG/PNG/GIF/WebP block structure, valid base64 data, image ordering, duplicate images, text feedback, and absent/empty-image behavior remain compatible. Unsupported MIME values and malformed/noncanonical headers now produce an explicit error naming the MIME or unknown. As in the selected extraction, the payload is the complete suffix after the header comma and remains opaque: there is no new base64 or image-byte validation, conversion, or normalization.

The reader-specific checks, descriptor-bound image reads, reader-specific unsupported/context-tracking behavior, native description changes, Unicode filename clipping, approval/cancellation/document processing, and numeric validation stay in #1950. There is no dependency on its new reader module, no new dependency/setting/test infrastructure, and no changelog or changeset. After this prerequisite is merged by maintainers, #1950 can update its base and drop these shared hunks; this PR will not be merged by the agent.

Regression evidence

Before applying either production hunk, the new formatter regressions ran against upstream main: 31 failed / 10 passed. In particular the old formatter returned incompatible BMP/TIFF/ICO blocks instead of rejecting them, while the supported-format assertions passed. After extraction, all 53 new tests pass.

The tests assert complete blocks and exact errors through both public formatter entry points, all existing MIME-map values plus unknown types, malformed headers, unsupported case/alias/whitespace spellings, Unicode BOM/zero-width/homoglyph/fullwidth delimiter boundaries, combining/astral feedback and opaque payload preservation, empty inputs, mixed-array failures, ordering, and input immutability. Unicode fixtures use escapes rather than prohibited invisible source characters.

The old reader already catches response-construction errors, and existing assistant-message/tool-feedback and provider suites are included in focused and full verification. Rejecting incompatible images at this shared boundary is intentional; conversion and reader-specific unsupported results remain outside this extraction.

Verification

On repository-pinned Node 22.23.1 / pnpm 10.8.1, in the isolated branch:

  • Focused package-local Vitest run: 6 suites / 146 tests passed, including the MIME regressions, assistant-message images, image cleaning, Anthropic provider, and existing formatter suites.
  • Full monorepo test command: 13/13 Turbo tasks passed, including 9,988 backend tests and 1,911 webview tests. Existing skips remain unchanged (backend: 39 tests / 4 files).
  • A second full backend run with V8 coverage: 9,988 passed / 39 existing skips, 520 passed / 4 skipped files.
  • Final verification head: 8a73f7f. Self-review made the empty-array parameter case explicit with a named object row; scoped formatting/lint, the 146 focused tests, and full 9,988-test backend coverage were rerun successfully. Normal commit/push hooks also reran monorepo lint/type checks.
  • Coverage comparison against upstream main: 9,935 existing backend tests passed / 39 existing skips before adding the new suite; 108 unchanged statement/function/branch counters were matched across the line shift and none of the previously covered counters became uncovered.
  • Full monorepo lint: 11/11 tasks passed; scoped lint with suppression pruning passed for all three files. The entire suppression ledger is semantically identical to the base; only ESLint-generated formatting churn was restored.
  • Full monorepo type checks: 11/11 tasks passed, including backend type checking.
  • Monorepo build: 4/4 tasks passed; production extension bundle passed.
  • Knip, translation completeness check, scoped Prettier check, changed-source invisible-character scan, and whitespace diff check passed.
  • Final diff audited: precisely the three selected files; no unrelated or original-worktree changes included.

Actual coverage results

Measured with the repository's Vitest V8 coverage provider, using both the focused run and full backend run. Raw counters were checked for every executable statement, function, and branch arm in the complete extracted utility and complete shared image-formatting path (including both public entry points).

Production scope Lines Functions Branch arms Statements
Complete imageMime utility 100% (2/2) 100% (2/2) 100% (4/4) 100% (2/2)
Complete shared image-formatting path in responses 100% (13/13) 100% (4/4) 100% (10/10) 100% (13/13)
Combined extracted/affected image logic 100% (15/15) 100% (6/6) 100% (14/14) 100% (15/15)

This is not a claim of 100% coverage for unrelated unchanged formatter behavior. The unfiltered whole formatter module in the full backend report has 84.84% lines, 76.19% functions, 72.91% branches, and 85.07% statements. Both complete production files were instrumented; no coverage exclusions, ignore pragmas, disabled checks, or relaxed existing tests were introduced. Test files are excluded by the repository's normal coverage configuration, not counted as production coverage. All requested production metrics are supported and reported.

The repository currently pins Vitest 4.1.11 and coverage-v8 4.1.9, which emit an existing mixed-version warning; reports and their raw counters were produced successfully. Prettier also emits the existing unknown ignore configuration-option warning. Neither warning was hidden or “fixed” through unrelated infrastructure changes.

To reproduce: from the backend package, run the MIME suite together with the assistant-image suite, image-cleaning suite, Anthropic suite, and existing formatter suites. Enable V8 coverage for the entire utility and formatter module; inspect the complete image functions and branch counters rather than discarding uncovered unrelated formatter code.

Pre-Submission Checklist

  • Issue linked and relationship to refactor: isolate reusable file-reading foundation (part of #1948) #1950 documented.
  • Scope limited to the selected shared MIME extraction.
  • Self-review, behavior regressions, coverage, lint, formatting, types, and build completed.
  • No new dependencies, persisted settings, changesets, or changelog changes.
  • No UI change; visual snapshots and user-facing documentation updates are not required.
  • AI assistance disclosed: implementation transfer, test expansion, and verification were performed with Zoo assistance, with actual local results checked.

Published CI and review status

  • Final head: 8a73f7f.
  • All six required CI checks passed: Linux/Windows unit tests, mocked end-to-end tests, compilation, Knip, and translation completeness. The test VSIX build, dependency review, invisible-character check, CodeQL, and Codecov checks also passed.
  • Codecov patch coverage independently reports 100.00% of diff hit.
  • Explicit CodeRabbit APPROVED review for the exact final head, submitted 2026-10-08 12:48:53 UTC: review #5456806813. No actionable comments or review threads were generated. The repository review gate passed and the PR is awaiting a human maintainer.
  • The underlying OpenGrep shell-execution finding is a false positive: the parser executes a literal regular expression, not a process or shell command. No production change or check suppression is warranted.
  • The separate advisory mutation-testing job completed successfully. Its downloaded report confirms 33/33 mutants killed: 10 in the formatter and 23 in the utility, with no surviving or uncovered mutants (100% mutation score). The report's related-test preflight also passed all 1,877 tests. CodeRabbit had already approved while that check was running. The mutation workflow reruns on PR-description edits even without code changes; any such rerun is independently visible in CI and is not implicitly claimed as complete here.
  • The PR remains open and has not been merged.

@coderabbitai

coderabbitai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: Zoo-Code-Org/Zoo-Code/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 738d5ca8-2cb1-4a9c-b044-770e08ec8eae

📥 Commits

Reviewing files that changed from the base of the PR and between 8a73f7f and 50e7aea.


📒 Files selected for processing (2)
  • src/core/mentions/__tests__/resolveImageMentions.spec.ts
  • src/core/mentions/resolveImageMentions.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.


📜 Recent review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: mutation-diff

🧰 Additional context used
📓 Path-based instructions (4)
Require regression coverage at the lowest valid harness with behavior-focused assertions, including relevant negative, error, false/unset, and boundary cases.

⚙️ CodeRabbit configuration file

Files:

  • src/core/mentions/__tests__/resolveImageMentions.spec.ts

Check strict typing and exhaustive behavior across normal, boundary, error, cancellation, retry, and compatibility paths.

⚙️ CodeRabbit configuration file

Files:

  • src/core/mentions/__tests__/resolveImageMentions.spec.ts
  • src/core/mentions/resolveImageMentions.ts

Verify extension/webview contracts, cancellation and error propagation, VS Code lifecycle correctness, and behavior under retries and partial failure.

⚙️ CodeRabbit configuration file

Files:

  • src/core/mentions/__tests__/resolveImageMentions.spec.ts
  • src/core/mentions/resolveImageMentions.ts

Act as an adversarial second-opinion reviewer.

⚙️ CodeRabbit configuration file

Files:

  • src/core/mentions/__tests__/resolveImageMentions.spec.ts
  • src/core/mentions/resolveImageMentions.ts



🔇 Additional comments (2)
src/core/mentions/resolveImageMentions.ts (1)

4-4: LGTM!

Also applies to: 54-58, 135-138


src/core/mentions/__tests__/resolveImageMentions.spec.ts (1)

134-161: LGTM!





📝 Summary

Summary by CodeRabbit

  • New Features
    • Image responses support JPEG, PNG, GIF, and WebP, while preserving image order and accompanying text.
  • Bug Fixes
    • Unsupported image types are skipped when resolving image mentions. Unsupported or unrecognized types supplied directly to response formatting produce an error.
  • Tests
    • Added coverage for supported and unsupported image types, image ordering and duplicates, text formatting, and opaque image payloads.

Walkthrough

Image formatting now validates MIME types in base64 data URLs. JPEG, PNG, GIF, and WebP are accepted. Unsupported or unrecognized types cause an error during formatting and are skipped during image mention resolution. Tests cover both paths.

Changes

Image MIME validation

Layer / File(s) Summary
MIME detection and support checks
src/utils/imageMime.ts, src/core/prompts/__tests__/responses-images.spec.ts
Added helpers to extract MIME types from matching base64 data URLs and check for JPEG, PNG, GIF, and WebP. Tests cover supported and unsupported values.
Image block validation
src/core/prompts/responses.ts, src/core/prompts/__tests__/responses-images.spec.ts
Image formatting validates each MIME type and rejects unsupported or unknown types. It uses the validated MIME type and extracts the payload after the first comma. Tests cover formatting, ordering, input preservation, and payload handling.
Image mention filtering
src/core/mentions/resolveImageMentions.ts, src/core/mentions/__tests__/resolveImageMentions.spec.ts
Image mention resolution skips unsupported MIME types. Tests cover supported and unsupported formats, mixed mentions, and memory and image-count limits.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix


Merge Risk: ⚪ Minimal · up to 50e7a

No actionable merge-blocking risk is established for these changes.

🚥 Pre-merge checks | ✅ 8
✅ Passed checks (8 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.
Regression Evidence Passed PASS. The changed MIME utility has focused tests for all four accepted types, unsupported types, missing headers, and empty values. The formatter tests cover both formatResponse.imageBlocks and `for…
Security Boundaries Passed No concrete security-boundary failure is introduced. src/utils/imageMime.ts uses a fixed MIME parser and an exact allowlist for JPEG, PNG, GIF, and WebP. src/core/prompts/responses.ts rejects unsu…
Persistence Integrity Passed No changed persistence path exists. The production changes only validate image MIME types, skip unsupported mention images, and format in-memory image arrays. They add no file, database, settings, or …
Lifecycle Resource Cleanup Passed No changed lifecycle resource path exists. The changes add pure MIME parsing and validation in imageMime.ts, synchronous block mapping in formatImagesIntoBlocks, and a per-call in-memory `ImageMem…
Title check Passed The title clearly and concisely describes the primary change: rejecting unsupported MIME types in image blocks.
Description check Passed The description is comprehensive and covers the related issue, implementation, scope, testing procedure, verification results, checklist, documentation impact, and review status. It uses verification …


✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR


  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

github-actions Bot commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Review status

Thanks for contributing. This comment tracks the review sequence and the next action.

Current step: Awaiting fresh human maintainer or CODEOWNER approval.

Automated review is complete for the latest commit but does not replace human approval.

Review-state labels are managed by this workflow; do not edit them manually. community-approved is managed the same way — do not add or remove it manually. It signals a fresh community code approval for the current head as an advisory priority only; maintainer review is still required.

@codecov

codecov Bot commented Oct 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions github-actions Bot added coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Oct 8, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Oct 8, 2026
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Oct 8, 2026
@WebMad

WebMad commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

Review follow-through: CodeRabbit explicitly approved the current head 8a73f7f in review #5456806813; there are no actionable comments or review threads. I inspected the underlying OpenGrep command-injection finding: getImageMimeType() uses RegExp.exec() on a literal regular expression. Its only import is type-only; it has no process import, shell, or command execution. That scanner result is a false positive, so no production guard or check was changed. All required CI is green and Codecov reports 100.00% of the diff hit. The separate advisory mutation job is still running and is not claimed as passed. This PR has not been merged.

WebMad added a commit to WebMad/Zoo-Code that referenced this pull request Oct 8, 2026
…#1948)

Build on the extracted Unicode clipping, shared image MIME guard, and streamed path fixes from PRs Zoo-Code-Org#1960, Zoo-Code-Org#1961, and Zoo-Code-Org#1962. Preserve their latest regression coverage while composing reader strategies, descriptor-bound access, approval, cancellation, and validated text/document results.
WebMad added a commit to WebMad/Zoo-Code that referenced this pull request Oct 8, 2026
…#1948)

Build on the extracted Unicode clipping, shared image MIME guard, and streamed path fixes from PRs Zoo-Code-Org#1960, Zoo-Code-Org#1961, and Zoo-Code-Org#1962. Preserve their latest regression coverage while composing reader strategies, descriptor-bound access, approval, cancellation, and validated text/document results.
Extract the shared image MIME guard from PR Zoo-Code-Org#1950 as a standalone prerequisite for Zoo-Code-Org#1948. Preserve the supported SDK payload contract and cover both formatter entry points, malformed headers, Unicode lookalikes, and opaque payload boundaries.
@WebMad
WebMad force-pushed the fix/1950-image-mime-guard branch from 8a73f7f to c6baabf Compare October 8, 2026 14:03
WebMad added a commit to WebMad/Zoo-Code that referenced this pull request Oct 8, 2026
…#1948)

Build on the extracted Unicode clipping, shared image MIME guard, and streamed path fixes from PRs Zoo-Code-Org#1960, Zoo-Code-Org#1961, and Zoo-Code-Org#1962. Preserve their latest regression coverage while composing reader strategies, descriptor-bound access, approval, cancellation, and validated text/document results.
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed awaiting-maintainer CodeRabbit approved; waiting for a human maintainer labels Oct 8, 2026
@github-actions github-actions Bot added the community-approved Fresh community approval on the current head; maintainer review still required label Oct 8, 2026
Comment thread src/core/prompts/responses.ts
@github-actions github-actions Bot added awaiting-author PR is waiting for the author to address requested changes and removed awaiting-maintainer CodeRabbit approved; waiting for a human maintainer community-approved Fresh community approval on the current head; maintainer review still required labels Oct 9, 2026
@github-actions github-actions Bot removed the awaiting-author PR is waiting for the author to address requested changes label Oct 9, 2026
@WebMad
WebMad requested a review from edelauna October 9, 2026 16:06
@github-actions github-actions Bot added coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Oct 9, 2026
@github-actions github-actions Bot added awaiting-maintainer CodeRabbit approved; waiting for a human maintainer and removed coderabbit-review-active Required CI passed; CodeRabbit review is active awaiting-coderabbit Waiting for CodeRabbit to approve the latest commit labels Oct 9, 2026
@edelauna
edelauna added this pull request to the merge queue Oct 9, 2026
Merged via the queue into Zoo-Code-Org:main with commit b7ab5a8 Oct 9, 2026
21 checks passed
WebMad added a commit to WebMad/Zoo-Code that referenced this pull request Oct 10, 2026
…#1948)

Build on the extracted Unicode clipping, shared image MIME guard, and streamed path fixes from PRs Zoo-Code-Org#1960, Zoo-Code-Org#1961, and Zoo-Code-Org#1962. Preserve their latest regression coverage while composing reader strategies, descriptor-bound access, approval, cancellation, and validated text/document results.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-maintainer CodeRabbit approved; waiting for a human maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants