This is an automated email from the ASF dual-hosted git repository.
dengliming pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new bbe2a35b45 fix: docker-compose hardcoded JWT secret key allows forging
admin authentication (#7063)
bbe2a35b45 is described below
commit bbe2a35b450b9feb3d9dc9acb69e5a6fdb6dcc61
Author: Arvin <[email protected]>
AuthorDate: Wed Sep 16 00:17:27 2026 +0800
fix: docker-compose hardcoded JWT secret key allows forging admin
authentication (#7063)
* fix #7058: force setting SHENYU_JWT_SECRETKEY in docker-compose instead
of shipping a public default
* fix #7058: add previously distributed public JWT key to the sentinel
denylist
* fix #7058: reject the publicly-known compose JWT key with fail-fast
validation
* test #7058: java validator unit test for public compose JWT key rejection
---------
Co-authored-by: aias00 <[email protected]>
Co-authored-by: Liming Deng <[email protected]>
---
.../org/apache/shenyu/admin/config/properties/JwtProperties.java | 3 ++-
.../apache/shenyu/admin/config/properties/JwtPropertiesTest.java | 8 ++++++++
.../java/org/apache/shenyu/common/constant/AdminConstants.java | 6 ++++++
.../src/main/resources/docker-compose.yaml | 7 +++++--
4 files changed, 21 insertions(+), 3 deletions(-)
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java
index 7ea2ed4685..ad14011734 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/config/properties/JwtProperties.java
@@ -40,7 +40,8 @@ public class JwtProperties {
@PostConstruct
private void init() {
- if (StringUtils.isBlank(secretKey) ||
AdminConstants.JWT_DEFAULT_SECRET_KEY.equals(this.secretKey)) {
+ if (StringUtils.isBlank(secretKey) ||
AdminConstants.JWT_DEFAULT_SECRET_KEY.equals(this.secretKey)
+ ||
AdminConstants.JWT_PUBLIC_SECRET_KEY.equals(this.secretKey)) {
throw new IllegalStateException("shenyu.jwt.secretKey is not
configured. "
+ "In a multi-instance Admin cluster, each instance would
generate a different key, "
+ "causing token verification failures. "
diff --git
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/config/properties/JwtPropertiesTest.java
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/config/properties/JwtPropertiesTest.java
index bc2b747117..e81ea45137 100644
---
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/config/properties/JwtPropertiesTest.java
+++
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/config/properties/JwtPropertiesTest.java
@@ -45,6 +45,14 @@ public class JwtPropertiesTest {
() -> ReflectionTestUtils.invokeMethod(jwtProperties, "init"));
}
+ @Test
+ public void testInitThrowsWhenSecretKeyIsPublicComposeKey() {
+ final JwtProperties jwtProperties = new JwtProperties();
+ jwtProperties.setSecretKey("please-replace-with-your-own-secret-key");
+ Assertions.assertThrows(IllegalStateException.class,
+ () -> ReflectionTestUtils.invokeMethod(jwtProperties, "init"));
+ }
+
@Test
public void testInitDoesNotThrowWhenSecretKeyIsConfigured() {
final JwtProperties jwtProperties = new JwtProperties();
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/AdminConstants.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/AdminConstants.java
index a160077bd5..4f3807a3b8 100644
---
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/AdminConstants.java
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/AdminConstants.java
@@ -308,5 +308,11 @@ public final class AdminConstants {
public static final long TEN_SECONDS_MILLIS_TIME = 10 * 1000L;
public static final String JWT_DEFAULT_SECRET_KEY = "defaultSecretKey";
+
+ /**
+ * The publicly-known JWT secret key that was previously distributed in
the official docker-compose.yaml.
+ * Any token signed with it can be forged by anyone who reads the
repository, so it must be rejected.
+ */
+ public static final String JWT_PUBLIC_SECRET_KEY =
"please-replace-with-your-own-secret-key";
}
diff --git
a/shenyu-dist/shenyu-docker-compose-dist/src/main/resources/docker-compose.yaml
b/shenyu-dist/shenyu-docker-compose-dist/src/main/resources/docker-compose.yaml
index 41d9cdeef7..ec0778f111 100644
---
a/shenyu-dist/shenyu-docker-compose-dist/src/main/resources/docker-compose.yaml
+++
b/shenyu-dist/shenyu-docker-compose-dist/src/main/resources/docker-compose.yaml
@@ -44,9 +44,12 @@ services:
ports:
- "9095:9095"
environment:
- # Required: replace with your own secure key in production.
+ # Required: generate your own secure key and export it, e.g.
+ # openssl rand -base64 48
+ # export SHENYU_JWT_SECRETKEY=<the-generated-value>
+ # docker compose refuses to start until SHENYU_JWT_SECRETKEY is set.
# In a multi-instance Admin cluster, all instances must share the same
secretKey.
- - SHENYU_JWT_SECRETKEY=please-replace-with-your-own-secret-key
+ - SHENYU_JWT_SECRETKEY=${SHENYU_JWT_SECRETKEY:?SHENYU_JWT_SECRETKEY must
be set. Generate one with 'openssl rand -base64 48' and export it.}
healthcheck:
test: [ "CMD-SHELL", "wget -q -O -
http://shenyu-admin:9095/actuator/health | grep UP || exit 1" ]
timeout: 2s