You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Native image routing now honors the shared file-safety read guard before embedding local image bytes into the model-provider request.
Problem
agent.image_routing.build_native_content_parts() reads local image paths through _file_to_data_url() and converts them into base64 data: URLs for native multimodal model input.
That path did not call the shared agent.file_safety read guard. As a result, a protected target could still be embedded into the outbound model request if it reached native image routing as a local image attachment, including the symlink case where an image-looking path points at a read-denied credential file.
This is the same boundary shape as other local media/provider-input fixes: local file bytes cross from Hermes into an external model provider request, so the shared file-safety policy should be applied at the final byte-loading chokepoint.
Changes
Call raise_if_read_blocked() inside _file_to_data_url() before reading local image bytes.
Treat blocked files like unreadable/unsupported attachments: skip them and continue the turn.
Add regression coverage for:
direct read-denied local image paths
native content parts skipping blocked images
image-looking symlinks whose resolved target is read-denied
Tests
python -m pytest tests/agent/test_image_routing.py -q -k "read_denied or symlink or png_passes" --timeout-method=thread
4 passed, 93 deselected
This was generated by AI during triage.
Related: same credential-read-guard family as #57827 (vision_tools.py local-file branches) — this closes the analogous chokepoint in agent/image_routing.py_file_to_data_url(). Complements the merged #57726/#57695 provider-input guard work; not a duplicate (different code site).
Security evidence: The affected trust boundary is local image paths converted into base64 data URLs for native multimodal provider requests, and I verified the current-main route embedded a synthetic PNG at HERMES_HOME/auth.json while the PR-merge route skipped that denied path, still passed a normal PNG through, covered denied .env paths and symlink-to-denied-file behavior in the focused image-routing tests (4 passed, 93 deselected), and kept _file_to_data_url as the byte-loading chokepoint used by build_native_content_parts.
CodeRabbit reported the broad exception around raise_if_read_blocked; source review found no remaining blocker because actual file-safety denials are raised as ValueError and return None before path.read_bytes(), while unexpected file-safety machinery failures already have documented best-effort/no-op semantics in agent.file_safety. I also checked the patch scope, current-base merge tree, and whitespace, and found no evidence-backed blocker.
Merged via PR #58752 — your commit was cherry-picked onto current main with your authorship preserved in git history (c13281a). Guarding at the single byte-loading chokepoint with graceful skip semantics was exactly the right shape, and the symlink regression test carried over as-is. Thanks!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
comp/agentCore agent runtime: loop, agent_init, prompt builder, context-compression, responses endpointneeds-reproBug needs reproduction stepsP2Medium — degraded but workaround existssweeper:risk-security-boundarySweeper risk: may affect sandboxing, auth, credentials, or sensitive datatool/visionVision analysis and image generationtype/securitySecurity vulnerability or hardening
4 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Native image routing now honors the shared file-safety read guard before embedding local image bytes into the model-provider request.
Problem
agent.image_routing.build_native_content_parts()reads local image paths through_file_to_data_url()and converts them into base64data:URLs for native multimodal model input.That path did not call the shared
agent.file_safetyread guard. As a result, a protected target could still be embedded into the outbound model request if it reached native image routing as a local image attachment, including the symlink case where an image-looking path points at a read-denied credential file.This is the same boundary shape as other local media/provider-input fixes: local file bytes cross from Hermes into an external model provider request, so the shared file-safety policy should be applied at the final byte-loading chokepoint.
Changes
raise_if_read_blocked()inside_file_to_data_url()before reading local image bytes.Tests