Skip to content

fix(api): sign tool file URLs generated by ToolFileMessageTransformer#39225

Open
amogh-nagri-11 wants to merge 4 commits into
langgenius:mainfrom
amogh-nagri-11:fix/39222-unsigned-tool-file-url
Open

fix(api): sign tool file URLs generated by ToolFileMessageTransformer#39225
amogh-nagri-11 wants to merge 4 commits into
langgenius:mainfrom
amogh-nagri-11:fix/39222-unsigned-tool-file-url

Conversation

@amogh-nagri-11

Copy link
Copy Markdown

Summary

  • ToolFileMessageTransformer.get_tool_file_url() built tool file URLs as a bare /files/tools/<id><ext> path with no signature, and that URL is used directly as the text of IMAGE_LINK / BINARY_LINK / LINK tool messages, which flow straight into the agent's answer/workflow output with no re-signing step downstream.
  • Since /files/tools/<id> requires timestamp, nonce, and sign query params (validated via ToolFileQuery in controllers/files/tool_files.py), any request to these unsigned URLs returns a 400.
  • Fixes it by routing get_tool_file_url() through the existing sign_tool_file() helper (core/tools/signature.py), the same signer used elsewhere in the codebase.

Note on scope: the issue also flags base_app_runner.py (MessageFile.url stored unsigned). That value is only used internally to recover tool_file_id (Message.message_files in models/model.py) and is re-signed fresh via
File.generate_url() before ever reaching a client, so it isn't part of this bug and wasn't changed here.

Fixes #39222

Test plan

  • uv run --project api python -m pytest api/tests/unit_tests/core/tools/utils/test_message_transformer.py -q
  • uv run --project api python -m pytest api/tests/unit_tests/core/tools/test_signature.py -q
  • uv run ruff check / ruff format --check on changed files

session.add/session.commit for a new segment ran outside the
redis_client.lock covering the max-position read, so concurrent
create_segment calls on the same document could read the same
max_position and commit duplicate segment positions.
hlen() and hset() were two separate, unsynchronized Redis round-trips,
letting concurrent requests all read a count under the cap and all get
admitted, exceeding max_active_requests. Replaced with a single atomic
Lua script that checks-and-sets in one round trip.
…test

create_segment takes session as an explicit parameter and never touches
the module-level db global, so patching it was unnecessary and appears
fragile under CI's parallel (-n auto) test execution, where the patch
target intermittently reported "module has no attribute db". Build the
mock session directly instead.
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool file URLs generated without signature parameters causing 400 validation errors

1 participant