This is an automated email from the ASF dual-hosted git repository.

wusheng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 5a3f6260e4 Fix `/debugging/config/dump` may leak sensitive information 
if there are second level properties in the configuration. (#13726)
5a3f6260e4 is described below

commit 5a3f6260e4dd681a9132204e5299064bef079886
Author: Wan Kai <[email protected]>
AuthorDate: Thu Mar 5 21:28:38 2026 +0800

    Fix `/debugging/config/dump` may leak sensitive information if there are 
second level properties in the configuration. (#13726)
---
 docs/en/changes/changes.md                         |   1 +
 .../server/core/status/ServerStatusService.java    |  35 +++-
 test/e2e-v2/cases/storage/expected/config-dump.yml | 204 +++++++++++++++++++++
 test/e2e-v2/cases/storage/mysql/e2e.yaml           |   4 +-
 4 files changed, 238 insertions(+), 6 deletions(-)

diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index 1c28ea4563..5752f12b6d 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -67,6 +67,7 @@
   | **Total (OAP threads)**               | **150+**           | **~72** | 
**~50% reduction, stable in high payload.** |
 
 * Replace PowerMock Whitebox with standard Java Reflection in 
`server-library`, `server-core`, and `server-configuration` to support JDK 25+.
+* Fix `/debugging/config/dump` may leak sensitive information if there are 
second level properties in the configuration.
 
 #### OAP Server
 
diff --git 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/status/ServerStatusService.java
 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/status/ServerStatusService.java
index a5e238e654..f561f89455 100644
--- 
a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/status/ServerStatusService.java
+++ 
b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/status/ServerStatusService.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.status;
 
 import java.util.HashMap;
 import java.util.List;
+import java.util.Properties;
 import java.util.concurrent.CopyOnWriteArrayList;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
@@ -100,12 +101,18 @@ public class ServerStatusService implements Service {
                 (providerName, providerConfiguration) ->
                     providerConfiguration.getProperties().forEach(
                         (key, value) -> {
-                            for (final String keyword : keywords) {
-                                if 
(key.toString().toLowerCase().contains(keyword.toLowerCase())) {
-                                    value = "******";
-                                }
+                            if (value instanceof Properties) {
+                                Properties properties = (Properties) value;
+                                properties.forEach((k, v) -> {
+                                    String configKey = moduleName + "." + 
providerName + "." + key + "." + k;
+                                    String configValue = 
maskConfigValue(k.toString(), v.toString(), keywords);
+                                    configList.put(configKey, configValue);
+                                });
+                            } else {
+                                String configKey = moduleName + "." + 
providerName + "." + key;
+                                String configValue = 
maskConfigValue(key.toString(), value.toString(), keywords);
+                                configList.put(configKey, configValue);
                             }
-                            configList.put(moduleName + "." + providerName + 
"." + key, value.toString());
                         }
                     )
             );
@@ -113,6 +120,24 @@ public class ServerStatusService implements Service {
         return configList;
     }
 
+    /**
+     * Mask the configuration value if the key contains any masking keyword.
+     *
+     * @param configKey   the configuration key to check
+     * @param configValue the configuration value to mask
+     * @param keywords    the keywords for masking secrets
+     * @return masked value "******" if key matches any keyword, otherwise 
return the original value
+     */
+    private String maskConfigValue(String configKey, String configValue, 
String[] keywords) {
+        String lowerConfigKey = configKey.toLowerCase();
+        for (String keyword : keywords) {
+            if (lowerConfigKey.contains(keyword.toLowerCase())) {
+                return "******";
+            }
+        }
+        return configValue;
+    }
+
     public static class ConfigList extends HashMap<String, String> {
         @Override
         public String toString() {
diff --git a/test/e2e-v2/cases/storage/expected/config-dump.yml 
b/test/e2e-v2/cases/storage/expected/config-dump.yml
new file mode 100644
index 0000000000..acd4c65da2
--- /dev/null
+++ b/test/e2e-v2/cases/storage/expected/config-dump.yml
@@ -0,0 +1,204 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+core.default.autocompleteTagKeysQueryMaxSize=100
+receiver-sharing-server.default.gRPCPort=0
+aws-firehose.default.port=12801
+core.default.restPort=12800
+receiver-sharing-server.default.gRPCSslCertChainPath=
+agent-analyzer.default.meterAnalyzerActiveFiles=datasource,threadpool,satellite,go-runtime,python-runtime,continuous-profiling,java-agent,go-agent,ruby-runtime
+receiver-pprof.default.memoryParserEnabled=true
+agent-analyzer.default.traceSamplingPolicySettingsFile=trace-sampling-policy-settings.yml
+core.default.gRPCSslTrustedCAPath=
+configuration-discovery.default.disableMessageDigest=false
+core.default.serviceNameMaxLength=70
+aws-firehose.default.tlsCertChainPath=
+envoy-metric.default.k8sServiceNameRule=${pod.metadata.labels.(service.istio.io/canonical-name)}.${pod.metadata.namespace}
+ai-pipeline.provider=default
+promql.default.buildInfoVersion=2.45.0
+receiver-ebpf.default.maxConcurrentCallsPerConnection=0
+aws-firehose.provider=default
+receiver-event.provider=default
+core.default.searchableAlarmTags=level
+core.default.prepareThreads=2
+core.default.topNReportPeriod=10
+core.default.enableDataKeeperExecutor=true
+agent-analyzer.default.slowCacheReadThreshold=default:20,redis:10
+receiver-ebpf.default.continuousPolicyCacheTimeout=60
+receiver-ebpf.default.gRPCSslKeyPath=
+receiver-browser.provider=default
+agent-analyzer.default.segmentStatusAnalysisStrategy=FROM_SPAN_STATUS
+envoy-metric.default.maxConcurrentCallsPerConnection=0
+health-checker.default.checkIntervalSeconds=30
+core.default.gRPCSslEnabled=false
+logql.default.restAcceptQueueSize=0
+receiver-clr.provider=default
+receiver-async-profiler.provider=default
+storage.provider=mysql
+query.graphql.maxQueryComplexity=3000
+core.default.httpMaxRequestHeaderSize=8192
+receiver-sharing-server.default.gRPCSslEnabled=false
+telemetry.prometheus.sslEnabled=false
+receiver-sharing-server.default.authentication=******
+aws-firehose.default.acceptQueueSize=0
+storage.mysql.properties.dataSource.prepStmtCacheSize=250
+core.default.serviceCacheRefreshInterval=10
+core.default.gRPCSslKeyPath=
+receiver-ebpf.provider=default
+telemetry.prometheus.sslCertChainPath=
+receiver-sharing-server.default.maxConcurrentCallsPerConnection=0
+storage.mysql.asyncBatchPersistentPoolSize=4
+telemetry.provider=prometheus
+core.default.trainingPeriodHttpUriRecognitionPattern=60
+promql.default.restContextPath=/
+core.default.maxHeapMemoryUsagePercent=96
+aws-firehose.default.contextPath=/
+agent-analyzer.default.slowCacheWriteThreshold=default:20,redis:10
+envoy-metric.default.maxMessageSize=0
+promql.default.buildInfoGoVersion=
+storage.mysql.properties.dataSource.cachePrepStmts=true
+receiver-ebpf.default.gRPCThreadPoolSize=0
+query.graphql.enableLogTestTool=false
+envoy-metric.default.gRPCSslCertChainPath=
+receiver-ebpf.default.gRPCPort=0
+promql.default.buildInfoRevision=
+receiver-otel.default.enabledOtelMetricsRules=apisix,nginx/*,k8s/*,istio-controlplane,vm,mysql/*,postgresql/*,oap,aws-eks/*,windows,aws-s3/*,aws-dynamodb/*,aws-gateway/*,redis/*,elasticsearch/*,rabbitmq/*,mongodb/*,kafka/*,pulsar/*,bookkeeper/*,rocketmq/*,clickhouse/*,activemq/*,kong/*,flink/*,banyandb/*
+core.default.syncPeriodHttpUriRecognitionPattern=10
+core.default.enableHierarchy=true
+event-analyzer.provider=default
+receiver-otel.default.enabledHandlers=otlp-metrics,otlp-logs
+core.default.enableEndpointNameGroupingByOpenapi=true
+receiver-ebpf.default.gRPCHost=0.0.0.0
+receiver-browser.default.sampleRate=10000
+core.default.searchableTracesTags=http.method,http.status_code,rpc.status_code,db.type,db.instance,mq.queue,mq.topic,mq.broker
+core.default.instanceNameMaxLength=70
+core.default.restAcceptQueueSize=0
+receiver-sharing-server.default.gRPCHost=0.0.0.0
+telemetry.prometheus.sslKeyPath=
+log-analyzer.provider=default
+envoy-metric.default.gRPCPort=0
+storage.mysql.properties.dataSource.password=******
+agent-analyzer.default.forceSampleErrorSegment=true
+ai-pipeline.default.uriRecognitionServerPort=17128
+core.default.restIdleTimeOut=30000
+receiver-sharing-server.default.restHost=0.0.0.0
+receiver-sharing-server.provider=default
+cluster.provider=standalone
+receiver-sharing-server.default.restAcceptQueueSize=0
+agent-analyzer.provider=default
+receiver-telegraf.provider=default
+aws-firehose.default.tlsKeyPath=
+receiver-sharing-server.default.maxMessageSize=52428800
+core.default.gRPCHost=0.0.0.0
+envoy-metric.default.gRPCHost=0.0.0.0
+logql.default.restIdleTimeOut=30000
+service-mesh.provider=default
+query.provider=graphql
+receiver-telegraf.default.activeFiles=vm
+aws-firehose.default.maxRequestHeaderSize=8192
+core.default.endpointNameMaxLength=150
+core.default.metricsDataTTL=7
+storage.mysql.properties.dataSource.user=******
+promql.provider=default
+core.default.maxConcurrentCallsPerConnection=0
+configuration-discovery.provider=default
+ai-pipeline.default.baselineServerAddr=
+core.provider=default
+receiver-pprof.default.pprofMaxSize=31457280
+health-checker.provider=default
+logql.default.restHost=0.0.0.0
+receiver-sharing-server.default.restIdleTimeOut=30000
+configuration.provider=none
+logql.provider=default
+core.default.persistentPeriod=25
+storage.mysql.metadataQueryMaxSize=5000
+storage.mysql.properties.jdbcUrl=jdbc:mysql://mysql:3306/swtest?allowMultiQueries=true
+receiver-sharing-server.default.gRPCThreadPoolSize=0
+receiver-register.provider=default
+core.default.storageSessionTimeout=70000
+receiver-trace.provider=default
+envoy-metric.provider=default
+query.graphql.enableOnDemandPodLog=false
+receiver-sharing-server.default.restPort=0
+logql.default.restContextPath=/
+promql.default.restAcceptQueueSize=0
+telemetry.prometheus.host=0.0.0.0
+receiver-ebpf.default.maxMessageSize=0
+receiver-profile.provider=default
+receiver-sharing-server.default.httpMaxRequestHeaderSize=8192
+storage.mysql.properties.dataSource.useServerPrepStmts=true
+core.default.gRPCThreadPoolSize=-1
+status-query.default.keywords4MaskingSecretsOfConfig=user,password,token,accessKey,secretKey,authentication
+storage.mysql.maxSizeOfBatchSql=2000
+log-analyzer.default.malFiles=nginx
+telemetry.prometheus.port=1234
+core.default.recordDataTTL=3
+core.default.maxHttpUrisNumberPerService=3000
+core.default.downsampling=[Hour, Day]
+aws-firehose.default.idleTimeOut=30000
+core.default.maxDirectMemoryUsage=-1
+agent-analyzer.default.slowDBAccessThreshold=default:200,mongodb:100
+receiver-log.provider=default
+receiver-sharing-server.default.restContextPath=/
+receiver-async-profiler.default.memoryParserEnabled=true
+envoy-metric.default.istioServiceNameRule=${serviceEntry.metadata.name}.${serviceEntry.metadata.namespace}
+envoy-metric.default.istioServiceEntryIgnoredNamespaces=
+alarm.provider=default
+receiver-sharing-server.default.gRPCSslTrustedCAsPath=
+aws-firehose.default.firehoseAccessKey=******
+core.default.autocompleteTagValuesQueryMaxSize=100
+agent-analyzer.default.noUpstreamRealAddressAgents=6000,9000
+core.default.searchableLogsTags=level,http.status_code
+core.default.role=Mixed
+receiver-sharing-server.default.gRPCSslKeyPath=
+receiver-pprof.provider=default
+receiver-ebpf.default.gRPCSslEnabled=false
+envoy-metric.default.gRPCThreadPoolSize=0
+aws-firehose.default.host=0.0.0.0
+promql.default.restHost=0.0.0.0
+envoy-metric.default.gRPCSslEnabled=false
+core.default.gRPCSslCertChainPath=
+envoy-metric.default.enabledEnvoyMetricsRules=envoy,envoy-svc-relation
+receiver-meter.provider=default
+ai-pipeline.default.uriRecognitionServerAddr=
+promql.default.restIdleTimeOut=30000
+status-query.provider=default
+envoy-metric.default.gRPCSslKeyPath=
+core.default.gRPCPort=11800
+receiver-ebpf.default.gRPCSslTrustedCAsPath=
+receiver-jvm.provider=default
+receiver-ebpf.default.gRPCSslCertChainPath=
+promql.default.buildInfoBuildDate=
+logql.default.restPort=3100
+core.default.l1FlushPeriod=500
+promql.default.restPort=9090
+receiver-async-profiler.default.jfrMaxSize=31457280
+envoy-metric.default.alsTCPAnalysis=
+core.default.restHost=0.0.0.0
+envoy-metric.default.acceptMetricsService=true
+core.default.restContextPath=/
+envoy-metric.default.gRPCSslTrustedCAsPath=
+storage.mysql.properties.dataSource.prepStmtCacheSqlLimit=2048
+promql.default.buildInfoBranch=
+envoy-metric.default.alsHTTPAnalysis=
+core.default.maxMessageSize=52428800
+core.default.dataKeeperExecutePeriod=5
+log-analyzer.default.lalFiles=envoy-als,mesh-dp,mysql-slowsql,pgsql-slowsql,redis-slowsql,k8s-service,nginx,default
+promql.default.buildInfoBuildUser=******
+aws-firehose.default.enableTLS=false
+ai-pipeline.default.baselineServerPort=18080
+receiver-otel.provider=default
+core.default.activeExtraModelColumns=false
+query.graphql.enableUpdateUITemplate=false
\ No newline at end of file
diff --git a/test/e2e-v2/cases/storage/mysql/e2e.yaml 
b/test/e2e-v2/cases/storage/mysql/e2e.yaml
index 774dc86c91..8e0ed1b872 100644
--- a/test/e2e-v2/cases/storage/mysql/e2e.yaml
+++ b/test/e2e-v2/cases/storage/mysql/e2e.yaml
@@ -68,4 +68,6 @@ verify:
           swctl --display yaml 
--base-url=http://${oap_host}:${oap_12800}/graphql trace ls --order startTime 
--service-name "e2e-service-provider" --endpoint-name "POST:/users" \
             | yq e '.traces[0].traceids[0]' - \
         )
-      expected: ../expected/trace-users-detail.yml
\ No newline at end of file
+      expected: ../expected/trace-users-detail.yml
+    - query: curl -X GET http://${oap_host}:${oap_12800}/debugging/config/dump
+      expected: ../expected/config-dump.yml

Reply via email to