Dispatcher caching breaks prefilled Adaptive Form after FDM change
A bank runs an Adaptive Form (AF) for address changes on AEM 6.5 Forms, published to a Dispatcher. The AF is bound to a Form Data Model (FDM) backed by a REST data source that returns the customer's current address. Prefill is configured via the FDM read service using a customerId request parameter. In staging (Dispatcher bypassed), prefill works. In production, customers intermittently see another customer's address, and the /content/forms/af/address-change.html path returns HTTP 200 with Cache-Control: max-age=300 from the Dispatcher. The form uses guidePrefillService with a POST to the AF URL. There are ~40k daily submissions, and the security team has flagged the cross-customer leak as P1. The Dispatcher farm has a default /0003 { /glob "*" /type "deny" } rule below a broad /0002 allow for /content/forms/*.
1. Diagnose the root cause of the cross-customer data exposure and state the two independent fixes required.
Read the worked answer
The exposure is caused by the Dispatcher caching the AF HTML that has been server-side prefilled with per-user FDM data. The max-age=300 header on the AF path proves the response is cacheable, and because prefill is server-side, the rendered HTML contains customer-specific values. Two independent fixes are needed:
Do not cache prefilled AF responses. Mark AF prefill responses as private/no-store (e.g., set
Cache-Control: private, no-storeon the AF servlet/filter path, or ensure the AF is requested with a non-cacheable selector/POST). Even with correct Dispatcher rules, downstream caches and browsers must not store this.Tighten Dispatcher rules. The broad
/0002allow for/content/forms/*overrides the intent of the deny rule; add an explicit deny for the AF render/prefill path (and any.prefill,.modelselectors) above the allow, and only allow static clientlibs. Verify withdispatcher:flushand a cache-buster.
Additionally, prefill via POST avoids URL caching, but the response must still be non-cacheable; POST alone is not sufficient if the servlet writes cacheable headers. Rotating the affected cache and notifying compliance is required given the P1 leak.
2. The team proposes moving prefill from server-side to client-side FDM invocation to avoid caching. Evaluate this and describe what must change.
Read the worked answer
Client-side FDM invocation moves the read call to the browser, so the AF HTML becomes static and cacheable - good for scale. But it does not remove the need for access control: the FDM REST endpoint must authenticate and authorize the caller, otherwise any user can enumerate customerId. Required changes:
- Expose the FDM read service via a secure AF data source with authentication (e.g., OAuth2 or a signed session token), and enforce server-side that the authenticated user matches the requested
customerId. - Ensure the client-side call is same-origin or CORS-restricted, and never place credentials in the AF definition.
- Keep the AF shell cacheable but mark any response containing PII as
no-store. - Add rate limiting and audit logging on the FDM endpoint.
Client-side prefill is acceptable only if authorization is enforced at the data layer; otherwise it simply relocates the leak. Given the P1, the safest path is server-side prefill with no-store plus Dispatcher deny, then migrate to client-side with proper authz.