Skip to content

fix: harden Flask REST API uploads#13760

Merged
glenn-jocher merged 4 commits intoultralytics:masterfrom
orbisai0security:fix-file-upload-validation-v001
May 2, 2026
Merged

fix: harden Flask REST API uploads#13760
glenn-jocher merged 4 commits intoultralytics:masterfrom
orbisai0security:fix-file-upload-validation-v001

Conversation

@orbisai0security
Copy link
Copy Markdown
Contributor

@orbisai0security orbisai0security commented Apr 30, 2026

Summary

Hardens the demo Flask REST API upload path by rejecting unsupported, malformed, and oversized image uploads before inference.

Vulnerability

Field Value
ID V-001
Severity MEDIUM
Scanner multi_agent_ai
Rule V-001
File utils/flask_rest_api/restapi.py:25

The endpoint previously accepted uploaded files without type or size validation before passing them to image parsing and inference.

Changes

  • Adds an image extension allowlist and PIL.Image.verify() validation for uploaded files.
  • Enforces a 16 MB upload/request limit and returns JSON for oversized uploads rejected by Flask.
  • Rejects malformed image uploads with a 400 client error instead of a server error.
  • Changes the default Flask bind address from 0.0.0.0 to 127.0.0.1 to avoid exposing the demo API on all interfaces by default.
  • Adds focused Flask test-client regression coverage for invalid, disallowed, oversized, and valid uploads.

Behavior Change

The demo server now binds to 127.0.0.1 by default. Users who previously accessed it remotely via the default all-interface bind will need to make an intentional host/proxy configuration change.

Validation

  • PYTHONPATH=$PWD pytest -q -c /dev/null -p no:cacheprovider tests/test_flask_rest_api.py (4 passed)
  • python -m py_compile utils/flask_rest_api/restapi.py tests/test_flask_rest_api.py
  • ruff check utils/flask_rest_api/restapi.py tests/test_flask_rest_api.py

Automated security fix by OrbisAI Security

Automated security fix generated by Orbis Security AI
@UltralyticsAssistant UltralyticsAssistant added bug Something isn't working fixed Bug has been resolved python Pull requests that update python code labels Apr 30, 2026
@UltralyticsAssistant
Copy link
Copy Markdown
Member

👋 Hello @orbisai0security, thank you for submitting a ultralytics/yolov5 🚀 PR! This is an automated message to help with review prep, and an engineer will assist you soon.

To ensure a seamless integration of your work, please review the following checklist:

  • Define a Purpose: Clearly explain the purpose of your fix or feature in your PR description, and link to any relevant issues. Ensure your commit messages are clear, concise, and adhere to the project's conventions.
  • Synchronize with Source: Confirm your PR is synchronized with the ultralytics/yolov5 main branch. If it's behind, update it by clicking the 'Update branch' button or by running git pull and git merge main locally.
  • Ensure CI Checks Pass: Verify all Ultralytics Continuous Integration (CI) checks are passing. If any checks fail, please address the issues.
  • Update Documentation: Update the relevant documentation for any new or modified features.
  • Add Tests: If applicable, include or update tests to cover your changes, and confirm that all tests are passing.
  • Sign the CLA: Please ensure you have signed our Contributor License Agreement if this is your first Ultralytics PR by writing "I have read the CLA Document and I sign the CLA" in a new message.
  • Minimize Changes: Limit your changes to the minimum necessary for your bug fix or feature addition. "It is not daily increase but daily decrease, hack away the unessential. The closer to the source, the less wastage there is." — Bruce Lee

For more guidance, please refer to our Contributing Guide. Don't hesitate to leave a comment if you have any questions. Thank you for contributing to Ultralytics! 🚀

Copy link
Copy Markdown
Member

@UltralyticsAssistant UltralyticsAssistant left a comment

Choose a reason for hiding this comment

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

🔍 PR Review

Made with ❤️ by Ultralytics Actions

Good security-focused cleanup overall: the extension allowlist, image verification, and localhost default all move this example in the right direction. The two gaps to address are that invalid images currently bubble up as 500s, and the 16 MB limit is not enforced early enough to stop oversized multipart requests from being accepted.

💬 Posted 2 inline comments

Comment thread utils/flask_rest_api/restapi.py Outdated
Comment thread utils/flask_rest_api/restapi.py
@pderrenger
Copy link
Copy Markdown
Member

Thanks for the security hardening PR; before review, please add or point to a focused regression test for rejected non-image or oversized uploads and note the localhost bind behavior change in the PR description, as outlined in the Development Workflow.

@orbisai0security
Copy link
Copy Markdown
Contributor Author

Thanks, I’ve added focused Flask test-client regression coverage.

@pderrenger
Copy link
Copy Markdown
Member

Thanks for adding the regression tests; please also update the PR description with the local validation you ran and explicitly call out the default bind change to 127.0.0.1, since that changes prior remote access behavior for reviewers and users, as noted in the Development Workflow.

@glenn-jocher glenn-jocher changed the title fix: remove unsafe exec() in restapi.py fix: harden Flask REST API uploads May 2, 2026
Copy link
Copy Markdown
Member

@glenn-jocher glenn-jocher left a comment

Choose a reason for hiding this comment

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

Reviewed the final diff and follow-up maintainer commit. The upload hardening now catches malformed images as 400s, enforces Flask-level request size limits with JSON 413 responses, documents the localhost default bind behavior, and includes focused Flask test-client regression coverage. Local validation passed for the focused pytest file, py_compile, and ruff on touched files; CI is green.

@glenn-jocher glenn-jocher merged commit 00c14a2 into ultralytics:master May 2, 2026
9 checks passed
@glenn-jocher
Copy link
Copy Markdown
Member

glenn-jocher commented May 2, 2026

@orbisai0security thanks for the security hardening contribution. I merged this after adding one small maintainer follow-up so Flask-level oversized multipart rejections return the same JSON 413 response as the handler path, tightening the oversized-upload regression test, resolving the review threads, and updating the PR description with the local validation and 127.0.0.1 default bind behavior. CI is green across the YOLOv5 matrix.

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

Labels

bug Something isn't working fixed Bug has been resolved python Pull requests that update python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants