Every CVESearch/Get API key

GHSA-r4v7-6wcg-ghj5

FileBrowser: Missing Rate Limiting on Authentication Endpoint Enables Brute Force Attacks

6.5 MediumFix available

GHSA-r4v7-6wcg-ghj5 is a medium vulnerability (CVSS 6.5) in github.com/gtsteffaniak/filebrowser, published June 25, 2026. No source lists public exploit code. Fixed in github.com/gtsteffaniak/filebrowser 0.0.0-20260522161427-fa5abc8c67f3a.

What does this mean?
Severity
6.5 MediumCVSS 3.1, GitHub Advisories
Exploit chance
UnscoredNo EPSS score yet
Exploitation
None knownNot on CISA’s or ENISA’s lists
Fixed in
0.0.0-20260522161427-fa5abc8c67f3agithub.com/gtsteffaniak/filebrowser +1 more

Description

Summary

The /api/auth/login endpoint does not implement rate limiting, account lockout, or progressive backoff for repeated authentication failures. As a result, an attacker can perform unlimited login attempts against the endpoint. When combined with the username enumeration timing vulnerability, valid accounts can be identified and then brute-forced without restriction. The risk is further increased by a weak default password policy that only enforces a minimum length of five characters.

Details

The authentication endpoint /api/auth/login does not enforce any form of rate limiting, account lockout, or progressive backoff for repeated failed login attempts. Testing confirmed that the endpoint accepts an unlimited number of authentication attempts from the same client without delay or restriction.

This allows attackers to repeatedly attempt password guesses against valid usernames.

Secure authentication systems typically enforce request throttling, temporary account lockout, or progressive delays after repeated failed login attempts to mitigate brute-force attacks.

$ python rate-limit-probe.py
[*] Probing http://localhost/api/auth/login for rate limiting, lockout, and backoff behavior...
    Attempt  10: status=401, latency=0.0411s
    Attempt  20: status=401, latency=0.0411s
    Attempt  30: status=401, latency=0.0402s
    Attempt  40: status=401, latency=0.0420s
    Attempt  50: status=401, latency=0.0403s
    Attempt  60: status=401, latency=0.0423s
    Attempt  70: status=401, latency=0.0474s
    Attempt  80: status=401, latency=0.0417s
    Attempt  90: status=401, latency=0.0407s
    Attempt 100: status=401, latency=0.0407s

--- CONCRETE EVIDENCE ---
Attempts completed:        100
Total runtime:             4.17s
Average request rate:      23.98 req/sec
Unique status codes:       [401]
Average time (first 5):    0.0447s
Average time (last 5):     0.0408s
Latency delta:             -0.0038s
[RESULT] No HTTP 429 responses observed.
[RESULT] No progressive backoff detected: response timing remained effectively constant.

Additional Context

Password validation is implemented in backend/database/storage/bolt/user.go via checkPassword(), which only verifies that the supplied password length is greater than or equal to settings.Config.Auth.Methods.PasswordAuth.MinLength. In backend/common/settings/auth.go, the PasswordAuthConfig documents the default value of MinLength as 5. No additional complexity requirements, such as uppercase, lowercase, numeric, or special character checks, were identified in this code path.

PoC

The script below demonstrates the lack of rate limiting by performing a high volume automated authentication test. The script sends sequential login requests and monitors for HTTP 429 (Too Many Requests) status codes.

import requests
import time
import statistics

URL = "http://localhost/api/auth/login"
USERNAME = "admin"
PASSWORD = "wrong-password"
MAX_ATTEMPTS = 100
TIMEOUT = 10

latencies = []
statuses = []

print(f"[*] Probing {URL} for rate limiting, lockout, and backoff behavior...")

start_total = time.time()

for i in range(1, MAX_ATTEMPTS + 1):
    start = time.perf_counter()

    resp = requests.post(
        URL,
        params={"username": USERNAME, "recaptcha": ""},
        headers={"X-Password": PASSWORD},
        timeout=TIMEOUT
    )

    duration = time.perf_counter() - start
    latencies.append(duration)
    statuses.append(resp.status_code)

    if resp.status_code == 429:
        print(f"[!] Rate limit detected at attempt {i} (HTTP 429)")
        break

    if i % 10 == 0:
        print(f"    Attempt {i:3}: status={resp.status_code}, latency={duration:.4f}s")

end_total = time.time()
attempts_completed = len(latencies)

print("\n--- CONCRETE EVIDENCE ---")

first_five_avg = statistics.mean(latencies[:5]) if attempts_completed >= 5 else statistics.mean(latencies)
last_five_avg = statistics.mean(latencies[-5:]) if attempts_completed >= 5 else statistics.mean(latencies)
latency_delta = last_five_avg - first_five_avg

print(f"Attempts completed:        {attempts_completed}")
print(f"Total runtime:             {end_total - start_total:.2f}s")
print(f"Average request rate:      {attempts_completed / (end_total - start_total):.2f} req/sec")
print(f"Unique status codes:       {sorted(set(statuses))}")
print(f"Average time (first 5):    {first_five_avg:.4f}s")
print(f"Average time (last 5):     {last_five_avg:.4f}s")
print(f"Latency delta:             {latency_delta:+.4f}s")

if 429 not in statuses:
    print("[RESULT] No HTTP 429 responses observed.")

if abs(latency_delta) < 0.05:
    print("[RESULT] No progressive backoff detected: response timing remained effectively constant.")
else:
    print("[RESULT] Latency variation detected: investigate possible throttling or environmental noise.")

Impact

An attacker can perform unlimited authentication attempts against valid usernames. When combined with the username enumeration timing vulnerability, this enables targeted brute-force attacks against user accounts and increases the likelihood of credential compromise.

Please let me know if you need any additional information or clarification. I'm happy to assist with testing or validating a fix.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
Low
Integrity
Low
Availability
None

Affected packages

Affected packages
PackageAffectedFixed
github.com/gtsteffaniak/filebrowser
Go
before 0.0.0-20260522161427-fa5abc8c67f3a
0.0.0-20260522161427-fa5abc8c67f3a
github.com/gtsteffaniak/filebrowser
Go
All versionsNone known

What each source reports

GitHub Advisories Score used6.5

FileBrowser: Missing Rate Limiting on Authentication Endpoint Enables Brute Force Attacks

Summary

The /api/auth/login endpoint does not implement rate limiting, account lockout, or progressive backoff for repeated authentication failures. As a result, an attacker can perform unlimited login attempts against the endpoint. When combined with the username enumeration timing vulnerability, valid accounts can be identified and then brute-forced without restriction. The risk is further increased by a weak default password policy that only enforces a minimum length of five characters.

Details

The authentication endpoint /api/auth/login does not enforce any form of rate limiting, account lockout, or progressive backoff for repeated failed login attempts. Testing confirmed that the endpoint accepts an unlimited number of authentication attempts from the same client without delay or restriction.

This allows attackers to repeatedly attempt password guesses against valid usernames.

Secure authentication systems typically enforce request throttling, temporary account lockout, or progressive delays after repeated failed login attempts to mitigate brute-force attacks.

$ python rate-limit-probe.py
[*] Probing http://localhost/api/auth/login for rate limiting, lockout, and backoff behavior...
    Attempt  10: status=401, latency=0.0411s
    Attempt  20: status=401, latency=0.0411s
    Attempt  30: status=401, latency=0.0402s
    Attempt  40: status=401, latency=0.0420s
    Attempt  50: status=401, latency=0.0403s
    Attempt  60: status=401, latency=0.0423s
    Attempt  70: status=401, latency=0.0474s
    Attempt  80: status=401, latency=0.0417s
    Attempt  90: status=401, latency=0.0407s
    Attempt 100: status=401, latency=0.0407s

--- CONCRETE EVIDENCE ---
Attempts completed:        100
Total runtime:             4.17s
Average request rate:      23.98 req/sec
Unique status codes:       [401]
Average time (first 5):    0.0447s
Average time (last 5):     0.0408s
Latency delta:             -0.0038s
[RESULT] No HTTP 429 responses observed.
[RESULT] No progressive backoff detected: response timing remained effectively constant.

Additional Context

Password validation is implemented in backend/database/storage/bolt/user.go via checkPassword(), which only verifies that the supplied password length is greater than or equal to settings.Config.Auth.Methods.PasswordAuth.MinLength. In backend/common/settings/auth.go, the PasswordAuthConfig documents the default value of MinLength as 5. No additional complexity requirements, such as uppercase, lowercase, numeric, or special character checks, were identified in this code path.

PoC

The script below demonstrates the lack of rate limiting by performing a high volume automated authentication test. The script sends sequential login requests and monitors for HTTP 429 (Too Many Requests) status codes.

import requests
import time
import statistics

URL = "http://localhost/api/auth/login"
USERNAME = "admin"
PASSWORD = "wrong-password"
MAX_ATTEMPTS = 100
TIMEOUT = 10

latencies = []
statuses = []

print(f"[*] Probing {URL} for rate limiting, lockout, and backoff behavior...")

start_total = time.time()

for i in range(1, MAX_ATTEMPTS + 1):
    start = time.perf_counter()

    resp = requests.post(
        URL,
        params={"username": USERNAME, "recaptcha": ""},
        headers={"X-Password": PASSWORD},
        timeout=TIMEOUT
    )

    duration = time.perf_counter() - start
    latencies.append(duration)
    statuses.append(resp.status_code)

    if resp.status_code == 429:
        print(f"[!] Rate limit detected at attempt {i} (HTTP 429)")
        break

    if i % 10 == 0:
        print(f"    Attempt {i:3}: status={resp.status_code}, latency={duration:.4f}s")

end_total = time.time()
attempts_completed = len(latencies)

print("\n--- CONCRETE EVIDENCE ---")

first_five_avg = statistics.mean(latencies[:5]) if attempts_completed >= 5 else statistics.mean(latencies)
last_five_avg = statistics.mean(latencies[-5:]) if attempts_completed >= 5 else…
Record
GHSA-r4v7-6wcg-ghj5
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-307
Updated
2026-11-02
OSV6.5

FileBrowser: Missing Rate Limiting on Authentication Endpoint Enables Brute Force Attacks

Summary

The /api/auth/login endpoint does not implement rate limiting, account lockout, or progressive backoff for repeated authentication failures. As a result, an attacker can perform unlimited login attempts against the endpoint. When combined with the username enumeration timing vulnerability, valid accounts can be identified and then brute-forced without restriction. The risk is further increased by a weak default password policy that only enforces a minimum length of five characters.

Details

The authentication endpoint /api/auth/login does not enforce any form of rate limiting, account lockout, or progressive backoff for repeated failed login attempts. Testing confirmed that the endpoint accepts an unlimited number of authentication attempts from the same client without delay or restriction.

This allows attackers to repeatedly attempt password guesses against valid usernames.

Secure authentication systems typically enforce request throttling, temporary account lockout, or progressive delays after repeated failed login attempts to mitigate brute-force attacks.

$ python rate-limit-probe.py
[*] Probing http://localhost/api/auth/login for rate limiting, lockout, and backoff behavior...
    Attempt  10: status=401, latency=0.0411s
    Attempt  20: status=401, latency=0.0411s
    Attempt  30: status=401, latency=0.0402s
    Attempt  40: status=401, latency=0.0420s
    Attempt  50: status=401, latency=0.0403s
    Attempt  60: status=401, latency=0.0423s
    Attempt  70: status=401, latency=0.0474s
    Attempt  80: status=401, latency=0.0417s
    Attempt  90: status=401, latency=0.0407s
    Attempt 100: status=401, latency=0.0407s

--- CONCRETE EVIDENCE ---
Attempts completed:        100
Total runtime:             4.17s
Average request rate:      23.98 req/sec
Unique status codes:       [401]
Average time (first 5):    0.0447s
Average time (last 5):     0.0408s
Latency delta:             -0.0038s
[RESULT] No HTTP 429 responses observed.
[RESULT] No progressive backoff detected: response timing remained effectively constant.

Additional Context

Password validation is implemented in backend/database/storage/bolt/user.go via checkPassword(), which only verifies that the supplied password length is greater than or equal to settings.Config.Auth.Methods.PasswordAuth.MinLength. In backend/common/settings/auth.go, the PasswordAuthConfig documents the default value of MinLength as 5. No additional complexity requirements, such as uppercase, lowercase, numeric, or special character checks, were identified in this code path.

PoC

The script below demonstrates the lack of rate limiting by performing a high volume automated authentication test. The script sends sequential login requests and monitors for HTTP 429 (Too Many Requests) status codes.

import requests
import time
import statistics

URL = "http://localhost/api/auth/login"
USERNAME = "admin"
PASSWORD = "wrong-password"
MAX_ATTEMPTS = 100
TIMEOUT = 10

latencies = []
statuses = []

print(f"[*] Probing {URL} for rate limiting, lockout, and backoff behavior...")

start_total = time.time()

for i in range(1, MAX_ATTEMPTS + 1):
    start = time.perf_counter()

    resp = requests.post(
        URL,
        params={"username": USERNAME, "recaptcha": ""},
        headers={"X-Password": PASSWORD},
        timeout=TIMEOUT
    )

    duration = time.perf_counter() - start
    latencies.append(duration)
    statuses.append(resp.status_code)

    if resp.status_code == 429:
        print(f"[!] Rate limit detected at attempt {i} (HTTP 429)")
        break

    if i % 10 == 0:
        print(f"    Attempt {i:3}: status={resp.status_code}, latency={duration:.4f}s")

end_total = time.time()
attempts_completed = len(latencies)

print("\n--- CONCRETE EVIDENCE ---")

first_five_avg = statistics.mean(latencies[:5]) if attempts_completed >= 5 else statistics.mean(latencies)
last_five_avg = statistics.mean(latencies[-5:]) if attempts_completed >= 5 else…
Record
GHSA-r4v7-6wcg-ghj5
CVSS 3.1
6.5 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Weakness
CWE-307
Updated
2026-11-02
OSVGO-2026-5776No score

FileBrowser: Missing Rate Limiting on Authentication Endpoint Enables Brute Force Attacks in github.com/gtsteffaniak/filebrowser

FileBrowser: Missing Rate Limiting on Authentication Endpoint Enables Brute Force Attacks in github.com/gtsteffaniak/filebrowser.

NOTE: The source advisory for this report contains additional versions that could not be automatically mapped to standard Go module versions.

(If this is causing false-positive reports from vulnerability scanners, please suggest an edit to the report.)

The additional affected modules and versions are: github.com/gtsteffaniak/filebrowser before v0.0.0-20260522161427-fa5abc8c67f3a.

Record
GO-2026-5776
Updated
2026-11-02

History

History
RecordedChangedSources
first indexedGitHub Advisories, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open