GHSA-gq4g-fpc9-vjfq: Webauthn SimpleFakeCredentialGenerator With An Empty Secret Vulnerability
LOWGHSA-gq4g-fpc9-vjfq is a LOW simplefakecredentialgenerator with an empty secret vulnerability (CWE-204: Observable Response Discrepancy) affecting Webauthn libraries in the Packagist ecosystem. The issue involves simplefakecredentialgenerator with an empty secret produces predictable fake credentials, weakening username enumeration protection. Remediation is available by upgrading affected packages to version 5.3.5.
GHSA-gq4g-fpc9-vjfq at a Glance
How to Fix GHSA-gq4g-fpc9-vjfq
To remediate this vulnerability, upgrade all affected Webauthn dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.
Upgrade web-auth/webauthn-lib to 5.3.5
Run the following command in your project directory to verify that all resolved dependencies use the patched release:
inspect dependencies for web-auth/webauthn-lib
How to Check if You Are Affected
To determine whether your application is affected by GHSA-gq4g-fpc9-vjfq, inspect your project dependencies for Webauthn:
inspect dependencies for web-auth/webauthn-lib
Analyze the terminal output to locate any version of Webauthn in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 5.3.5), your application is affected.
Note: Verify declared build manifests and deployed runtime container environments.
Technical Details
Vulnerability Mechanism & Technical Analysis
This vulnerability is classified under CWE-204: Observable Response Discrepancy, where the product provides different responses to incoming requests in a way that reveals internal state information to an unauthorized actor outside of the intended control sphere. In Webauthn, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.
Source Advisory Statement
GHSA-gq4g-fpc9-vjfq Affected Webauthn Versions
1 component(s)| Product / Package | Ecosystem | Affected Versions | Fixed Version |
|---|---|---|---|
|
web-auth/webauthn-lib
|
Packagist |
≥ 4.9.0
< 5.3.5
|
5.3.5
|
References
Frequently Asked Questions
What is GHSA-gq4g-fpc9-vjfq?
Which Webauthn versions are affected?
What version fixes GHSA-gq4g-fpc9-vjfq?
Is web-auth/webauthn-lib affected?
What CWE is associated with GHSA-gq4g-fpc9-vjfq?
How can I check Packagist dependencies for GHSA-gq4g-fpc9-vjfq?
Machine-readable OSV JSON
OSV v1.5 Schema
{
"schema_version" : "1.4.0",
"id" : "GHSA-gq4g-fpc9-vjfq",
"modified" : "2026-07-07T23:40:01Z",
"published" : "2026-07-07T23:39:43Z",
"aliases" : [ ],
"summary" : "Webauthn: SimpleFakeCredentialGenerator with an empty secret produces predictable fake credentials, weakening username enumeration protection",
"details" : "## Impact\n\n`Webauthn\\SimpleFakeCredentialGenerator` is the library-provided default implementation of the `FakeCredentialGenerator` interface. It returns a stable list of decoy `PublicKeyCredentialDescriptor` objects for a given username so that an assertion request for an unknown user looks the same as a request for a real one, which mitigates username enumeration.\n\nThe generator derives the whole decoy list from a single seed:\n\n```php\n$seed = hash('sha256', $username . $this->secret, true);\n```\n\nWhen it is constructed without a secret (its constructor default, `$secret = ''`), the seed depends only on the username. The username is attacker-chosen and the algorithm is public, so an unauthenticated requester can recompute the exact, byte-for-byte decoy list the server returns for any username. The attacker then compares a probed username's response against the locally computed list and decides whether the account is real or fake, which is precisely the distinction the mechanism is meant to hide.\n\nWith any non-empty secret the seed becomes a value the attacker cannot evaluate and the mitigation holds. The defect is the empty default, not the algorithm.\n\n## Affected configurations\n\n- Direct use of the library (`web-auth/webauthn-lib`) where `SimpleFakeCredentialGenerator` is instantiated without a secret.\n- Any integration that wires the generator with an empty secret.\n\nThe Symfony bundle is not affected with its default configuration: it injects the application secret (`kernel.secret`) into the generator, so out-of-the-box deployments already use a non-empty secret. Deployments that set an empty `kernel.secret` are affected.\n\n## Patches\n\nFixed in 5.3.5. The generator now emits a deprecation when it is constructed without a secret, which surfaces the misconfiguration in logs and the Symfony profiler. A non-empty secret will be required in 6.0.0. The recommended remediation is to always provide a non-empty, deployment-specific secret.\n\n## Workarounds\n\nConstruct `SimpleFakeCredentialGenerator` with a non-empty secret value (for example the application secret), or provide a custom `FakeCredentialGenerator` implementation seeded with a secret.\n\n## Proof of concept\n\n```php\n<?php\ndeclare(strict_types=1);\n\nrequire $src . '/PublicKeyCredentialDescriptor.php';\nrequire $src . '/FakeCredentialGenerator.php';\nrequire $src . '/SimpleFakeCredentialGenerator.php';\n\nuse Webauthn\\PublicKeyCredentialDescriptor;\nuse Webauthn\\SimpleFakeCredentialGenerator;\n\n$username = 'alice@example.com';\n\n// 1. The \"server\" runs the library default wiring (cache=null, secret='').\n$server = new SimpleFakeCredentialGenerator();\n$refl = new ReflectionMethod(SimpleFakeCredentialGenerator::class, 'generateCredentials');\n$refl->setAccessible(true);\n$serverDescriptors = $refl->invoke($server, $username);\n\n// 2. The \"attacker\" recomputes the same algorithm, knowing only the username.\nfunction attackerRecompute(string $username): array {\n $transports = [\n PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_USB,\n PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_NFC,\n PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_BLE,\n PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_HYBRID,\n PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_INTERNAL,\n PublicKeyCredentialDescriptor::AUTHENTICATOR_TRANSPORT_SMART_CARD,\n ];\n $seed = hash('sha256', $username . '', true); // empty secret\n $count = (ord($seed[0]) % 3) + 1;\n $out = [];\n for ($i = 0; $i < $count; $i++) {\n $credSeed = hash('sha256', $seed . pack('N', $i), true);\n $transportCount = (ord($credSeed[0]) % 2) + 1;\n $sel = [];\n for ($j = 0; $j < $transportCount; $j++) {\n $sel[] = $transports[ord($credSeed[$j + 1]) % count($transports)];\n }\n $sel = array_values(array_unique($sel));\n $out[] = ['type' => PublicKeyCredentialDescriptor::CREDENTIAL_TYPE_PUBLIC_KEY,\n 'id' => hash('sha256', $credSeed . $username), 'transports' => $sel];\n }\n return $out;\n}\n\n// 3. The two lists match byte-for-byte, so the decoy is reproducible.\n// The same call with a non-empty secret diverges, confirming the defect\n// is the default value rather than the algorithm.\n```\n\nWith the default empty secret the library's fake-credential list is bit-for-bit reproducible from the public username alone, which defeats the username enumeration mitigation. The same call with a non-empty secret diverges.\n\n## Severity\n\nLow. The decoy responses are still well-formed and the issue only re-enables username enumeration, and only when the generator is used without a secret (which is not the case for default Symfony bundle deployments).\n\n## Credits\n\nFound during an internal security audit of the project.",
"severity" : [ {
"type" : "CVSS_V4",
"score" : "CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:N/SI:N/SA:N/E:P"
} ],
"affected" : [ {
"package" : {
"ecosystem" : "Packagist",
"name" : "web-auth/webauthn-lib"
},
"ranges" : [ {
"type" : "ECOSYSTEM",
"events" : [ {
"introduced" : "4.9.0"
}, {
"fixed" : "5.3.5"
} ]
} ]
} ],
"references" : [ {
"type" : "WEB",
"url" : "https://github.com/web-auth/webauthn-framework/security/advisories/GHSA-gq4g-fpc9-vjfq"
}, {
"type" : "PACKAGE",
"url" : "https://github.com/web-auth/webauthn-framework"
} ],
"database_specific" : {
"cwe_ids" : [ "CWE-204", "CWE-330" ],
"severity" : "LOW",
"github_reviewed" : true,
"github_reviewed_at" : "2026-07-07T23:39:43Z",
"nvd_published_at" : null
}
}