Repository navigation
List and download pasted inline images through ctx.files - #629
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The HTML image-tag regex has quadratic behavior on malformed user-controlled input.
1 open finding
What changed in this PR
Adds pasted inline-image support to ctx.files, including filtering, secure Bot API downloads, format detection, errors, tests, and example updates.
Changes:
- Lists and filters uploaded files and pasted images.
- Downloads inline images using lazily resolved Bot API credentials.
- Adds format detection, redirect protections, errors, and coverage.
| File | Description |
|---|---|
packages/apps/tests/test_inline_image.py |
Tests image parsing and format detection. |
packages/apps/tests/test_files_download_inline.py |
Tests inline-image downloads and security. |
packages/apps/tests/test_files_download_graph.py |
Expands redirect credential tests. |
packages/apps/tests/test_files_credential.py |
Tests lazy Bot API credentials. |
packages/apps/tests/test_files_accessor_inline.py |
Tests inline-image listing and filtering. |
packages/apps/tests/test_app_process.py |
Tests context credential wiring. |
packages/apps/src/microsoft_teams/apps/routing/activity_context.py |
Passes Bot API credentials to files. |
packages/apps/src/microsoft_teams/apps/files/types.py |
Defines attachment styles. |
packages/apps/src/microsoft_teams/apps/files/inline_image.py |
Parses and identifies inline images. |
packages/apps/src/microsoft_teams/apps/files/incoming_file.py |
Supports inline-image downloads and typing. |
packages/apps/src/microsoft_teams/apps/files/files_accessor.py |
Lists and filters inline images. |
packages/apps/src/microsoft_teams/apps/files/errors.py |
Adds inline-image-specific errors. |
packages/apps/src/microsoft_teams/apps/files/downloaded_file.py |
Documents resolved image metadata. |
packages/apps/src/microsoft_teams/apps/files/download.py |
Implements secure Bot API fetching. |
packages/apps/src/microsoft_teams/apps/files/__init__.py |
Exports new public APIs. |
packages/apps/src/microsoft_teams/apps/files_credential.py |
Selects lazy inline-image credentials. |
packages/apps/src/microsoft_teams/apps/app_process.py |
Builds credentials per activity. |
examples/ai-file-analysis/src/main.py |
Handles pasted-image downloads. |
examples/ai-file-analysis/src/file_card.py |
Displays attachment style. |
examples/ai-file-analysis/README.md |
Documents inline-image behavior. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Inside FilesAccessor, `list` resolves to the accessor's own `list()` method, so Pyright could not type the parameter. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Compare service URL paths case-sensitively, match img tags in linear time with quote awareness, and skip inline image hint parsing when listing only file attachments. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Corina (corinagum)
force-pushed
the
cg/inline-images-py
branch
from
October 14, 2026 17:19
9751237 to
947c877
Compare
Lily Du (lilyydu)
approved these changes
Oct 15, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.

What this does
Images a user pastes into a message are now listed by
ctx.filesalongside attached files, and download through the samedownload()call. Each listed file has a newattachment_styleof"file"or"inlineImage", andlist()andfirst()acceptattachment_style=to return only one kind.Inline images are read from the Bot API with the same token the app uses to reply in that conversation, not through Graph. That makes them work for traditional bots and agentic users alike, in personal chats, group chats and channels. The token is resolved lazily, so a turn that never downloads an inline image never acquires one.
Naming and formats
image-<attachmentId>, with an extension and MIME type taken from the format hint in the message HTML..gifand downloads as PNG; the downloaded type is detected from the bytes.InlineImageTransformationError(415). The same image sent as a file downloads normally.InlineImageAccessError(401or403), distinct fromFileAccessError, which is about Graph.Where the token is sent
The Bot API token is only sent to an
httpsURL under the activity'sservice_url. An inline image hosted anywhere else is skipped with a warning. Redirects keepAuthorizationonly while they stay on the original origin and are refused if they leavehttps; this PR adds tests that pin that behavior for the inline and Graph paths.Behavior change for existing code
list()andfirst()previously returned only attached files. They now include pasted images by default, so an app that treats every listed item as an uploaded document should passattachment_style="file".Testing
ai-file-analysisexample, which now shows pasted images: PNG, JPEG, GIF and WebP in one message, as a traditional bot and as an agentic user, in a personal chat, a group chat, a channel post and a channel thread reply.