Advanced 18 min read

Secure Apex/LWC Communication and Safe DOM Manipulation

By the end of this lesson, you'll be able to:

  • Combine server-side and client-side security practices into one coherent approach
  • Build a component that enforces security correctly on both sides of the Apex/LWC boundary
  • Apply a practical security checklist to a new component

Prerequisites: "XSS and Injection Risks in LWC"

Recap: Two Sides of the Same Boundary

  • Server side (Apex)AccessLevel.USER_MODE or with sharing (Lesson 2) for CRUD/FLS/sharing enforcement; AuraHandledException (Module 7) to surface safe, deliberate error messages without leaking internal details.
  • Client side (LWC) — template bindings that auto-escape by default (Lesson 4), avoiding innerHTML and lwc:dom="manual" on untrusted content.

A component is only as secure as the weaker of these two sides — a perfectly locked-down Apex method still leaks data if the component then dumps the result into innerHTML unsafely, and perfectly safe rendering still leaks data if the Apex behind it skips FLS enforcement.

A Secure Worked Example

public with sharing class CaseSummaryController {
    @AuraEnabled(cacheable=true)
    public static List<CaseSummary> getOpenCases(Id accountId) {
        if (accountId == null) {
            throw new AuraHandledException('An Account is required.');
        }

        List<Case> cases = Database.query(
            'SELECT Id, Subject, Status FROM Case WHERE AccountId = :accountId AND IsClosed = false',
            AccessLevel.USER_MODE
        );

        List<CaseSummary> results = new List<CaseSummary>();
        for (Case c : cases) {
            results.add(new CaseSummary(c.Id, c.Subject, c.Status));
        }
        return results;
    }
}

public class CaseSummary {
    @AuraEnabled public Id caseId;
    @AuraEnabled public String subject;
    @AuraEnabled public String status;

    public CaseSummary(Id caseId, String subject, String status) {
        this.caseId = caseId;
        this.subject = subject;
        this.status = status;
    }
}
<template for:each={cases} for:item="caseItem">
    <div key={caseItem.caseId} class="case-row">
        <span>{caseItem.subject}</span> — <span>{caseItem.status}</span>
    </div>
</template>

AccessLevel.USER_MODE (Lesson 2) enforces CRUD/FLS/sharing on the query; AuraHandledException (Module 7) gives a safe, deliberate validation message; the wrapper class (Module 7) shapes the response cleanly; and the template renders every value through ordinary {expression} bindings — no innerHTML, nothing to reintroduce an XSS risk.

A Security Checklist for a New Component

  1. Does every SOQL query use AccessLevel.USER_MODE or run inside a with sharing class with WITH SECURITY_ENFORCED?
  2. Do error messages use AuraHandledException rather than leaking a raw exception's internal details?
  3. Is all dynamic content rendered through template bindings, with no innerHTML or lwc:dom="manual" on untrusted data?
  4. If a reusable utility class is involved, is its sharing behavior explicit (inherited sharing) rather than ambiguous?

Exercise

Identify, as a comment, every security practice from this module present in the getOpenCases example above.

Show hint

There are at least three distinct practices layered together.

APEX

Exercise

Challenge: explain, as a comment, why a perfectly secure Apex method can still result in an insecure component overall.

Show hint

Think about what happens after the data arrives in JavaScript.

JAVASCRIPT

Secure Apex/LWC Communication and Safe DOM Manipulation Quiz

1. What does AccessLevel.USER_MODE enforce in the worked example?

2. What does AuraHandledException provide in this example?

3. Why does the template use {expression} bindings instead of innerHTML?

4. Can a perfectly secure Apex method still result in an insecure component overall?

5. What does the security checklist recommend for a reusable utility class's sharing behavior?

Log in to submit the quiz and save your score.

My Notes

Log in to keep private notes on this lesson.

Questions about this lesson

No questions yet — be the first to ask.

Log in to ask a question about this lesson.

Summary

Security is a boundary with two sides — a correctly enforced Apex layer (CRUD/FLS/sharing, safe error messages) and a correctly rendered LWC layer (auto-escaped bindings, no raw innerHTML) — both need to hold for a component to be genuinely secure.