Poisoned Registration: Finding Stored XSS and SSTI During Signup
Signup forms feed more systems than the page you can see. A display name may later appear in an admin queue, welcome email, invoice, support dashboard, audit log, or CRM export. “Poisoned registration” means placing a controlled test string into those fields at account creation and watching for unsafe rendering downstream. The interesting sink often belongs to a staff member, not the registering user.
Begin with a canary, not an exploit. Put a unique marker such as BF19-NAME-7Q2 in first name, company, address line two, referral code, and any free-text onboarding field your own account can reach. Then map every place the value reappears. View your profile, request a password email, generate an invoice, open a support ticket, and inspect API responses. This tells you which renderer handles each copy.
Escalate one context at a time
If HTML output contains the marker, identify its exact context before choosing a payload. Text between tags, an attribute, JavaScript, a URL, and an email template all need different probes. A harmless formatting string such as <b>BF19</b> can show whether HTML is interpreted without executing script. Move to a non-destructive execution proof only after you understand the sink, preferably console.log or a change visible solely to your account.
Stored XSS in a staff dashboard has a sharp trust boundary. A public user creates the record; a privileged employee views it; attacker-controlled script runs with the employee's session and application permissions. Do not attempt to lure real staff. If the program permits testing, ask triage to view a benign record or demonstrate the same vulnerable component in a role you control.
SSTI has a different signal. Template syntax is evaluated on the server before the result reaches a browser. Start with arithmetic probes suited to likely engines: {{7*7}}, ${7*7}, or <%= 7*7 %>. A rendered 49 in an email or PDF is evidence; seeing the literal characters is not. Use several controls because some front ends perform their own substitutions.
Stop at safe evaluation. Do not read environment variables, execute operating-system commands, or pull files merely to make the screenshot dramatic. Engine identification plus a harmless expression usually proves the primitive. If triage needs stronger impact, coordinate the next step.
Registration quirks worth testing
Server and client validation often disagree. Intercept the signup request and try longer values, Unicode direction markers, quote characters, or fields removed from the visible form. Check whether the API accepts a role, template, locale, or redirect property the UI never sends. Keep every value within reasonable size; this is not a parser stress test.
Also test post-registration edits. The signup endpoint may sanitize a name while the profile API stores raw input, or the reverse. Case changes and duplicate fields can route values through different validators.
Make the data flow obvious
A strong report traces source to sink: the exact registration request, the stored field, where it is rendered, and what security context executes it. For XSS, state whose browser is affected and what that role can access. For SSTI, name the evaluated expression and likely template engine without overstating command execution you did not test.
Recommend context-aware output encoding at every renderer, allowlisting where rich text is unnecessary, and treating emails, PDFs, logs, and internal tools as hostile-input surfaces. Template engines should run with sandboxing and minimal object access. Sanitizing only the signup page misses the point; the dangerous interpretation happens later.