{
    "document": {
        "category": "csaf_base",
        "csaf_version": "2.0",
        "distribution": {
            "tlp": {
                "label": "WHITE"
            }
        },
        "lang": "en",
        "notes": [
            {
                "category": "legal_disclaimer",
                "text": "The Netherlands Cyber Security Center (henceforth: NCSC-NL) maintains this portal to enhance access to its information and vulnerabilities. The use of this information is subject to the following terms and conditions:\n\nThe vulnerabilities disclosed in this portal are gathered by NCSC-NL from a variety of open sources, which the user can retrieve from other platforms. NCSC-NL makes every reasonable effort to ensure that the content of this portal is kept up to date, and that it is accurate and complete. Nevertheless, NCSC-NL cannot entirely rule out the possibility of errors, and therefore cannot give any warranty in respect of its completeness, accuracy or real-time keeping up-to-date. NCSC-NL does not control nor guarantee the accuracy, relevance, timeliness or completeness of information obtained from these external sources. The vulnerabilities disclosed in this portal are intended solely for the convenience of professional parties to take appropriate measures to manage the risks posed to the cybersecurity. No rights can be derived from the information provided therein.\n\nNCSC-NL and the Kingdom of the Netherlands assume no legal liability or responsibility for any damage resulting from either the use or inability of use of the vulnerabilities disclosed in this portal. This includes damage resulting from the inaccuracy of incompleteness of the information contained in it.\nThe information on this page is subject to Dutch law. All disputes related to or arising from the use of this portal regarding the disclosure of vulnerabilities will be submitted to the competent court in The Hague. This choice of means also applies to the court in summary proceedings."
            }
        ],
        "publisher": {
            "category": "coordinator",
            "contact_details": "cert@ncsc.nl",
            "name": "National Cyber Security Centre",
            "namespace": "https://www.ncsc.nl/"
        },
        "title": "CVE-2026-31888",
        "tracking": {
            "current_release_date": "2026-03-23T11:03:13.309802Z",
            "generator": {
                "date": "2026-02-17T15:00:00Z",
                "engine": {
                    "name": "V.E.L.M.A",
                    "version": "1.7"
                }
            },
            "id": "CVE-2026-31888",
            "initial_release_date": "2026-03-11T19:27:36.778254Z",
            "revision_history": [
                {
                    "date": "2026-03-11T19:27:36.778254Z",
                    "number": "1",
                    "summary": "CVE created.| Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (1).| CWES updated (1)."
                },
                {
                    "date": "2026-03-11T19:27:44.406711Z",
                    "number": "2",
                    "summary": "NCSC Score created."
                },
                {
                    "date": "2026-03-11T19:39:03.152743Z",
                    "number": "3",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| Products connected (3).| Products created (1).| References created (1).| CWES updated (1)."
                },
                {
                    "date": "2026-03-11T19:39:05.292904Z",
                    "number": "4",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-11T20:00:45.171889Z",
                    "number": "5",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (2).| CWES updated (1)."
                },
                {
                    "date": "2026-03-11T20:00:47.257921Z",
                    "number": "6",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-11T21:56:44.237859Z",
                    "number": "7",
                    "summary": "References created (1)."
                },
                {
                    "date": "2026-03-12T14:57:30.668195Z",
                    "number": "8",
                    "summary": "Source created.| CVE status created. (valid)| EPSS created."
                },
                {
                    "date": "2026-03-12T14:57:33.091686Z",
                    "number": "9",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-12T20:38:49.087107Z",
                    "number": "10",
                    "summary": "Unknown change."
                },
                {
                    "date": "2026-03-16T21:24:53.812241Z",
                    "number": "11",
                    "summary": "Products connected (2).| Product Identifiers created (2)."
                },
                {
                    "date": "2026-03-16T21:24:56.031458Z",
                    "number": "12",
                    "summary": "NCSC Score updated."
                },
                {
                    "date": "2026-03-19T15:30:40.576273Z",
                    "number": "13",
                    "summary": "Source created.| CVE status created. (valid)| Description created for source.| CVSS created.| References created (3).| CWES updated (1)."
                },
                {
                    "date": "2026-03-20T09:32:23.762117Z",
                    "number": "14",
                    "summary": "Source connected.| CVE status created. (valid)| EPSS created."
                },
                {
                    "date": "2026-03-20T09:32:26.975341Z",
                    "number": "15",
                    "summary": "NCSC Score updated."
                }
            ],
            "status": "interim",
            "version": "15"
        }
    },
    "product_tree": {
        "branches": [
            {
                "branches": [
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/<6.6.10.15",
                                "product": {
                                    "name": "vers:unknown/<6.6.10.15",
                                    "product_id": "CSAFPID-5798757"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=6.7.0.0|<6.7.8.1",
                                "product": {
                                    "name": "vers:unknown/>=6.7.0.0|<6.7.8.1",
                                    "product_id": "CSAFPID-5798756"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "core"
                    },
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/<6.6.10.14",
                                "product": {
                                    "name": "vers:unknown/<6.6.10.14",
                                    "product_id": "CSAFPID-5798764"
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=6.7.0.0|<6.7.8.1",
                                "product": {
                                    "name": "vers:unknown/>=6.7.0.0|<6.7.8.1",
                                    "product_id": "CSAFPID-5798758"
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "platform"
                    },
                    {
                        "branches": [
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/<6.6.10.15",
                                "product": {
                                    "name": "vers:unknown/<6.6.10.15",
                                    "product_id": "CSAFPID-5830366",
                                    "product_identification_helper": {
                                        "cpe": "cpe:2.3:a:shopware:shopware:*:*:*:*:*:*:*:*"
                                    }
                                }
                            },
                            {
                                "category": "product_version_range",
                                "name": "vers:unknown/>=6.7.0.0|<6.7.8.1",
                                "product": {
                                    "name": "vers:unknown/>=6.7.0.0|<6.7.8.1",
                                    "product_id": "CSAFPID-5830367",
                                    "product_identification_helper": {
                                        "cpe": "cpe:2.3:a:shopware:shopware:*:*:*:*:*:*:*:*"
                                    }
                                }
                            }
                        ],
                        "category": "product_name",
                        "name": "shopware"
                    }
                ],
                "category": "vendor",
                "name": "shopware"
            }
        ]
    },
    "vulnerabilities": [
        {
            "cve": "CVE-2026-31888",
            "cwe": {
                "id": "CWE-204",
                "name": "Observable Response Discrepancy"
            },
            "notes": [
                {
                    "category": "description",
                    "text": "Shopware is an open commerce platform. Prior to 6.7.8.1 and 6.6.10.15, the Store API login endpoint (POST /store-api/account/login) returns different error codes depending on whether the submitted email address belongs to a registered customer (CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS) or is unknown (CHECKOUT__CUSTOMER_NOT_FOUND). The \"not found\" response also echoes the probed email address. This allows an unauthenticated attacker to enumerate valid customer accounts. The storefront login controller correctly unifies both error paths, but the Store API does not — indicating an inconsistent defense. This vulnerability is fixed in 6.7.8.1 and 6.6.10.15.",
                    "title": "nvd - https://nvd.nist.gov/vuln/detail/CVE-2026-31888"
                },
                {
                    "category": "description",
                    "text": "Shopware is an open commerce platform. Prior to 6.7.8.1 and 6.6.10.15, the Store API login endpoint (POST /store-api/account/login) returns different error codes depending on whether the submitted email address belongs to a registered customer (CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS) or is unknown (CHECKOUT__CUSTOMER_NOT_FOUND). The \"not found\" response also echoes the probed email address. This allows an unauthenticated attacker to enumerate valid customer accounts. The storefront login controller correctly unifies both error paths, but the Store API does not — indicating an inconsistent defense. This vulnerability is fixed in 6.7.8.1 and 6.6.10.15.",
                    "title": "cveprojectv5 - https://www.cve.org/CVERecord?id=CVE-2026-31888"
                },
                {
                    "category": "description",
                    "text": "## Summary\n\nThe Store API login endpoint (`POST /store-api/account/login`) returns different error codes depending on whether the submitted email address belongs to a registered customer (`CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS`) or is unknown (`CHECKOUT__CUSTOMER_NOT_FOUND`). The \"not found\" response also echoes the probed email address. This allows an unauthenticated attacker to enumerate valid customer accounts. The storefront login controller correctly unifies both error paths, but the Store API does not — indicating an inconsistent defense.\n\n## CWE\n\n- **CWE-204**: Observable Response Discrepancy\n\n## Description\n\n### Distinct error codes leak account existence\n\nThe login flow in `AccountService::getCustomerByLogin()` calls `getCustomerByEmail()` first, which throws `CustomerNotFoundException` if the email is not found. If the email IS found but the password is wrong, a separate `BadCredentialsException` is thrown:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/AccountService.php:116-145\npublic function getCustomerByLogin(string $email, string $password, SalesChannelContext $context): CustomerEntity\n{\n    if ($this->isPasswordTooLong($password)) {\n        throw CustomerException::badCredentials();\n    }\n\n    $customer = $this->getCustomerByEmail($email, $context);\n    // ↑ Throws CustomerNotFoundException with CHECKOUT__CUSTOMER_NOT_FOUND if email unknown\n\n    if ($customer->hasLegacyPassword()) {\n        if (!$this->legacyPasswordVerifier->verify($password, $customer)) {\n            throw CustomerException::badCredentials();\n            // ↑ Throws BadCredentialsException with CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS\n        }\n        // ...\n    }\n\n    if ($customer->getPassword() === null\n        || !password_verify($password, $customer->getPassword())) {\n        throw CustomerException::badCredentials();\n        // ↑ Same: CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS\n    }\n    // ...\n}\n```\n\nThe two exception types produce clearly distinguishable API responses:\n\n**Email not registered:**\n```json\n{\n  \"errors\": [{\n    \"status\": \"401\",\n    \"code\": \"CHECKOUT__CUSTOMER_NOT_FOUND\",\n    \"detail\": \"No matching customer for the email \\\"probe@example.com\\\" was found.\",\n    \"meta\": { \"parameters\": { \"email\": \"probe@example.com\" } }\n  }]\n}\n```\n\n**Email registered, wrong password:**\n```json\n{\n  \"errors\": [{\n    \"status\": \"401\",\n    \"code\": \"CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS\",\n    \"detail\": \"Invalid username and/or password.\"\n  }]\n}\n```\n\n### Storefront is protected — Store API is not\n\nThe storefront login controller demonstrates that Shopware's developers are aware of this risk class. `AuthController::login()` catches both exceptions together and returns a generic error:\n\n```php\n// src/Storefront/Controller/AuthController.php:203\n} catch (BadCredentialsException|CustomerNotFoundException) {\n    // Unified handling — no distinction exposed to the user\n}\n```\n\nThe Store API `LoginRoute::login()` does NOT catch these exceptions. They propagate to the global `ErrorResponseFactory`, which serializes the distinct error codes into the JSON response:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/LoginRoute.php:54-58\n$token = $this->accountService->loginByCredentials(\n    $email,\n    (string) $data->get('password'),\n    $context\n);\n// No try/catch — exceptions propagate with distinct codes\n```\n\nThis inconsistency confirms the Store API exposure is an oversight, not a design decision.\n\n### Rate limiting is present but insufficient for enumeration\n\nThe login route has rate limiting (LoginRoute.php:47-51) keyed on `strtolower($email) . '-' . $clientIp`. This slows bulk enumeration but does not prevent it because:\n\n1. The attacker only needs **one request per email** to determine existence\n2. The rate limit key includes the IP, so rotating IPs resets the counter\n3. The rate limiter is designed to prevent brute-force password guessing, not single-probe enumeration\n\n## Impact\n\n- **Customer email enumeration**: An attacker can confirm whether specific email addresses are registered as customers, enabling targeted attacks\n- **Phishing enablement**: Confirmed customer emails can be targeted with store-specific phishing campaigns (e.g., fake order confirmations, password reset lures)\n- **Credential stuffing optimization**: Attackers with breached credential databases can first filter for valid emails before attempting password guesses, improving efficiency against rate limits\n- **Privacy violation**: Confirms an individual's association with a specific store, which may be sensitive depending on the store's nature (e.g., medical supplies, adult products)\n- **Email reflection**: The `CHECKOUT__CUSTOMER_NOT_FOUND` response echoes the probed email in the `detail` and `meta.parameters.email` fields, which could be leveraged in reflected content attacks\n\n## Recommended Remediation\n\n### Option 1: Catch both exceptions in LoginRoute and throw a unified error (Preferred)\n\nApply the same pattern already used in the storefront controller:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/LoginRoute.php\npublic function login(#[\\SensitiveParameter] RequestDataBag $data, SalesChannelContext $context): ContextTokenResponse\n{\n    EmailIdnConverter::encodeDataBag($data);\n    $email = (string) $data->get('email', $data->get('username'));\n\n    if ($this->requestStack->getMainRequest() !== null) {\n        $cacheKey = strtolower($email) . '-' . $this->requestStack->getMainRequest()->getClientIp();\n\n        try {\n            $this->rateLimiter->ensureAccepted(RateLimiter::LOGIN_ROUTE, $cacheKey);\n        } catch (RateLimitExceededException $exception) {\n            throw CustomerException::customerAuthThrottledException($exception->getWaitTime(), $exception);\n        }\n    }\n\n    try {\n        $token = $this->accountService->loginByCredentials(\n            $email,\n            (string) $data->get('password'),\n            $context\n        );\n    } catch (CustomerNotFoundException) {\n        // Normalize to the same exception as bad credentials\n        throw CustomerException::badCredentials();\n    }\n\n    if (isset($cacheKey)) {\n        $this->rateLimiter->reset(RateLimiter::LOGIN_ROUTE, $cacheKey);\n    }\n\n    return new ContextTokenResponse($token);\n}\n```\n\nThis ensures both \"not found\" and \"bad credentials\" return the same `CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS` code and generic message.\n\n### Option 2: Unify at the AccountService layer\n\nFor defense in depth, change `AccountService::getCustomerByLogin()` to throw `BadCredentialsException` instead of letting `CustomerNotFoundException` propagate:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/AccountService.php\npublic function getCustomerByLogin(string $email, string $password, SalesChannelContext $context): CustomerEntity\n{\n    if ($this->isPasswordTooLong($password)) {\n        throw CustomerException::badCredentials();\n    }\n\n    try {\n        $customer = $this->getCustomerByEmail($email, $context);\n    } catch (CustomerNotFoundException) {\n        throw CustomerException::badCredentials();\n    }\n\n    // ... rest of password verification\n}\n```\n\nThis protects all callers of `getCustomerByLogin()` regardless of how they handle exceptions. Note: `getCustomerByEmail()` is also called independently (e.g., password recovery), so that method should continue to throw `CustomerNotFoundException` for internal use — the normalization should happen at the login boundary.\n\n### Additional: Fix registration endpoint\n\nThe registration endpoint (`POST /store-api/account/register`) also leaks email existence via `CUSTOMER_EMAIL_NOT_UNIQUE`. For complete remediation, consider returning a generic success response and sending a notification email to the existing address instead.\n\n## Credit\n\nThis vulnerability was discovered and reported by [bugbunny.ai](https://bugbunny.ai).",
                    "title": "github - https://github.com/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "description",
                    "text": "## Summary\n\nThe Store API login endpoint (`POST /store-api/account/login`) returns different error codes depending on whether the submitted email address belongs to a registered customer (`CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS`) or is unknown (`CHECKOUT__CUSTOMER_NOT_FOUND`). The \"not found\" response also echoes the probed email address. This allows an unauthenticated attacker to enumerate valid customer accounts. The storefront login controller correctly unifies both error paths, but the Store API does not — indicating an inconsistent defense.\n\n## CWE\n\n- **CWE-204**: Observable Response Discrepancy\n\n## Description\n\n### Distinct error codes leak account existence\n\nThe login flow in `AccountService::getCustomerByLogin()` calls `getCustomerByEmail()` first, which throws `CustomerNotFoundException` if the email is not found. If the email IS found but the password is wrong, a separate `BadCredentialsException` is thrown:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/AccountService.php:116-145\npublic function getCustomerByLogin(string $email, string $password, SalesChannelContext $context): CustomerEntity\n{\n    if ($this->isPasswordTooLong($password)) {\n        throw CustomerException::badCredentials();\n    }\n\n    $customer = $this->getCustomerByEmail($email, $context);\n    // ↑ Throws CustomerNotFoundException with CHECKOUT__CUSTOMER_NOT_FOUND if email unknown\n\n    if ($customer->hasLegacyPassword()) {\n        if (!$this->legacyPasswordVerifier->verify($password, $customer)) {\n            throw CustomerException::badCredentials();\n            // ↑ Throws BadCredentialsException with CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS\n        }\n        // ...\n    }\n\n    if ($customer->getPassword() === null\n        || !password_verify($password, $customer->getPassword())) {\n        throw CustomerException::badCredentials();\n        // ↑ Same: CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS\n    }\n    // ...\n}\n```\n\nThe two exception types produce clearly distinguishable API responses:\n\n**Email not registered:**\n```json\n{\n  \"errors\": [{\n    \"status\": \"401\",\n    \"code\": \"CHECKOUT__CUSTOMER_NOT_FOUND\",\n    \"detail\": \"No matching customer for the email \\\"probe@example.com\\\" was found.\",\n    \"meta\": { \"parameters\": { \"email\": \"probe@example.com\" } }\n  }]\n}\n```\n\n**Email registered, wrong password:**\n```json\n{\n  \"errors\": [{\n    \"status\": \"401\",\n    \"code\": \"CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS\",\n    \"detail\": \"Invalid username and/or password.\"\n  }]\n}\n```\n\n### Storefront is protected — Store API is not\n\nThe storefront login controller demonstrates that Shopware's developers are aware of this risk class. `AuthController::login()` catches both exceptions together and returns a generic error:\n\n```php\n// src/Storefront/Controller/AuthController.php:203\n} catch (BadCredentialsException|CustomerNotFoundException) {\n    // Unified handling — no distinction exposed to the user\n}\n```\n\nThe Store API `LoginRoute::login()` does NOT catch these exceptions. They propagate to the global `ErrorResponseFactory`, which serializes the distinct error codes into the JSON response:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/LoginRoute.php:54-58\n$token = $this->accountService->loginByCredentials(\n    $email,\n    (string) $data->get('password'),\n    $context\n);\n// No try/catch — exceptions propagate with distinct codes\n```\n\nThis inconsistency confirms the Store API exposure is an oversight, not a design decision.\n\n### Rate limiting is present but insufficient for enumeration\n\nThe login route has rate limiting (LoginRoute.php:47-51) keyed on `strtolower($email) . '-' . $clientIp`. This slows bulk enumeration but does not prevent it because:\n\n1. The attacker only needs **one request per email** to determine existence\n2. The rate limit key includes the IP, so rotating IPs resets the counter\n3. The rate limiter is designed to prevent brute-force password guessing, not single-probe enumeration\n\n## Impact\n\n- **Customer email enumeration**: An attacker can confirm whether specific email addresses are registered as customers, enabling targeted attacks\n- **Phishing enablement**: Confirmed customer emails can be targeted with store-specific phishing campaigns (e.g., fake order confirmations, password reset lures)\n- **Credential stuffing optimization**: Attackers with breached credential databases can first filter for valid emails before attempting password guesses, improving efficiency against rate limits\n- **Privacy violation**: Confirms an individual's association with a specific store, which may be sensitive depending on the store's nature (e.g., medical supplies, adult products)\n- **Email reflection**: The `CHECKOUT__CUSTOMER_NOT_FOUND` response echoes the probed email in the `detail` and `meta.parameters.email` fields, which could be leveraged in reflected content attacks\n\n## Recommended Remediation\n\n### Option 1: Catch both exceptions in LoginRoute and throw a unified error (Preferred)\n\nApply the same pattern already used in the storefront controller:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/LoginRoute.php\npublic function login(#[\\SensitiveParameter] RequestDataBag $data, SalesChannelContext $context): ContextTokenResponse\n{\n    EmailIdnConverter::encodeDataBag($data);\n    $email = (string) $data->get('email', $data->get('username'));\n\n    if ($this->requestStack->getMainRequest() !== null) {\n        $cacheKey = strtolower($email) . '-' . $this->requestStack->getMainRequest()->getClientIp();\n\n        try {\n            $this->rateLimiter->ensureAccepted(RateLimiter::LOGIN_ROUTE, $cacheKey);\n        } catch (RateLimitExceededException $exception) {\n            throw CustomerException::customerAuthThrottledException($exception->getWaitTime(), $exception);\n        }\n    }\n\n    try {\n        $token = $this->accountService->loginByCredentials(\n            $email,\n            (string) $data->get('password'),\n            $context\n        );\n    } catch (CustomerNotFoundException) {\n        // Normalize to the same exception as bad credentials\n        throw CustomerException::badCredentials();\n    }\n\n    if (isset($cacheKey)) {\n        $this->rateLimiter->reset(RateLimiter::LOGIN_ROUTE, $cacheKey);\n    }\n\n    return new ContextTokenResponse($token);\n}\n```\n\nThis ensures both \"not found\" and \"bad credentials\" return the same `CHECKOUT__CUSTOMER_AUTH_BAD_CREDENTIALS` code and generic message.\n\n### Option 2: Unify at the AccountService layer\n\nFor defense in depth, change `AccountService::getCustomerByLogin()` to throw `BadCredentialsException` instead of letting `CustomerNotFoundException` propagate:\n\n```php\n// src/Core/Checkout/Customer/SalesChannel/AccountService.php\npublic function getCustomerByLogin(string $email, string $password, SalesChannelContext $context): CustomerEntity\n{\n    if ($this->isPasswordTooLong($password)) {\n        throw CustomerException::badCredentials();\n    }\n\n    try {\n        $customer = $this->getCustomerByEmail($email, $context);\n    } catch (CustomerNotFoundException) {\n        throw CustomerException::badCredentials();\n    }\n\n    // ... rest of password verification\n}\n```\n\nThis protects all callers of `getCustomerByLogin()` regardless of how they handle exceptions. Note: `getCustomerByEmail()` is also called independently (e.g., password recovery), so that method should continue to throw `CustomerNotFoundException` for internal use — the normalization should happen at the login boundary.\n\n### Additional: Fix registration endpoint\n\nThe registration endpoint (`POST /store-api/account/register`) also leaks email existence via `CUSTOMER_EMAIL_NOT_UNIQUE`. For complete remediation, consider returning a generic success response and sending a notification email to the existing address instead.\n\n## Credit\n\nThis vulnerability was discovered and reported by [bugbunny.ai](https://bugbunny.ai).",
                    "title": "github - https://api.github.com/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "other",
                    "text": "0.00048",
                    "title": "EPSS"
                },
                {
                    "category": "other",
                    "text": "5.3",
                    "title": "NCSC Score"
                },
                {
                    "category": "other",
                    "text": "Is related to (a version of) an uncommon product",
                    "title": "NCSC Score top increasing factors"
                }
            ],
            "product_status": {
                "known_affected": [
                    "CSAFPID-5798756",
                    "CSAFPID-5798757",
                    "CSAFPID-5798758",
                    "CSAFPID-5798764",
                    "CSAFPID-5830366",
                    "CSAFPID-5830367"
                ]
            },
            "references": [
                {
                    "category": "external",
                    "summary": "Source - nvd",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-31888"
                },
                {
                    "category": "external",
                    "summary": "Source raw - nvd",
                    "url": "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId=CVE-2026-31888"
                },
                {
                    "category": "external",
                    "summary": "Source - cveprojectv5",
                    "url": "https://www.cve.org/CVERecord?id=CVE-2026-31888"
                },
                {
                    "category": "external",
                    "summary": "Source raw - cveprojectv5",
                    "url": "https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/31xxx/CVE-2026-31888.json"
                },
                {
                    "category": "external",
                    "summary": "Source - github",
                    "url": "https://github.com/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "external",
                    "summary": "Source raw - github",
                    "url": "https://api.github.com/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss?cve=CVE-2026-31888"
                },
                {
                    "category": "external",
                    "summary": "Source raw - first",
                    "url": "https://api.first.org/data/v1/epss?limit=10000&offset=0"
                },
                {
                    "category": "external",
                    "summary": "Source - github",
                    "url": "https://api.github.com/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "external",
                    "summary": "Source - first",
                    "url": "https://api.first.org/data/v1/epss?limit=10000&offset=0"
                },
                {
                    "category": "external",
                    "summary": "Reference - cveprojectv5; github; nvd",
                    "url": "https://github.com/shopware/shopware/security/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://github.com/advisories/GHSA-gqc5-xv7m-gcjq"
                },
                {
                    "category": "external",
                    "summary": "Reference - github",
                    "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-31888"
                }
            ],
            "scores": [
                {
                    "cvss_v3": {
                        "version": "3.1",
                        "vectorString": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N",
                        "baseScore": 5.3,
                        "baseSeverity": "MEDIUM"
                    },
                    "products": [
                        "CSAFPID-5798756",
                        "CSAFPID-5798757",
                        "CSAFPID-5798758",
                        "CSAFPID-5798764",
                        "CSAFPID-5830366",
                        "CSAFPID-5830367"
                    ]
                }
            ],
            "title": "CVE-2026-31888"
        }
    ]
}