Security: Fix CWE-79 (Cross-Site Scripting) vulnerability in src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02317.java:64#667
Open
appsecai-app[bot] wants to merge 1 commit intomainfrom
Conversation
Apply OWASP Java Encoder's Encode.forHtml() to prevent cross-site scripting vulnerability where user-controlled HTTP request parameter names were written directly to HTML response without encoding. Fixes: 1 CWE-79 vulnerability
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What we found
69c734ebsrc/main/java/org/owasp/benchmark/testcode/BenchmarkTest02317.java:64Description: Detected user-controlled input flowing into a response writer without HTML encoding. This bypasses any view or template environments that would normally escape HTML, exposing the application to cross-site scripting (XSS) vulnerabilities. Direct writes to response output streams circumvent standard web framework protections.
Why this matters
Risk if not fixed: An attacker could inject malicious JavaScript that executes in victims' browsers, potentially stealing session cookies, redirecting users to phishing sites, or performing actions on behalf of authenticated users.
Risk level: Medium to High — depends on sensitivity of data accessible through the compromised session or the actions an attacker can perform.
Attack surface: Any HTTP request parameter name can be crafted to contain script payloads. The vulnerability requires no special authentication or preconditions.
Why we're changing it
Status: Confirmed vulnerability with clear exploitation path.
Vulnerability Flow Diagram
%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, Inter, system-ui, sans-serif','primaryColor':'#EDE9FE','primaryTextColor':'#1A1A2E','primaryBorderColor':'#7C3AED','lineColor':'#5B21B6','secondaryColor':'#FEF3C7','tertiaryColor':'#DCFCE7'}}}%% flowchart TD A["HTTP Request Parameter Name<br/>(Attacker-Controlled)"] --> B["request.getParameterNames()<br/>Line 53 - param = name"] B --> C["doSomething(param)<br/>Line 74 - 500/42 + 196 ) 200<br/>Always TRUE - returns param unmodified"] C --> D["response.getWriter().format(bar, obj)<br/>Line 64 - No HTML Encoding"] D --> E["❌ Unencoded Script Injected<br/>into HTML Response Body"] E --> F["🔴 Browser Executes Malicious<br/>JavaScript in Victim Context"] style A fill:#EDE9FE,stroke:#7C3AED style B fill:#EDE9FE,stroke:#7C3AED style C fill:#EDE9FE,stroke:#7C3AED style D fill:#FFE5E5,stroke:#F65A5A style E fill:#FEF3C7,stroke:#F59E0B style F fill:#FEF3C7,stroke:#F59E0BData Flow Analysis
Input source (lines 45–58): The code iterates
request.getParameterNames(), looking for any parameter whose value equals"BenchmarkTest02317". When found,paramis assigned the parameter name — fully attacker-controlled. An HTTP request can contain arbitrary parameter names.Propagation (lines 67–78,
doSomething): The arithmetic branch(500/42) + 196 > 200evaluates to207 > 200— a compile-time constanttrue. Thereforebar = paramunconditionally; no sanitization occurs on this path. Theelsebranch is dead code.Sink (line 64):
PrintWriter.format()writesbaras a format string directly to the HTTP response. The response content type istext/html;charset=UTF-8, and theX-XSS-Protection: 0header is explicitly set to disable browser-side XSS filtering. There is no HTML encoding at any point in the flow.Exploitation: An attacker crafts a request with a parameter named
<script>alert(1)</script>(valueBenchmarkTest02317). That name flows unmodified throughdoSomething, then is written verbatim into the HTML response body, executing in any browser that renders the response.How we confirmed
Manual Verification Steps
request.getParameterNames()returns attacker-controlled parameter names (line 53).(500/42) + 196 > 200always evaluates totrue(line 74), making theelsebranch unreachable.response.getWriter().format(bar, obj)writesbardirectly to the response without encoding (line 64).text/htmlandX-XSS-Protectionheader is set to0(lines 62, 63).Runnable Verification Script (click to expand)
Save this script and run with
bash verify_fix.sh:Vulnerable flow: src/main/java/org/owasp/benchmark/testcode/BenchmarkTest02317.java:64
Cross-Site Scripting
%%{init: {'theme':'base','themeVariables':{'fontFamily':'ui-sans-serif, Inter, system-ui, sans-serif','primaryColor':'#EDE9FE','primaryTextColor':'#1A1A2E','primaryBorderColor':'#7C3AED','lineColor':'#5B21B6','secondaryColor':'#FEF3C7','tertiaryColor':'#DCFCE7'}}}%% flowchart TD subgraph Vulnerable["❌ Vulnerable Flow"] direction LR A1["Project"] --> A2["Unescaped user input in HTML output"] A2 --> A3["💥 XSS Script Executed"] end Vulnerable ~~~ Fixed subgraph Fixed["✅ Fixed Flow"] direction LR B1["Project"] --> B2["Context-aware output encoding"] B3["🛡️ Attack Blocked"] B2 --> B3 end style A2 fill:#FFE5E5,color:#000 style A3 fill:#ffa94d,color:#000 style B2 fill:#74c0fc,color:#000 style B3 fill:#DCFCE7,color:#000How we fixed it
Root Cause
User-controlled input (HTTP request parameter name) flowed into
response.getWriter().format(bar, obj)without HTML encoding. The parameter name is assigned tobarthroughdoSomething(), which unconditionally returnsparambecause the arithmetic condition(500/42 + 196 = 207 > 200)is always true. Writing unencoded user input directly to an HTML response allows an attacker to inject arbitrary HTML and JavaScript.Fix Approach
The OWASP Java Encoder's
Encode.forHtml()contextually encodes all HTML metacharacters (<,>,&,",') before the string reaches the response writer, neutralizing any injected markup or script. Thewrite()call replacesformat()to eliminate the secondary format-string injection risk (user input used as a printf-style format pattern). This is the idiomatic defense recommended by OWASP for output encoding in HTML context.Code Change
Before:
After:
Alternatives Considered
Vulnerabilities Addressed
CWE-79
No Direct Response Writer
How we validated it
Validation approach:
format()call has been replaced withwrite(Encode.forHtml()).How to verify
Reviewers can verify this fix by:
response.getWriter().write(Encode.forHtml(bar))instead offormat(bar, obj).org.owasp.encoder.Encodeis imported at the top of the file.pom.xmlorbuild.gradle.<script>alert(1)</script>and verify the response contains HTML-encoded entities (<script>...</script>) instead of executable script.Before you merge
Learn more
This fix was generated by AppSecAI. Please review before merging.