Skip to content

Unauthenticated Open Redirect via Thumbnail via-uri Endpoint (v2.25.1) #10247

Description

@geo-chen

Prerequisites

  • I have searched for related issues in the issues list.
  • This is an issue with the Halo project itself. If it is not an issue with the project itself(For example: Installation and deployment issues.), it is recommended to submit it in the Discussions.
  • I have tried disabling all plugins to rule out plugins as the cause of the problem.
  • If it is an issue with plugins and themes, please submit it in the respective plugin and theme repositories.

System information

reported via email on 15 June 2026.

What is the project operation method?

Docker

What happened?

I am writing to report an unauthenticated open redirect vulnerability in Halo v2.25.1 (the current latest release).

Affected endpoint:
GET /apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=<arbitrary>&size=<m|s|l|xl>

Root cause:
ThumbnailEndpoint.getThumbnailByUri passes the raw uri query parameter directly to DefaultThumbnailService.get(URI, ThumbnailSize). When no matching attachment is found, the endpoint falls back to .defaultIfEmpty(uri.get()) and issues a 302 Found to the original, unvalidated URI. The anonymous role explicitly grants get access to api.storage.halo.run/thumbnails/via-uri, so no authentication is required.

Reproduce Steps

Proof of concept (tested against halohub/halo:2.25.1):

# Start Halo
docker run -d --name halo-poc -p 8090:8090 halohub/halo:2.25.1
sleep 15

# Trigger unauthenticated open redirect
curl -v "http://localhost:8090/apis/api.storage.halo.run/v1alpha1/thumbnails/-/via-uri?uri=https://attacker.example.com/&size=m"

# Expected response:
# < HTTP/1.1 302 Found
# < Location: https://attacker.example.com/

Impact:
Any visitor can craft a link on a legitimate Halo domain that redirects to an attacker-controlled site, enabling phishing campaigns and potential OAuth token harvesting if the Halo domain is trusted in external identity providers.

Suggested fix:
Before issuing the redirect, validate that the resolved URI is either a relative path within the application or shares the same origin as the configured Halo external URL. If the URI refers to an unregistered external host, return a 400 Bad Request.

Relevant log output

Additional information

No response

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions