apache / apache/shenyu

[BUG] Logging console desensitization algorithm leaks across concurrent requests

Open
#6,511 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
8.8k
Forks
3.1k
Avg merge
7d 1h
Merged PRs (30d)
85

Description

### Search before asking

- [x] I had searched in the [issues](https://github.com/apache/shenyu/issues) and found no similar issues.

### Apache ShenYu Component

shenyu-plugin

### What happened

`LoggingConsolePlugin` stores the desensitization algorithm in a static mutable field:

```java
private static String dataDesensitizeAlg = DataDesensitizeEnum.CHARACTER_REPLACE.getDataDesensitizeAlg();
```

For every request whose logging rule enables masking, the plugin overwrites that static field from the current rule:

```java
if (desensitized) {
Collections.addAll(keywordSets, keywords.split(";"));
dataDesensitizeAlg = Optional.ofNullable(commonLoggingRuleHandle.getMaskType())
.orElse(DataDesensitizeEnum.MD5_ENCRYPT.getDataDesensitizeAlg());
keyWordMatch = new KeyWordMatch(keywordSets);
}
```

Later, when the response body is logged, the response decorator reads the same static field:

```java
String responseBody = DataDesensitizeUtils.desensitizeBody(desensitized, writer.output(), keyWordMatch, dataDesensitizeAlg);
```

Because response logging happens asynchronously and after the plugin has already returned control to the chain, another concurrent request matching a different logging rule can overwrite `dataDesensitizeAlg` before the first response reaches `doFinally(...)`. The first request then logs with the second rule's masking algorithm.

This makes console logs nondeterministic when different logging rules use different `maskType` values.

### Expected behavior

The desensitization algorithm should be request-scoped, like `desensitized` and `keyWordMatch`. It should be captured in a local final variable and passed into `LoggingServerHttpRequest`/`LoggingServerHttpResponse` instead of being stored in a static mutable field.

### How to reproduce

1. Configure two logging-console rules with different `maskType` values.
2. Send concurrent requests matching both rules.
3. Let one response complete after the other request has entered `LoggingConsolePlugin.doExecute(...)` and overwritten `dataDesensitizeAlg`.
4. The first request's response log can be masked using the second rule's algorithm.

### Debug logs

_No response_

### Environment

Current `master` branch.

### Are you willing to submit a PR?

- [ ] Yes I am willing to submit a PR!

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading LoggingConsolePlugin.doExecute(...) and tracing how desensitized, keyWordMatch, and dataDesensitizeAlg reach LoggingServerHttpRequest, LoggingServerHttpResponse, and doFinally(...). Verify the behavior with concurrent requests using different maskType values; done means each response log consistently uses the algorithm selected for its own request without shared mutable state.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
backend, observability
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.