Tool file URLs generated without signature parameters causing 400 validation errors
- Dominant language
- TypeScript
- Stars
- 156k
- Forks
- 24.6k
- Avg merge
- 22h 9m
- Merged PRs (30d)
- 610
Description
### Self Checks
- [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).
- [x] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general).
- [x] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones.
- [x] I confirm that I am using English to submit this report, otherwise it will be closed.
- [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
- [x] Please do not modify this template :) and fill in all the required fields.
### Dify version
1.16.0
### Cloud or Self Hosted
Self Hosted (Docker)
### Steps to reproduce
**Bug**: Tool file URLs are being generated without required security parameters (timestamp,
nonce, sign), causing 400 validation errors when users try to access tool-generated files
(images, documents, etc.)
1. Use an agent or tool that generates files (e.g., image generation)
2. Let the tool complete and generate a file
3. Try to access/download the generated file
4. Observe 400 validation error
## Error Message
pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolFileQuery
timestamp
Field required [type=missing, input_value={}, input_type=dict]
nonce
Field required [type=missing, input_value={}, input_type=dict]
sign
Field required [type=missing, input_value={}, input_type=dict]
## Root Cause
The error occurs because tool file URLs are being generated **without using the
`sign_tool_file()` function**, which is responsible for adding required security parameters.
## Affected Code Locations
### 1. `/api/core/app/apps/base_app_runner.py` (Line ~447)
```python
# CURRENT (BUGGY):
url=f"/files/tools/{tool_file.id}",
# SHOULD BE:
url=sign_tool_file(tool_file_id=tool_file.id, extension=extension),
2. /api/core/tools/utils/message_transformer.py (Line ~204)
# CURRENT (BUGGY):
@classmethod
def get_tool_file_url(cls, tool_file_id: str, extension: str | None) -> str:
return f"/files/tools/{tool_file_id}{extension or '.bin'}"
# SHOULD BE:
@classmethod
def get_tool_file_url(cls, tool_file_id: str, extension: str | None) -> str:
return sign_tool_file(tool_file_id=tool_file_id, extension=extension or '.bin')
Evidence from Logs
Nginx Access Log:
GET /files/tools/44111312-4099-465c-ae7b-1e661dce50c4.png HTTP/1.1" 400 559
Note: URL is missing query parameters ?timestamp=...&nonce=...&sign=...
API Error Log:
File "/app/api/controllers/files/tool_files.py", line 52, in get
args = ToolFileQuery.model_validate(request.args.to_dict())
pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolFileQuery
Investigation Results
✅ Environment Variables: All correctly configured
- SECRET_KEY: Properly set and loaded
- FILES_URL: https://gpt.epuber.cn
- FILES_ACCESS_TIMEOUT: 300 seconds
- Aliyun OSS: Fully configured
❌ Code Issue: Two locations generate URLs without signing
Expected Behavior
According to /api/core/tools/signature.py, tool file URLs should be generated using
sign_tool_file() which adds cryptographic signature, timestamp, and nonce parameters for
security.
Impact
- User Impact: Tool-generated files (images, documents) cannot be accessed/downloaded
- Security: The validation is working correctly - preventing unauthorized access
- Functionality: Files are generated successfully but URLs are invalid
- #29620 (https://github.com/langgenius/dify/issues/29620) - Signature Verification Failure
- #14713 (https://github.com/langgenius/dify/issues/14713) - Plugin Signature Verification
Failed
Additional Context
This issue was discovered when investigating why tool-generated images were returning 400
errors. The investigation confirmed that:
- Environment configuration is correct
- SECRET_KEY is properly loaded across all services
- The issue is purely in the URL generation code
### ✔️ Expected Behavior
✔️ Expected Behavior
Tool-generated files should be accessible via signed URLs with proper security parameters:
- URL should include ?timestamp=...&nonce=...&sign=...
- Files should download/display correctly
- No validation errors should occur
### ❌ Actual Behavior
Tool-generated files return 400 validation errors:
pydantic_core._pydantic_core.ValidationError: 3 validation errors for ToolFileQuery
timestamp - Field required
nonce - Field required
sign - Field required
Nginx access log shows requests without query parameters:
GET /files/tools/44111312-4099-465c-ae7b-1e661dce50c4.png HTTP/1.1" 400 559
Root Cause Analysis
Two code locations generate tool file URLs without using the sign_tool_file() function:
1. /api/core/app/apps/base_app_runner.py (Line ~447):
url=f"/files/tools/{tool_file.id}", # Missing signature parameters
2. /api/core/tools/utils/message_transformer.py (Line ~204):
def get_tool_file_url(cls, tool_file_id: str, extension: str | None) -> str:
return f"/files/tools/{tool_file_id}{extension or '.bin'}" # Missing signature
Environment Configuration Verified ✅
- SECRET_KEY: Properly configured and loaded
- FILES_URL: https://gpt.epuber.cn
- FILES_ACCESS_TIMEOUT: 300 seconds
- Aliyun OSS: Fully configured
- All services running healthy
Impact
- Tool-generated images/files cannot be accessed
- Affects agents that generate visual content
- Security validation working correctly (preventing unauthorized access)
Related Issues
- #21068 - File expired in historical conversations
- #29620 - Signature Verification Failure and Plugins Not Appearing
Contributor guide
Research direction
Start with the two affected locations: api/core/app/apps/base_app_runner.py and api/core/tools/utils/message_transformer.py. Read api/core/tools/signature.py and trace how tool file URLs are consumed by api/controllers/files/tool_files.py. Confirm generated URLs include timestamp, nonce, and sign parameters, then verify tool-generated files no longer return the reported 400 validation errors.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend, security
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100