xss-and-injection-prevention

Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).

Best use case

xss-and-injection-prevention is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).

Teams using xss-and-injection-prevention should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/xss-and-injection-prevention/SKILL.md --create-dirs "https://raw.githubusercontent.com/PranavNagrecha/AwesomeSalesforceSkills/main/skills/security/xss-and-injection-prevention/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/xss-and-injection-prevention/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How xss-and-injection-prevention Compares

Feature / Agentxss-and-injection-preventionStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Use when writing or reviewing Visualforce pages, Apex controllers, or LWC components that output user-supplied data, build dynamic queries, or construct HTTP responses. Triggers: 'XSS in Visualforce', 'SOQL injection vulnerability', 'how to encode output in Apex', 'JSENCODE Visualforce', 'open redirect prevention'. NOT for Apex CRUD/FLS enforcement (use soql-security or apex-crud-and-fls), NOT for Shield encryption (use shield-encryption-key-management), NOT for AppExchange security review process (use secure-coding-review-checklist).

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# XSS and Injection Prevention

Use this skill when writing or reviewing Visualforce pages, Apex controllers, or LWC components that render user-supplied data, build dynamic queries, or construct redirect URLs. It covers the full set of Salesforce-specific encoding functions, the SOQL injection bind-variable pattern, CRLF injection prevention, and open redirect mitigation.

---

## Before Starting

Gather this context before working on anything in this domain:

- Identify how user input enters the system: URL parameters, form fields, Apex method parameters from external callers, or data stored in sObject fields.
- Identify the output context for each user input: HTML body, JavaScript block, URL parameter, HTTP response header. Each context requires a different encoding function.
- Determine whether any dynamic SOQL or dynamic SOSL constructs exist in the Apex code. These are the injection surface, not static queries with bind variables.

---

## Core Concepts

### Output Context Determines Encoding Function

Salesforce provides four Visualforce encoding functions. Applying the wrong one is as bad as applying none:

| Output Context | Correct Function | Notes |
|---|---|---|
| HTML body | `HTMLENCODE()` | Auto-applied to `{!field}` in HTML body — explicit for string expressions |
| JavaScript string in VF script block | `JSENCODE()` | `{!field}` inside `<script>` is NOT auto-encoded — #1 XSS vector |
| HTML attribute with JavaScript | `JSINHTMLENCODE()` | Encodes for JS first, then HTML — for inline event handlers like `onclick` |
| URL parameter | `URLENCODE()` | Use when constructing URLs with user data |

The critical rule: Visualforce auto-escapes `{!field}` in HTML context only. Inside a `<script>` block, `{!field}` is rendered raw. Every JavaScript variable assignment from a VF expression must use `JSENCODE()`.

### SOQL Injection via String Concatenation

Dynamic SOQL built by string concatenation with user input is injectable. The attacker can escape the intended query structure and append arbitrary conditions.

**Vulnerable pattern:**
```apex
String query = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';
List<Account> results = Database.query(query);
```

**Safe pattern using bind variables:**
```apex
String query = 'SELECT Id FROM Account WHERE Name = :userInput';
List<Account> results = Database.query(query);
```

Bind variables (`:varName`) prevent injection because the platform treats the bound value as a literal data value, never as query syntax. This is the authoritative solution for dynamic SOQL. `String.escapeSingleQuotes()` is a secondary measure only — it does not fully prevent injection in all edge cases.

### LWC and Locker Service / Lightning Web Security

LWC runs inside Lightning Locker Service or Lightning Web Security depending on the org configuration. These sandbox the DOM and prevent cross-component script access. However, they do not prevent stored XSS in data coming from Apex. If an Apex controller returns maliciously crafted HTML from a user-supplied field and the LWC renders it with `innerHTML`, the attack succeeds. Safe LWC patterns use template bindings `{field}` which are auto-escaped by the framework.

---

## Common Patterns

### Encode All JavaScript Variable Assignments in Visualforce

**When to use:** Any Visualforce page that assigns Apex controller data into a JavaScript variable.

**How it works:**
```html
<!-- VULNERABLE: raw expression in script block -->
<script>
    var accountName = '{!account.Name}';
</script>

<!-- SAFE: JSENCODE applied -->
<script>
    var accountName = '{!JSENCODE(account.Name)}';
</script>
```

**Why not rely on auto-escape:** Auto-escaping only applies to HTML contexts. JavaScript rendering receives the raw string before HTML interpretation.

### Always Use Bind Variables in Dynamic SOQL

**When to use:** Any Apex code that builds a SOQL string dynamically with user-supplied data.

**How it works:**
```apex
// SAFE: bind variable
public List<Contact> searchContacts(String lastName) {
    return Database.query(
        'SELECT Id, Name FROM Contact WHERE LastName = :lastName'
    );
}
```

### Whitelist PageReference Targets to Prevent Open Redirect

**When to use:** Any Apex controller that constructs a `PageReference` using URL parameters or user input.

**How it works:**
```apex
private static final Set<String> ALLOWED_PATHS = new Set<String>{
    '/home/home.jsp',
    '/lightning/page/home'
};

public PageReference redirect() {
    String retUrl = ApexPages.currentPage().getParameters().get('retUrl');
    if (retUrl != null && ALLOWED_PATHS.contains(retUrl)) {
        return new PageReference(retUrl);
    }
    return Page.DefaultLanding; // safe fallback
}
```

---

## Decision Guidance

| Situation | Recommended Approach | Reason |
|---|---|---|
| VF variable in HTML body | `{!field}` auto-encoding sufficient | Auto-escaped in HTML context |
| VF variable in `<script>` block | `{!JSENCODE(field)}` mandatory | Auto-encoding does not apply in JS context |
| VF variable in onclick attribute | `{!JSINHTMLENCODE(field)}` | Double-encoding: JS first, then HTML |
| Dynamic SOQL with user input | Bind variable `:varName` | Primary injection prevention |
| LWC template expression | `{field}` binding | Framework auto-escapes template bindings |
| LWC with innerHTML | Sanitize or avoid user data | innerHTML bypasses framework protection |
| PageReference from user input | Allowlist validation | No platform-level redirect protection |

---

## Recommended Workflow

Step-by-step instructions for reviewing code for XSS and injection issues:

1. **Identify all input sources.** Find every place user-controlled data enters the system: URL params, form fields, Apex REST endpoints, externally-loaded data. Map them to the data flow.
2. **Identify all output points.** For each input source, trace where the data is eventually rendered — HTML block, JavaScript block, HTML attribute, URL, or HTTP header.
3. **Apply the correct encoding function for each output context.** Use the context table above. Pay special attention to `<script>` blocks — they are the most common XSS location.
4. **Audit all dynamic SOQL and SOSL.** Search for `Database.query(` with string concatenation. Every such query must use bind variables for user input.
5. **Audit PageReference construction.** Any `new PageReference(url)` where the URL is derived from user input must be validated against an allowlist.
6. **Check for CRLF injection.** If the code sets HTTP response headers using user input, verify `\r` and `\n` characters are stripped before use.
7. **Validate with Salesforce Code Analyzer.** Run `sf scanner run` with PMD rules — it includes ApexXSSFromURLParam, ApexSOQLInjection, and ApexOpenRedirect rules.

---

## Review Checklist

Run through these before marking work in this area complete:

- [ ] All `<script>` block variable assignments from Apex use `{!JSENCODE(field)}`
- [ ] No dynamic SOQL/SOSL uses string concatenation with user input — bind variables used
- [ ] All PageReference targets from user input validated against allowlist
- [ ] LWC components do not use `innerHTML` with user-sourced data
- [ ] HTTP response headers do not include user-supplied values without stripping `\r\n`
- [ ] Salesforce Code Analyzer (PMD) runs clean with no XSS or injection findings
- [ ] Stored user data rendered in Visualforce uses encoding appropriate for its output context

---

## Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

1. **`{!field}` is NOT auto-encoded in JavaScript contexts** — The single most common XSS vector in Visualforce. Every Apex expression inside a `<script>` block needs `{!JSENCODE(...)}` explicitly.
2. **`String.escapeSingleQuotes()` does not fully prevent SOQL injection** — It handles the common case but does not cover all edge cases. Always use bind variables as the primary defense.
3. **LWC Locker Service does not sanitize Apex-returned HTML** — Locker Service protects the DOM from cross-component access, not from XSS in Apex-returned data rendered via `innerHTML`.

---

## Output Artifacts

| Artifact | Description |
|---|---|
| Code review findings | List of each XSS/injection finding with file, input source, output context, and correct fix |
| Corrected code snippets | The unsafe code with the encoding function or bind variable fix applied |

---

## Related Skills

- soql-security — CRUD/FLS enforcement in SOQL queries (sharing model, not injection)
- secure-coding-review-checklist — AppExchange security review and Checkmarx patterns

Related Skills

recaptcha-and-bot-prevention

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when configuring reCAPTCHA on Web-to-Case, Web-to-Lead, Experience Cloud forms, or Headless Identity flows, or when designing bot-mitigation strategies for Salesforce public-facing surfaces. Triggers: 'enable reCAPTCHA on Web-to-Case', 'bot spam submissions on my Experience Site', 'Headless Identity reCAPTCHA v3 setup'. NOT for AppExchange security review (use secure-coding-review-checklist), NOT for session-level login security policies (use session-management-and-timeout), NOT for IP-range-based access controls (use network-security-and-trusted-ips).

recursion-and-re-entry-prevention

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when a record-triggered Flow re-fires on the same record because its own DML (or a downstream Flow's DML) re-satisfies the entry criteria — causing CPU-limit failures, duplicated side effects, or 'Maximum Trigger Depth Exceeded' errors. Triggers: 'flow infinite loop', 'flow re-firing on same record', 'flow updates field then runs again', 'flow A and flow B keep updating each other', 'maximum trigger depth exceeded record-triggered flow', 'flow recursion limit hit'. NOT for Apex trigger recursion (use apex/recursive-trigger-prevention) or for Loop element design inside a single Flow run (use flow/flow-loop-element-patterns).

environment-specific-value-injection

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring, reviewing, or troubleshooting how environment-specific values — endpoint URLs, client IDs, thresholds, feature flags — are managed across Salesforce orgs without hardcoding. Triggers: 'named credential per environment', 'custom metadata for config', 'sfdx string replacement', 'CI variable substitution', 'secrets in org configuration', 'org-specific values'. NOT for sandbox refresh automation (use sandbox-refresh-and-templates), NOT for general deployment pipeline setup (use github-actions-for-salesforce or bitbucket-pipelines-for-salesforce), and NOT for per-user or per-profile configuration overrides.

recursive-trigger-prevention

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when debugging or preventing recursive Apex trigger behavior, especially around self-DML, static guard flaws, Set<Id>-based deduplication, and legitimate re-entry scenarios. Triggers: 'trigger recursion', 'static boolean guard', 'recursive update', 'self DML', 'trigger firing multiple times'. NOT for general trigger-framework structure unless recursion is the actual design problem.

prompt-injection-defense

8
from PranavNagrecha/AwesomeSalesforceSkills

Red-team an Agentforce agent against prompt-injection and jailbreak attacks; codify test cases and guardrails. NOT for general application-security reviews outside the agent boundary.

visualforce-security-and-modernization

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when hardening or modernizing legacy Visualforce pages — covers the platform CSRF token model and when disabling it is a security regression, view state encryption guarantees and the 170 KB ceiling, FLS/CRUD enforcement gaps on `<apex:outputField>` and on getters that return sObjects, `<apex:includeScript>` interaction with the org Content Security Policy, hosting LWC inside a VF page via `lightning:container` / `lightning-out`, and the retire-vs-harden-vs-leave-alone decision for an inventory of legacy pages. Triggers: 'should I rewrite this Visualforce page in LWC', 'CSRF protection disabled on Visualforce page is that safe', 'community user sees a field they should not on a Visualforce page', 'view state encryption is that enough for sensitive data', 'how do I host an LWC inside a Visualforce page', 'apex:dynamicComponent and apex:actionFunction safe to keep'. NOT for greenfield Visualforce architecture (use apex/visualforce-fundamentals — controller types, view state pattern selection, PDF rendering); NOT for Visualforce email template authoring (use apex/visualforce-email-templates if/when that skill is authored); NOT for general Apex security review across triggers and async (use apex/soql-security and security/secure-coding-review-checklist).

transaction-security-policies

8
from PranavNagrecha/AwesomeSalesforceSkills

Transaction Security policy creation and configuration: condition builder, enhanced policies, enforcement actions (block, MFA, notification, end session), real-time monitoring mode, and policy troubleshooting. NOT for Event Monitoring log analysis or Shield Event Monitoring setup (use event-monitoring). NOT for Apex testing or debug-log analysis.

sso-saml-troubleshooting

8
from PranavNagrecha/AwesomeSalesforceSkills

Diagnosing broken SAML SSO into Salesforce — IdP-initiated vs SP-initiated flows, signing-certificate validity / expiry, NameID format mismatches, RelayState handling, audience / entityId / issuer mismatches, clock skew, the SAML Assertion Validator in Setup, the Login History debug log, and the My Domain prerequisite for SSO. Covers the standard diagnostic loop: read the SAML response, identify which check failed, fix at the IdP or SP. NOT for OAuth / OpenID Connect SSO (see security/oauth-openid-troubleshooting), NOT for setting up SSO from scratch (see security/sso-saml-setup).

shield-kms-byok-setup

8
from PranavNagrecha/AwesomeSalesforceSkills

Configure Shield Platform Encryption with customer-supplied (BYOK) or customer-held (Cache-Only Key Service) tenant secrets, rotate them, and recover. NOT for Classic Encryption or field masking.

shield-event-log-retention-strategy

8
from PranavNagrecha/AwesomeSalesforceSkills

Use when designing Salesforce Shield Event Monitoring retention, SIEM routing, and storage-tier strategy — which event types to keep, for how long, where, and how to answer audit queries across hot/warm/cold tiers. Triggers: 'shield event log retention', 'route event monitoring to splunk', 'how long to keep login history', 'siem salesforce integration', 'event monitoring storage tier'. NOT for enabling Shield (see salesforce-shield-deployment).

session-management-and-timeout

8
from PranavNagrecha/AwesomeSalesforceSkills

Use this skill when configuring session timeout values, concurrent session limits, session IP locking, or logout behavior in Salesforce. Covers org-wide session settings, profile-level overrides, Connected App session policies, and Metadata API SecuritySettings deployment. NOT for OAuth token refresh flows, login IP ranges, or MFA/identity-provider configuration.

session-high-assurance-policies

8
from PranavNagrecha/AwesomeSalesforceSkills

Enforce step-up authentication for sensitive pages/objects using High Assurance session level and login flow policies. NOT for initial MFA enrollment UX.