Skip to content

fix: apply configured WAF statusCode to HTTP response instead of hardcoded 403 - #6821

Open
wy471x wants to merge 3 commits into
apache:masterfrom
wy471x:fix_WAFPluginConfiguration
Open

fix: apply configured WAF statusCode to HTTP response instead of hardcoded 403#6821
wy471x wants to merge 3 commits into
apache:masterfrom
wy471x:fix_WAFPluginConfiguration

Conversation

@wy471x

@wy471x wy471x commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

apply configured WAF statusCode to HTTP response instead of hardcoded 403

Make sure that:

  • You have read the contribution guidelines.
  • You submit test cases (unit or integration tests) that back your changes.
  • Your local test passed ./mvnw clean install -Dmaven.javadoc.skip=true.

Summary

Problem:

WafPlugin hardcoded exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN), ignoring the configurable statusCode from WafHandle. This meant setting a custom
statusCode (e.g., 404) only changed the response body code, while the actual HTTP transport status remained 403.

Changes:

  • WafPlugin.java:67-71 — Parse wafHandle.getStatusCode() once, apply it via setRawStatusCode(statusCode) instead of setStatusCode(HttpStatus.FORBIDDEN), and reuse the same int
    value in ShenyuResultWrap.error(), keeping HTTP status and body code consistent.
  • WafPluginTest.java — Updated testWafPluginReject to use a valid statusCode: "403" and added assertEquals(403, exchange.getResponse().getRawStatusCode()). Added
    testWafPluginRejectWithCustomStatusCode that configures statusCode: "404" and asserts the HTTP response status is actually 404.

close #6477

@Aias00

Aias00 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Good catch — hardcoding HttpStatus.FORBIDDEN ignored the configured statusCode on the wire, and setRawStatusCode(int) is the right way to honor custom codes. One behavioral change worth a guard before merge:

Null/non-numeric statusCode now produces a 500 instead of a 403 (WAF no longer fails closed). WafHandle.statusCode is a plain String with no default initializer (WafHandle.java:37), so a reject rule whose JSON omits statusCode deserializes to null. In the old code, setStatusCode(FORBIDDEN) ran before Integer.parseInt(wafHandle.getStatusCode()) for the body — so even when the parse threw, 403 was already on the response. In the new code (WafPlugin.java:67), int statusCode = Integer.parseInt(wafHandle.getStatusCode()) parses first, so a null/non-numeric value throws before any status is set and propagates to the global error handler (likely 500). For a WAF, a misconfigured reject rule should fail closed (403), not surface as a 500. Suggested fix:

int statusCode = Optional.ofNullable(wafHandle.getStatusCode())
        .filter(NumberUtils::isCreatable)
        .map(Integer::parseInt)
        .orElse(HttpStatus.FORBIDDEN.value());

Also: the two new tests cover 403 and 404 (valid codes) but not the null/empty/non-numeric statusCode case — exactly the path that now 500s. A test for that case would pin the intended fail-closed behavior.

Minor: setRawStatusCode accepts any int, so a user configuring statusCode:"200" makes a WAF reject look like a 200 success to the client. Restoring configurability is the PR's intent, so this is the operator's responsibility, but a 4xx/5xx range guard would prevent foot-shooting if desired.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] WAF reject rules ignore the configured HTTP status code

2 participants