VYPR
Moderate severityNVD Advisory· Published Dec 11, 2025· Updated Dec 11, 2025

Miniflux 2 has an Open Redirect via protocol-relative `redirect_url`

CVE-2025-67713

Description

Miniflux 2 is an open source feed reader. Versions 2.2.14 and below treat redirect_url as safe when url.Parse(...).IsAbs() is false, enabling phishing flows after login. Protocol-relative URLs like //ikotaslabs.com have an empty scheme and pass that check, allowing post-login redirects to attacker-controlled sites. This issue is fixed in version 2.2.15.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
miniflux.app/v2Go
< 2.2.152.2.15

Affected products

1

Patches

1
76df99f3a3db

fix: only relative path should allowed for redirectURL parameter

https://github.com/miniflux/v2Frédéric GuillotOct 26, 2025via ghsa
3 files changed · +53 6
  • internal/ui/login_check.go+4 6 modified
    @@ -6,7 +6,6 @@ package ui // import "miniflux.app/v2/internal/ui"
     import (
     	"log/slog"
     	"net/http"
    -	"net/url"
     
     	"miniflux.app/v2/internal/config"
     	"miniflux.app/v2/internal/http/cookie"
    @@ -17,6 +16,7 @@ import (
     	"miniflux.app/v2/internal/ui/form"
     	"miniflux.app/v2/internal/ui/session"
     	"miniflux.app/v2/internal/ui/view"
    +	"miniflux.app/v2/internal/urllib"
     )
     
     func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) {
    @@ -96,11 +96,9 @@ func (h *handler) checkLogin(w http.ResponseWriter, r *http.Request) {
     		config.Opts.BasePath(),
     	))
     
    -	if redirectURL != "" {
    -		if parsedURL, err := url.Parse(redirectURL); err == nil && !parsedURL.IsAbs() {
    -			html.Redirect(w, r, redirectURL)
    -			return
    -		}
    +	if redirectURL != "" && urllib.IsRelativePath(redirectURL) {
    +		html.Redirect(w, r, redirectURL)
    +		return
     	}
     
     	html.Redirect(w, r, route.Path(h.router, user.DefaultHomePage))
    
  • internal/urllib/url.go+15 0 modified
    @@ -10,6 +10,21 @@ import (
     	"strings"
     )
     
    +// IsRelativePath returns true if the link is a relative path.
    +func IsRelativePath(link string) bool {
    +	if link == "" {
    +		return false
    +	}
    +	if parsedURL, err := url.Parse(link); err == nil {
    +		// Only allow relative paths (not scheme-relative URLs like //example.org)
    +		// and ensure the URL doesn't have a host component
    +		if !parsedURL.IsAbs() && parsedURL.Host == "" && parsedURL.Scheme == "" {
    +			return true
    +		}
    +	}
    +	return false
    +}
    +
     // IsAbsoluteURL returns true if the link is absolute.
     func IsAbsoluteURL(link string) bool {
     	u, err := url.Parse(link)
    
  • internal/urllib/url_test.go+34 0 modified
    @@ -5,6 +5,40 @@ package urllib // import "miniflux.app/v2/internal/urllib"
     
     import "testing"
     
    +func TestIsRelativePath(t *testing.T) {
    +	scenarios := map[string]bool{
    +		// Valid relative paths
    +		"path/to/file.ext":    true,
    +		"./path/to/file.ext":  true,
    +		"../path/to/file.ext": true,
    +		"file.ext":            true,
    +		"./file.ext":          true,
    +		"../file.ext":         true,
    +		"/absolute/path":      true,
    +		"path?query=value":    true,
    +		"path#fragment":       true,
    +		"path?query#fragment": true,
    +
    +		// Not relative paths
    +		"https://example.org/file.ext": false,
    +		"http://example.org/file.ext":  false,
    +		"//example.org/file.ext":       false,
    +		"//example.org":                false,
    +		"ftp://example.org/file.ext":   false,
    +		"mailto:user@example.org":      false,
    +		"magnet:?xt=urn:btih:example":  false,
    +		"":                             false,
    +		"magnet:?xt.1=urn:sha1:YNCKHTQCWBTRNJIV4WNAE52SJUQCZO5C": false,
    +	}
    +
    +	for input, expected := range scenarios {
    +		actual := IsRelativePath(input)
    +		if actual != expected {
    +			t.Errorf(`Unexpected result for IsRelativePath, got %v instead of %v for %q`, actual, expected, input)
    +		}
    +	}
    +}
    +
     func TestIsAbsoluteURL(t *testing.T) {
     	scenarios := map[string]bool{
     		"https://example.org/file.pdf": true,
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.