Summary
The PATCH /api/customers/:id endpoint allows any unauthenticated attacker to overwrite any customer's email address, password, and profile fields by supplying the customer's UUID in the URL path. No authentication token, session cookie, or proof of ownership is required. Because the endpoint returns HTTP 200 with the updated customer record, the attacker can immediately log in with the new credentials, locking out the legitimate account holder.
Details
The route is registered in packages/evershop/src/modules/customer/api/updateCustomer/route.json:
{
"methods": ["PATCH"],
"path": "/customers/:id",
"access": "public"
}
Setting "access": "public" causes the global admin-auth middleware ([getCurrentUser]auth.ts) to skip its check and call next() unconditionally. No customer-session middleware guards this route. The sole file in the middleware chain is [context]bodyParser[auth].js, which only parses the JSON body:
export default (request, response, next) => {
bodyParser.json({ inflate: false })(request, response, next);
};
The handler updateCustomer.js then looks up the target customer by UUID directly from the URL parameter and writes the supplied fields — including a newly hashed password — back to the database without verifying that the caller is the owner of that record:
export default async (request, response, next) => {
const customer = await select()
.from('customer')
.where('uuid', '=', request.params.id) // no session check
.load(connection, false);
...
await update('customer')
.given({ ...request.body, group_id: 1 })
.where('uuid', '=', request.params.id)
.execute(connection, false);
The customer UUID is a v4 UUID exposed through admin order-edit pages, email order confirmations, and other application surfaces, making it obtainable by any party who has ever interacted with the victim's account.
PoC
(available upon request)
Impact
Any unauthenticated internet user who obtains a customer UUID can silently take over that customer account. Customer UUIDs appear in order confirmation emails, admin panel URLs, and application URLs that may be exposed via referrer headers or shared links. Upon takeover the attacker gains access to the customer's saved addresses, order history, and any payment methods stored via third-party integrations, and the legitimate account holder is locked out.
Summary
The
PATCH /api/customers/:idendpoint allows any unauthenticated attacker to overwrite any customer's email address, password, and profile fields by supplying the customer's UUID in the URL path. No authentication token, session cookie, or proof of ownership is required. Because the endpoint returns HTTP 200 with the updated customer record, the attacker can immediately log in with the new credentials, locking out the legitimate account holder.Details
The route is registered in
packages/evershop/src/modules/customer/api/updateCustomer/route.json:{ "methods": ["PATCH"], "path": "/customers/:id", "access": "public" }Setting
"access": "public"causes the global admin-auth middleware ([getCurrentUser]auth.ts) to skip its check and callnext()unconditionally. No customer-session middleware guards this route. The sole file in the middleware chain is[context]bodyParser[auth].js, which only parses the JSON body:The handler
updateCustomer.jsthen looks up the target customer by UUID directly from the URL parameter and writes the supplied fields — including a newly hashedpassword— back to the database without verifying that the caller is the owner of that record:The customer UUID is a v4 UUID exposed through admin order-edit pages, email order confirmations, and other application surfaces, making it obtainable by any party who has ever interacted with the victim's account.
PoC
(available upon request)
Impact
Any unauthenticated internet user who obtains a customer UUID can silently take over that customer account. Customer UUIDs appear in order confirmation emails, admin panel URLs, and application URLs that may be exposed via referrer headers or shared links. Upon takeover the attacker gains access to the customer's saved addresses, order history, and any payment methods stored via third-party integrations, and the legitimate account holder is locked out.