Skip to content

fix(utils): handle image_url string shorthand in _is_image_type_with_blob_content - #6478

Merged
sentrivana merged 1 commit into
getsentry:masterfrom
devteamaegis:fix/attributeerror-crash-on-unguarded-get-ca
Jun 2, 2026
Merged

fix(utils): handle image_url string shorthand in _is_image_type_with_blob_content#6478
sentrivana merged 1 commit into
getsentry:masterfrom
devteamaegis:fix/attributeerror-crash-on-unguarded-get-ca

Conversation

@devteamaegis

Copy link
Copy Markdown
Contributor

What's broken

_is_image_type_with_blob_content crashes with AttributeError: 'str' object has no attribute 'get' when image_url is a plain string shorthand (e.g. {"type": "image_url", "image_url": "data:image/jpeg;base64,..."}) instead of a dict. The OpenAI API supports this form and transform_openai_content_part in the same file documents it. Any call to redact_blob_message_parts — which is invoked from truncate_and_annotate_messages across the OpenAI, LiteLLM, Anthropic, LangChain, pydantic-ai, and openai-agents integrations when send_default_pii=True — would crash on such input.

Why it happens

item.get("image_url", {}) returns the raw string when the value is a string, and the subsequent .get("url", "") call fails because strings have no .get method.

Fix

Check isinstance(image_url_val, dict) before calling .get("url", ""), falling back to using the string directly. The same guard is applied to the redaction path at line 702 where item["image_url"]["url"] would also fail on a string.

Test

Added test_redact_blob_message_parts_image_url_string_shorthand to TestRedactBlobMessageParts which passes a message with the string shorthand form and asserts it is redacted to [Blob substitute] without raising.

Fixes #6477

…ntent

When image_url is a plain string (OpenAI shorthand), calling .get() on it
raised AttributeError. Now both dict form {"url": "..."} and string form
are handled correctly in both the detection and redaction paths.
@devteamaegis
devteamaegis requested a review from a team as a code owner June 1, 2026 18:32
Comment thread sentry_sdk/ai/utils.py
Comment on lines +614 to +617
image_url_val.get("url", "")
if isinstance(image_url_val, dict)
else (image_url_val or "")
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Bug: If image_url_val is a truthy non-string, non-dict value, re.match() is called on a non-string, causing a TypeError.
Severity: LOW

Suggested Fix

Ensure image_url is a string before passing it to DATA_URL_BASE64_REGEX.match(). One way is to explicitly convert image_url_val to a string or handle the else case more safely, for example by returning an empty string if the type is not a string. A more robust fix would be else str(image_url_val or "").

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: sentry_sdk/ai/utils.py#L614-L617

Potential issue: The expression `(image_url_val or "")` does not properly handle all
types. If `image_url_val` is a truthy value that is not a string or a dictionary (e.g.,
a list or an integer), the expression will return the original object. Subsequently,
`DATA_URL_BASE64_REGEX.match()` is called with this non-string object, which raises a
`TypeError: expected string or bytes-like object`. While this requires malformed input,
the function does not perform type validation, making it vulnerable to data from
user-constructed messages or buggy integrations.

Did we get this right? 👍 / 👎 to inform future reviews.

@sentrivana
sentrivana merged commit 6bee147 into getsentry:master Jun 2, 2026
139 checks passed
mgaligniana pushed a commit to mgaligniana/sentry-python that referenced this pull request Aug 9, 2026
…blob_content (getsentry#6478)

## What's broken

`_is_image_type_with_blob_content` crashes with `AttributeError: 'str'
object has no attribute 'get'` when `image_url` is a plain string
shorthand (e.g. `{"type": "image_url", "image_url":
"data:image/jpeg;base64,..."}`) instead of a dict. The OpenAI API
supports this form and `transform_openai_content_part` in the same file
documents it. Any call to `redact_blob_message_parts` — which is invoked
from `truncate_and_annotate_messages` across the OpenAI, LiteLLM,
Anthropic, LangChain, pydantic-ai, and openai-agents integrations when
`send_default_pii=True` — would crash on such input.

## Why it happens

`item.get("image_url", {})` returns the raw string when the value is a
string, and the subsequent `.get("url", "")` call fails because strings
have no `.get` method.

## Fix

Check `isinstance(image_url_val, dict)` before calling `.get("url",
"")`, falling back to using the string directly. The same guard is
applied to the redaction path at line 702 where
`item["image_url"]["url"]` would also fail on a string.

## Test

Added `test_redact_blob_message_parts_image_url_string_shorthand` to
`TestRedactBlobMessageParts` which passes a message with the string
shorthand form and asserts it is redacted to `[Blob substitute]` without
raising.

Fixes getsentry#6477

Co-authored-by: devteamaegis <devteamaegis@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants