MediumGHSA-v39m-97p8-gqg7CVE-2026-48010

Shopware: Privilege escalation: non-admin user with user:create ACL can create admin accounts

Published 4 Jun 2026 · Updated 10 Sept 2026

Affected packages

Affected
>=6.7.0.0 <6.7.10.1
Fixed in
6.7.10.1
Update to the fixed version for your release line, for example:composer require shopware/platform:^6.7.10.1
Affected
<6.6.10.18
Fixed in
6.6.10.18
Update to the fixed version for your release line, for example:composer require shopware/platform:^6.6.10.18
Affected
>=6.7.0.0 <6.7.10.1
Fixed in
6.7.10.1
Update to the fixed version for your release line, for example:composer require shopware/core:^6.7.10.1
Affected
<6.6.10.18
Fixed in
6.6.10.18
Update to the fixed version for your release line, for example:composer require shopware/core:^6.6.10.18

Details

UserController::upsertUser() writes user data in SYSTEM_SCOPE and does not filter the admin field. A non-admin API user with user:create or user:update ACL permission can set admin: true on new or existing users, escalating to full admin access.

The Problem

In src/Core/Framework/Api/Controller/UserController.php, line 210-234:

public function upsertUser(?string $userId, Request $request, Context $context, ResponseFactoryInterface $factory): Response
{
    $data = $request->request->all(); // raw request data, no field filtering
    // ...
    $events = $context->scope(Context::SYSTEM_SCOPE, fn (Context $context) =>
        $this->userRepository->upsert([$data], $context)
    );
}

SYSTEM_SCOPE bypasses AclWriteValidator entirely (line 52 of AclWriteValidator::preValidate() returns early for SYSTEM_SCOPE). The admin boolean field is accepted without restriction.

Compare with IntegrationController::upsertIntegration() in the same codebase, which correctly checks:

if ((!$source instanceof AdminApiSource)
    || (!$source->isAdmin()
    && isset($data['admin']))
) {
    throw new PermissionDeniedException();
}

UserController is missing this exact check.

Impact

Any API user with the low-privilege user:create permission can create accounts with full admin access, or with user:update can promote any existing user to admin. This is a direct privilege escalation.

Suggested Fix

Add the same isAdmin() check from IntegrationController:

$source = $context->getSource();
if ((!$source instanceof AdminApiSource) || (!$source->isAdmin() && isset($data['admin']))) {
    throw new PermissionDeniedException();
}

Best regards, Keyvan Hardani

Is GHSA-v39m-97p8-gqg7 in any of your client repos?

Checking one package by hand is fine. Checking it across forty client projects is not. NPMscan reads the lockfiles in every GitHub repo you pick, finds each project with an affected shopware/platform, and gives you the command that fixes it.

References

Advisory data from OSV.dev (opens OSV.dev in a new tab), refreshed daily.