Aias00 opened a new issue, #7370:
URL: https://github.com/apache/shenyu/issues/7370
### Is there an existing issue for this?
- [x] I have searched the existing issues. This is not a duplicate of #6720,
which fixed the disallowed `OPTIONS` short-circuit behavior.
### Current Behavior
When `shenyu.cross.allowedAnyOrigin=false` and `allowedOrigin` is
configured, the configured CORS policy is not reliably reflected in the final
response:
1. A configured absolute origin can be rejected when its scheme differs from
the request URI scheme.
`CrossFilter` preserves an origin only when it starts with the current
request scheme. Otherwise it prefixes the current scheme unconditionally:
```java
if (ALL.equals(oneOrigin) || oneOrigin.startsWith(String.format("%s://",
scheme))) {
return oneOrigin.trim();
}
return String.format("%s://%s", scheme, oneOrigin.trim());
```
For a request URI whose scheme is `http`, the configured absolute origin
`https://frontend.example.com` becomes `http://https://frontend.example.com`.
Consequently, a request carrying the configured origin receives no
`Access-Control-Allow-Origin` header. This is common when TLS is terminated
before the gateway or when allowed origins legitimately use a different scheme
from the gateway URL.
2. A disallowed origin can still receive an upstream-provided CORS header.
With the default Netty HTTP client, all upstream response headers are
copied with:
```java
response.getHeaders().putAll(headers);
```
Therefore, if the upstream service returns `Access-Control-Allow-Origin:
*` (or echoes the request origin), it can overwrite or bypass the policy
established by `CrossFilter`. The WebClient path also copies all upstream
headers before `WebClientMessageWriter` attempts to omit
`Access-Control-Allow-Origin`, so the earlier value can remain in the gateway
response.
The result is that `allowedOrigin` can produce both false negatives
(configured origin gets no CORS header) and false positives (disallowed origin
gets an upstream CORS header).
### Expected Behavior
When the gateway CORS filter is enabled and `allowedAnyOrigin=false`:
- Absolute configured origins should be parsed and compared as-is,
regardless of the gateway request scheme.
- A configured cross-origin value should receive
`Access-Control-Allow-Origin`.
- A disallowed origin should not receive `Access-Control-Allow-Origin`, even
if the upstream service returns one, or the precedence should be explicitly
configurable and documented.
- Netty and WebClient strategies should apply the same CORS-header
precedence.
### Steps To Reproduce
#### False negative for a configured origin
1. Configure the gateway:
```yaml
shenyu:
cross:
enabled: true
allowedAnyOrigin: false
allowedOrigin:
origins:
- https://frontend.example.com
allowedMethods: "GET,POST,OPTIONS"
allowCredentials: false
```
2. Start the gateway with an HTTP listener and send a request to any
existing route:
```bash
curl -i 'http://localhost:9195/<existing-route>' \
-H 'Origin: https://frontend.example.com'
```
3. `Access-Control-Allow-Origin` is absent because the configured origin is
normalized to `http://https://frontend.example.com` before comparison.
#### Disallowed origin overridden by the upstream response
1. Keep `allowedAnyOrigin=false` and allow only
`https://frontend.example.com`.
2. Configure an upstream route whose service returns:
```http
Access-Control-Allow-Origin: *
```
3. Send:
```bash
curl -i 'http://localhost:9195/<existing-route>' \
-H 'Origin: https://evil.example.com'
```
4. The final gateway response can still contain the upstream
`Access-Control-Allow-Origin` header even though the origin is not in the
gateway allow-list.
### Environment
```markdown
ShenYu version(s): 2.7.0 and current master
(6a757d4477d22330ca38af35a1e1f87262b1ddcc)
HTTP client strategies: Netty (default); WebClient has the same precedence
concern because headers are copied before response rewriting
```
### Debug logs
No exception is logged. The issue is visible in the final response headers.
### Anything else?
Relevant current-master code:
- `CrossFilter` origin normalization and comparison:
https://github.com/apache/shenyu/blob/6a757d4477d22330ca38af35a1e1f87262b1ddcc/shenyu-web/src/main/java/org/apache/shenyu/web/filter/CrossFilter.java#L68-L99
- Netty upstream response-header copy:
https://github.com/apache/shenyu/blob/6a757d4477d22330ca38af35a1e1f87262b1ddcc/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/NettyHttpClientPlugin.java#L108-L126
- WebClient upstream response-header copy:
https://github.com/apache/shenyu/blob/6a757d4477d22330ca38af35a1e1f87262b1ddcc/shenyu-plugin/shenyu-plugin-httpclient/src/main/java/org/apache/shenyu/plugin/httpclient/WebClientPlugin.java#L107-L118
- WebClient response rewrite:
https://github.com/apache/shenyu/blob/6a757d4477d22330ca38af35a1e1f87262b1ddcc/shenyu-plugin/shenyu-plugin-response/src/main/java/org/apache/shenyu/plugin/response/strategy/WebClientMessageWriter.java#L103-L121
Suggested direction:
- Parse configured origins as origins/URIs and only prefix genuinely
scheme-less values.
- Make `CrossFilter` authoritative for CORS response headers when enabled,
or introduce an explicit gateway-vs-upstream precedence option.
- Add tests covering absolute origins with a different request scheme and
upstream CORS headers under both HTTP client strategies.
--
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]