Skip to content

fix(safety): allow image-only messages without text content#1208

Open
smkrv wants to merge 1 commit intonearai:mainfrom
smkrv:fix/allow-image-only-messages
Open

fix(safety): allow image-only messages without text content#1208
smkrv wants to merge 1 commit intonearai:mainfrom
smkrv:fix/allow-image-only-messages

Conversation

@smkrv
Copy link
Contributor

@smkrv smkrv commented Mar 15, 2026

Problem

Messages with attachments (photos, files) but no text caption are rejected by safety validation:

Input rejected by safety validation: input: Input cannot be empty

This affects all channels (Telegram, web, etc.) when users send image-only messages.

Root cause: SafetyLayer::validate_input(content) in thread_ops.rs rejects empty strings. For image-only messages, content is empty because the text portion has no caption — but the message has valid attachments that get processed downstream by augment_with_attachments().

Fix

Skip the empty-input validation check when the message has attachments. The attachment pipeline will provide content (image descriptions, extracted text) downstream. Non-empty text messages still go through full safety validation.

let has_attachments = !message.attachments.is_empty();
let validation = if content.is_empty() && has_attachments {
    ironclaw_safety::ValidationResult::ok()
} else {
    self.safety().validate_input(content)
};

Testing

  • Verified locally with Telegram channel sending photos without captions
  • All existing tests pass (cargo test)
  • Clippy clean (cargo clippy --all-features)

@github-actions github-actions bot added the scope: agent Agent core (agent loop, router, scheduler) label Mar 15, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a bug where messages containing only attachments, such as image-only messages without captions, were incorrectly rejected by the safety validation system. The change introduces a conditional bypass for the empty-input validation when attachments are present, ensuring that these messages are properly handled and processed downstream, thus improving the robustness of message processing across various channels.

Highlights

  • Safety Validation: Modified the safety validation logic to allow messages containing only attachments (e.g., images) without any text content, preventing them from being rejected as empty inputs.
  • Attachment Handling: Introduced a check for message attachments to conditionally bypass the empty-input validation, ensuring that messages with valid attachments are processed even if their text content is empty.
Changelog
  • src/agent/thread_ops.rs
    • Added a conditional check to bypass empty input safety validation if a message contains attachments but no text content.
Activity
  • No specific activity beyond the initial PR creation has been noted.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions github-actions bot added size: S 10-49 changed lines risk: medium Business logic, config, or moderate-risk modules contributor: regular 2-5 merged PRs labels Mar 15, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request addresses a bug where messages containing only attachments without any text were being rejected by the safety validation. The fix modifies process_user_input to bypass the empty-input validation check when attachments are present, as the message content is augmented with attachment information downstream in the pipeline. The change is localized to the safety validation logic and resolves the described issue.

Messages with attachments (e.g., photos sent via Telegram) but no text
caption were rejected by safety validation with "Input cannot be empty".

The empty-input check now skips when the message has attachments, since
the attachment pipeline (augment_with_attachments) will provide content
downstream. Non-empty text messages still go through full validation.

Fixes image/file-only messages being rejected across all channels.
@smkrv smkrv force-pushed the fix/allow-image-only-messages branch from e2afa3a to 903739b Compare March 15, 2026 17:52
Copy link
Collaborator

@zmanian zmanian left a comment

Choose a reason for hiding this comment

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

Review: REQUEST CHANGES

Correct diagnosis -- image-only messages (empty content + attachments) were rejected by the Validator before the attachment pipeline could extract useful content. The bypass is safe: empty strings contain no injection payload.

Issues (should fix):

  1. Missing regression test at the thread_ops level. The new tests only prove the validator rejects empty input (already true). The actual bypass logic in thread_ops.rs has no test. Per review-discipline.md: "Every bug fix must include a test that would have caught the bug." Need a test exercising process_user_input with empty content + non-empty attachments.

  2. Incomplete bypass. After skipping validate_input, check_policy(content) and scan_inbound_for_secrets(content) still run on the empty string (lines ~258 and ~269 in thread_ops.rs). Both are harmless on empty input, but semantically wrong and confusing for future maintainers. The bypass should cover all three checks consistently when content is empty and attachments are present.

Note (not blocking, worth tracking separately):

augment_with_attachments produces content from image transcripts and extracted text that never passes through safety validation (validate_input, check_policy, scan_inbound_for_secrets). An adversary could embed prompt injection in an image transcript or PDF text. This predates this PR and is not made worse by it, but is worth a follow-up issue.

What's good:

  • Narrowly scoped fix (12 lines of production code)
  • Bypass lives in the caller, not the validator -- preserves validator invariants
  • Security analysis: bypass only fires on literally empty strings, non-empty messages still get full safety checks
  • CI all green

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: regular 2-5 merged PRs risk: medium Business logic, config, or moderate-risk modules scope: agent Agent core (agent loop, router, scheduler) size: S 10-49 changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants