Skip to content
GHSA W3vv 5wxh Xg4h

GHSA W3vv 5wxh Xg4h

github.com September 10, 2026

Snipe-IT resolved a SAML-authenticated user by taking the SAML username attribute (or NameID when no mapping is configured) and running an Eloquent equality query against the users.username column. On MySQL/MariaDB the default collation for that column is utf8mb4_unicode_ci , which is both case-insensitive AND accent-insensitive. A signed SAML assertion for snípeitreport3 therefore resolved to the existing local Snipe-IT user snipeitreport3 , even though the two strings are different byte sequences and represent different IdP accounts. The SAML login path then authenticated the browser session as the wrong local Snipe-IT user, achieving account takeover.

The same class of bypass applied to any federated login path that hit the same WHERE username = ? shape (LDAP, REMOTE_USER , Google OAuth).

Already fixed in commit 2304066d79 on 2026-07-11 ("Auth: Fixed FD-56498 - check username case for non-local logins"). This advisory documents the vulnerability for CVE assignment and public disclosure once the fix has shipped in a tagged release.

High . CVSS 3.1 base score 8.1 with vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N .

Primary: CWE-178 (Improper Handling of Case Sensitivity) . The core defect: an authentication lookup treats byte-distinct strings as equivalent because the underlying database collation folds case and accents.

Related: CWE-287 (Improper Authentication) . Ultimate consequence: the wrong local account is authenticated.

Also relevant: CWE-706 (Use of Incorrectly-Resolved Name or Reference) . The name-to-account resolution step is the specific weakness.

Confirmed at Snipe-IT v8.6.3 (Docker image digest snipe/snipe-it@sha256:6476be7cca765880374a6d489d22ad43d3edba965ab3cb862bf828f5fc856e50 ). Likely affects all versions where the SAML login path ran a plain WHERE username = ? query and the database was configured with the default utf8mb4_unicode_ci collation (which has been the Snipe-IT default for many releases). Fixed on the develop branch in commit 2304066d79 . The first tagged release containing the fix will be filled in at publication.

Root cause: database collation on users.username

The migration that creates the username column does not force a byte-preserving collation:

( database/migrations/2014_11_20_203007_add_username_to_user.php:17 )

Snipe-IT's config/database.php defaults to utf8mb4_unicode_ci :

Under that collation, the database treats byte-distinct strings as equal:

app/Services/Saml.php::samlLogin() prior to the fix:

$username came from the attacker-controlled SAML username attribute (or NameID ), was substituted directly into the query, and MySQL / MariaDB's collation resolved the accented spelling to the plain-ASCII victim row. No byte-exact post-filter guarded the result before it was returned to the caller.

The returned row was trusted

LoginController::samlLogin() called Auth::login($user) on whatever samlLogin() returned, completing the session takeover.

Where the SAML username came from

Saml::getUsername() selects the NameID by default, then replaces it with the attribute named by saml_attr_mapping_username if that setting is configured:

Either path is attacker-controlled at the IdP.

Same class of bug applied to other federated login paths

LoginController and GoogleAuthController had structurally similar WHERE username = ? lookups that inherited the same collation folding. The fix commit closes all of them, not just the SAML path.

Reproduced by the researcher (whale120) against a fresh Snipe-IT v8.6.3 Docker deployment with a Keycloak IdP.

Snipe-IT snipe/snipe-it:v8.6.3

MariaDB 11.8, users.username collation utf8mb4_unicode_ci

Keycloak realm saml-collation-poc with self-registration enabled

Victim (existing local Snipe-IT account and matching IdP account):

Snipe-IT username snipeitreport3 (database id 4)

Full name "Snipe VictimThree"

Attacker registers a new Keycloak account with username snípeitreport3 (Latin small letter i with acute accent).

Attacker initiates SP-initiated SAML SSO at .

Keycloak issues a signed SAML response with: NameID : snípeitreport3 Attribute username : snípeitreport3

NameID : snípeitreport3

Attribute username : snípeitreport3

Snipe-IT ACS accepts the assertion, runs the vulnerable query, and returns the victim's local user row (id 4, snipeitreport3 ) because utf8mb4_unicode_ci folds the accent.

Auth::login($victimUser) completes the session takeover.

Attacker is redirected to /account/profile and sees "Snipe VictimThree".

Database state after the attack:

No local Snipe-IT account with that byte sequence exists. The attacker's session is nonetheless bound to snipeitreport3 (id 4).

Applied in commit 2304066d79 . Introduces a shared post-filter in App\Models\User :

Each federated login path ( Saml.php , LoginController , GoogleAuthController ) now runs its username lookup and then calls verifyExactUsernameMatch() before completing authentication. hash_equals() compares byte-for-byte in constant time, so the check does not leak timing information.

Post-fix Saml.php::samlLogin() :

Snipe-IT chose the post-filter approach over an ALTER TABLE ... COLLATE utf8mb4_bin migration because:

Changing the column collation would migrate every existing installation, requiring maintenance downtime for large deployments, and would silently break case-insensitive username display or patterns that admins may rely on today.

Keeping display and case-insensitive while making authentication byte-exact matches the reporter's alternative recommendation and preserves operator expectations.

The post-filter closes the specific attack vector (federated authentication paths that trust the collation-folded lookup) without changing every other query that touches the username column.

2026-07-02: Vulnerability discovered by whale120 during the DEVCORE Internship Program.

2026-07-11: Fix committed as 2304066d79 on the develop branch (internal ticket FD-56498).

Vulnerability reported by whale120 ( @whale120_tw ) working with the DEVCORE Internship Program. Internally tracked as FD-56498.

CWE-178: Improper Handling of Case Sensitivity

CWE-287: Improper Authentication

CWE-706: Use of Incorrectly-Resolved Name or Reference

MySQL / MariaDB utf8mb4_unicode_ci collation behavior