JavaScript Aspect — Security Questionnaire (Vendor Response)
This page is the canonical, pre-filled vendor response to the JavaScript Aspect Architecture, Security, and Compatibility Questionnaire that FI security / AppSec teams use during partner due-diligence reviews.
Rather than asking every FI to independently re-derive how a Forge-CLI-emitted Aspect answers each question, this page ships:
- The 60 questions verbatim (anchored, so other docs can deep-link).
- A coverage matrix showing which Forge templates address which question groups.
- Per-template completed responses for the three templates that cross trust boundaries —
oidc-snippet,hidden-iframe-sso,mobile-vendor-chat-jsbridge. - A shared response summary for the remaining 12 templates grouped by family.
How to use this page:
- FI AppSec reviewer — open the per-template response for the template being submitted, verify each pre-filled answer matches the deployment, sign off using the Deployment Security Checklist.
- Partner integrator — when authoring custom snippets that don't go through
forge aspect submit, treat the per-template responses as a target spec. - Candescent contributor — when adding a new template or security control, update both the Security Architecture page and this page so question coverage stays accurate.
Each answer is tagged:
- ✓ CLI — the Forge CLI enforces this property in every emitted snippet. FI verification is mechanical (e.g.
grepfor an inlined helper). - ◯ FI — the property exists but requires FI configuration, deployment validation, or downstream wiring. Listed so AppSec teams know what they own.
- n/a — the question does not apply to this template (e.g. SRI on a template that loads no external scripts).
The Questionnaire
Source: JavaScript Aspect Architecture, Security, and Compatibility Questionnaire — Candescent partner due-diligence intake. Classified as Highly Confidential. Quoted verbatim below for traceability.
Section 1 — End-to-End Architecture Overview
Q1. Architecture diagram
Provide a high-level architecture diagram showing: parent FI Digital Banking application; embedded static loader script; runtime services and APIs; UI rendering mechanism (DOM, Shadow DOM, iframe); logging / analytics endpoints.
Q2. Parties involved
List all parties involved (e.g., Elan, TransUnion, subcontractors).
Q3. Per-party responsibilities
For each party, describe: responsibilities; systems owned; data processed; operational support ownership.
Q4. Layer ownership
Identify which party hosts the static loader script, runtime APIs, owns offer logic, owns UI rendering, owns logging and analytics.
Section 2 — Script Execution Model & Trust Boundaries
Q5. Parent-window execution
What JavaScript executes directly in the parent window context?
Q6. Execution placement
What functionality executes in the parent DOM / inside Shadow DOM / inside a sandboxed iframe?
Q7. Trust boundaries
Describe the trust boundaries between: parent FI site; static loader; runtime services; partner systems.
Q8. Approved runtime domains
How are approved runtime domains defined, enforced, and validated?
Section 3 — Static vs. Dynamic Content (SRI Model)
Q9. Static loader responsibilities
Describe the responsibilities of the static loader script: initialization; context setup; event registration; runtime fetch orchestration.
Q10. Dynamic runtime content
Describe what logic exists in dynamic runtime content: offer eligibility; campaign logic; UI configuration; personalization rules.
Q11. Immutability + SRI
Confirm: static loader is immutable and versioned; static loader supports Subresource Integrity (SRI); dynamic content does not introduce new executable entry points.
Section 4 — Context, State & Authentication Handling
Q12. Contextual data passed
What contextual data is passed from the parent site to the JS Aspect? (Customer identifiers, session identifiers, authentication state, page context.)
Q13. Context-passing mechanism
How is context passed? (Script attributes, global variables, postMessage, URL parameters.)
Q14. Context validation & sanitization
How is context validated, sanitized, and protected from spoofing or replay?
Q15. Auth context shared with parent
How is authenticated context shared with the parent window? (postMessage, cookies, tokens, other.)
Q16. Forgery / misuse protection
What guarantees ensure authenticated context cannot be forged or misused?
Section 5 — Communication Back to the Parent Website
Q17. Communication mechanism
How does the JS Aspect communicate actions or results back to the parent site? (postMessage, DOM events, callbacks.)
Q18. Message format / schema
What message formats and schemas are used?
Q19. Message origin / source validation
How is message origin and source validated? (event.origin, event.source, schema validation.)
Q20. Triggerable parent-site actions
What parent-site actions can be triggered as a result?
Section 6 — Rendering & XSS Protections
Q21. Render location of dynamic data
Where is dynamic remote data rendered?
Q22. innerHTML usage
Is innerHTML used? If yes, list all usage locations.
Q23. XSS prevention measures
Explain security measures in place to prevent XSS, including: output encoding, sanitization libraries, HTML allow-listing, escaping strategies.
Q24. Dangerous primitives
Confirm whether the solution uses: eval, new Function, inline script injection.
Section 7 — UI & Design System Integration
Q25. Vendor styling level
Is the UI dialog fully vendor-styled, partially customizable, or fully themeable?
Q26. Customizable UI elements
What UI elements can be customized to match the parent site's design system? (Colors, fonts, layout, button labels.)
Q27. CSS isolation
How is CSS isolation handled? (Shadow DOM, iframe, scoped CSS conventions.)
Q28. Parent-CSS impact
Can parent-site CSS break or visually impact the UI?
Section 8 — Error Handling, Timeouts & Resiliency
Q29. Failure modes
What happens if the static loader fails to load? Runtime APIs time out? A partner API is unavailable?
Q30. Timeout thresholds
What timeout thresholds are used?
Q31. UX during failures
What user experience is presented during partial failures, full failures, slow responses?
Q32. Fail-open vs fail-closed
Is the behavior fail-open or fail-closed?
Q33. Retry handling
How are retries handled?
Section 9 — Troubleshooting & Operational Support
Q34. Troubleshooting workflow
How is troubleshooting performed when an FI reports an issue?
Q35. Telemetry & diagnostics
What telemetry or diagnostics are available? (Client-side logs, correlation IDs, error codes.)
Q36. First responder
Which party is the first responder for UI issues, API failures, authentication issues?
Q37. Coordination cost
How many parties must coordinate to resolve a typical incident?
Section 10 — Logging, Analytics & User Activity
Q38. Activities logged externally
What user activities are logged externally, in addition to CTA clicks? (Page load, dialog open/close, scroll, hover, form input, errors.)
Q39. Log data elements
What data elements are included in logs?
Q40. Identity binding in logs
Are logs tied to customer identity, session identity, anonymous identifiers?
Q41. Log retention
Where are logs stored and for how long?
Section 11 — JavaScript Libraries & Dependency Management
Q42. Third-party libraries
List all third-party JavaScript libraries used.
Q43. Library delivery
Are libraries bundled, loaded dynamically, referenced from CDNs?
Q44. Library conflict prevention
How are library conflicts prevented when running inside the parent window? (Namespacing, bundling, Shadow DOM, iframe isolation.)
Q45. Global variables
Are any globally scoped variables introduced? If yes, list them.
Section 12 — Script Compatibility with FI Environment
Q46. FI script compatibility
Describe how the JS Aspect ensures compatibility with existing FI scripts, including analytics, fraud tools, accessibility tooling, and tag managers.
Q47. Parent-site global dependencies
Does the script depend on or interact with any parent-site globals? If yes, list dependencies.
Q48. FI framework conflicts
How does the script avoid conflicts with common FI frameworks? (React / Angular / Vue, jQuery, AMD / RequireJS, tag managers.)
Q49. Global event listeners
Does the script register global event listeners? (window, document, message, keydown, click, etc.)
Q50. Event scoping / namespacing
How are events scoped or namespaced to avoid interference?
Q51. Failure containment
How is failure contained so errors do not break other FI scripts or page rendering?
Q52. Performance impact
What impact does the script have on page load, main thread usage, rendering performance?
Q53. Async / non-blocking execution
Is execution asynchronous? Non-blocking?
Q54. Behavior in script-heavy environments
How does the script behave in script-heavy FI environments?
Section 13 — Change Management & Governance
Q55. Change classification
What changes require a static loader update vs runtime config update only?
Q56. Breaking-change communication
How are breaking changes communicated?
Q57. Backward compatibility
How is backward compatibility maintained?
Q58. Rollback strategy
What is the rollback strategy if an update causes issues?
Section 14 — Compliance & Assurance
Q59. Security review
Has the solution been reviewed by internal AppSec? External assessors?
Q60. Pen-test / code-review artifacts
Are penetration test or code review artifacts available?
Coverage Matrix
Summary view: rows = questionnaire sections, columns = template families. Cells indicate whether the Forge CLI enforces the controls in that section by default (✓), requires FI configuration / verification (◯), or the section does not apply (—).
| Section | UI templates¹ | Personalized UI² | Vendor loaders³ | oidc-snippet | hidden-iframe-sso | mobile-vendor-chat-jsbridge |
|---|---|---|---|---|---|---|
| 1 — Architecture (Q1-4) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 2 — Trust boundaries (Q5-8) | ✓ | ✓ | ◯ | ◯ | ✓ | ◯ |
| 3 — Static vs dynamic / SRI (Q9-11) | ✓ | ✓ | ◯ FI sets --integrity | ✓ | ✓ | ◯ FI sets --integrity |
| 4 — Context handling (Q12-16) | — | ✓ | — | ✓ | ✓ | ✓ |
| 5 — Communication back to parent (Q17-20) | — | — | — | ◯ FI wires backend | ✓ | ✓ |
| 6 — Rendering / XSS (Q21-24) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 7 — UI / design system (Q25-28) | ◯ | ◯ | n/a | ◯ | n/a | ◯ |
| 8 — Resiliency (Q29-33) | ✓ | ✓ | ◯ | ✓ | ✓ | ✓ |
| 9 — Troubleshooting (Q34-37) | partial | partial | partial | ✓ correlation id | ✓ correlation id | ✓ correlation id |
| 10 — Logging (Q38-41) | ◯ FI pipeline | ◯ FI pipeline | ◯ FI pipeline | ◯ FI pipeline | ◯ FI pipeline | ◯ FI pipeline |
| 11 — Libraries (Q42-45) | ✓ | ✓ | ◯ vendor SDK | ✓ | ✓ | ◯ vendor SDK |
| 12 — FI compatibility (Q46-54) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 13 — Change management (Q55-58) | ✓ submit-time | ✓ submit-time | ✓ submit-time | ✓ submit-time | ✓ submit-time | ✓ submit-time |
| 14 — Compliance (Q59-60) | ◯ FI review | ◯ FI review | ◯ FI review | ◯ FI review | ◯ FI review | ◯ FI review |
¹ banner, toast, card, modal, countdown, floating-action-button
² welcome-banner, personalized-toast
³ vendor-script-loader, vendor-script-with-config, tag-manager, vendor-sdk-personalized
Per-Template Responses — High-Leverage Templates
The three templates that cross trust boundaries get full per-question responses. All other templates share grouped summaries below.
oidc-snippet — Completed Response
Full OIDC authorization-code-flow scaffold. Targets local Toolkit (auto-config) or FI Keycloak (--client-id / --fi-domain).
Section 1 — Architecture (Q1-4)
| # | Status | Evidence / How |
|---|---|---|
| Q1 | ✓ CLI | Architecture diagram in Security Architecture. Parent window → static loader IIFE → __cdxFetch to OIDC endpoint → console.* logs (no analytics endpoint). |
| Q2 | ✓ CLI | Three parties: FI (host shell, dbk API, OIDC backend exchange); Candescent (Forge CLI, generated snippet); OIDC IdP (Keycloak / Toolkit, returns authorization code). |
| Q3 | ✓ CLI | See party-responsibility table in Security Architecture. |
| Q4 | ✓ CLI | Static loader hosted by FI; runtime API (/auth/realms/.../auth) hosted by FI or federated IdP; offer logic / UI rendering owned by FI; logging owned by FI (browser-log pipeline). |
Section 2 — Trust Boundaries (Q5-8)
| # | Status | Evidence / How |
|---|---|---|
| Q5 | ✓ CLI | The full IIFE runs in the parent window. No iframe, no Shadow DOM. |
| Q6 | ✓ CLI | Parent DOM only. oidc-snippet does not use iframe or Shadow DOM. |
| Q7 | ✓ CLI | FI ↔ OIDC IdP boundary crossed via HTTPS fetch; auth code returned to parent JS, then FI's responsibility to forward to backend. See Trust Zones. |
| Q8 | ◯ FI | OIDC endpoint domain set via --fi-domain at submission time. FI verifies the submitted snippet's hardcoded domain matches the approved IdP. |
Section 3 — Static vs Dynamic / SRI (Q9-11)
| # | Status | Evidence / How |
|---|---|---|
| Q9 | ✓ CLI | Static loader handles: auth-URL construction, fetch-with-retry, response parsing, toast UX. No personalization or campaign logic. |
| Q10 | ✓ CLI | Dynamic content = OIDC authorization code (opaque string) returned by IdP. Code does not introduce new executable entry points; it is forwarded to the FI backend by FI-controlled glue code. |
| Q11 | ✓ CLI | Each forge aspect submit produces an immutable IIFE. SRI on script tags is n/a (no external script loaded by oidc-snippet); the loader itself is FI-hosted and would be SRI-protected by the FI's own page. |
Section 4 — Context Handling (Q12-16)
| # | Status | Evidence / How |
|---|---|---|
| Q12 | ✓ CLI | clientId (configured at submit time), redirectUri (computed from window.location.origin). |
| Q13 | ✓ CLI | URL query parameters on the /authorize request. credentials: 'include' forwards FI session cookies. |
| Q14 | ✓ CLI | clientId is hardcoded into the snippet at generation time; redirectUri is derived from window.location.origin (browser-trusted). Authorization code returned by IdP is treated as opaque — FI backend validates it. |
| Q15 | ◯ FI | The authorization code surfaces in console.log and as the toast detail. FI is responsible for wiring the code from the front-end to the backend (typically via fetch to an FI API). |
| Q16 | ◯ FI | OIDC's standard PKCE / state / nonce parameters are the FI backend's responsibility. The CLI's emitted snippet does not inject or validate these — current scaffolding is auth-code only; FIs that need PKCE must extend the snippet. |
Section 5 — Communication Back to Parent (Q17-20)
| # | Status | Evidence / How |
|---|---|---|
| Q17 | ◯ FI | oidc-snippet does not communicate back. It logs the authorization code; FI custom code reads the log or extends the snippet. |
| Q18 | n/a | No postMessage in this template. |
| Q19 | n/a | No postMessage listener. |
| Q20 | n/a | None directly; FI backend's response drives any parent-site action. |
Section 6 — Rendering & XSS (Q21-24)
| # | Status | Evidence / How |
|---|---|---|
| Q21 | ✓ CLI | A toast inside the parent DOM. Toast contents: clientId, truncated authorization code, redirect URL — all string-coerced and __cdxEsc-escaped. |
| Q22 | ✓ CLI | Yes — toast HTML is built via el.innerHTML = '...' with string concatenation. All interpolated values pass through __cdxEsc. |
| Q23 | ✓ CLI | Output encoding via __cdxEsc (escapes & < > " ' /). No third-party sanitizer needed. |
| Q24 | ✓ CLI | No eval, no new Function, no inline <script> injection, no inline onclick= (all event handlers via addEventListener). |
Section 7 — UI / Design System (Q25-28)
| # | Status | Evidence / How |
|---|---|---|
| Q25 | ◯ | Toast is fully Forge-styled (no FI theming hooks at this time). |
| Q26 | ◯ | Limited customization — no --bg-color / --text-color flags on oidc-snippet. |
| Q27 | ◯ FI | No Shadow DOM. Tracked work; until shipped, FI must verify parent-CSS impact. CSP nonce on inline <style> is ✓ via --csp-nonce. |
| Q28 | ◯ FI | Parent CSS can affect the toast. FI must validate at deploy time. |
Section 8 — Resiliency (Q29-33)
| # | Status | Evidence / How |
|---|---|---|
| Q29 | ✓ CLI | OIDC endpoint timeout / 5xx / network error → user-facing toast with timeout-specific hint, all logged with correlation id. |
| Q30 | ✓ CLI | Default 10 000 ms via inlined __cdxFetch. Override --timeout-ms <1000-60000>. |
| Q31 | ✓ CLI | Red-background error toast distinguishes timeout (Request timed out after Xms) from other failures (HTTP 4xx/5xx). Hint: "increase --timeout-ms or check the network." |
| Q32 | ✓ CLI | Fail-closed on auth (no code → no downstream action). Fail-open on telemetry (correlation id missing → still emits log without prefix). |
| Q33 | ✓ CLI | Default 3 retries on 5xx / network errors with exponential backoff (1s → 2s → 4s, capped at 8s). 4xx never retried. Override --max-retries <0-5> / --retry-delay-ms. |
Section 9 — Troubleshooting & Operational Support (Q34-37)
| # | Status | Evidence / How |
|---|---|---|
| Q34 | ✓ CLI | FI on-call greps browser logs for [cdx-aspect:<correlation-id>] to isolate a specific deployment. See Correlation IDs. |
| Q35 | ✓ CLI | Auto-generated correlation id on every console.* line. Override via --correlation-id "$RELEASE_ID" to chain logs from CI / release pipeline. |
| Q36 | ◯ FI | UI issues / browser-log review → FI. OIDC endpoint failures → FI (IdP owner). Token-exchange failures → FI (backend). |
| Q37 | ◯ FI | Typically 1-2 parties (FI + IdP). The CLI itself does not enter incident response post-deployment. |
Section 10 — Logging (Q38-41)
| # | Status | Evidence / How |
|---|---|---|
| Q38 | ◯ FI | Forge CLI logs only to console.*. No external sink is shipped — FI's existing browser-log pipeline (Sentry, Datadog Browser, etc.) consumes the logs. |
| Q39 | ✓ CLI | Per log line: correlation id; the message; truncated code (≤ 20 chars); truncated redirect URL (≤ 50 chars). No PII, no full token. |
| Q40 | ◯ FI | Logs are not tied to customer identity by default. FI's browser-log pipeline can correlate via session cookie if their logger captures it. |
| Q41 | ◯ FI | Retention is FI's browser-log policy. |
Section 11 — Libraries & Dependencies (Q42-45)
| # | Status | Evidence / How |
|---|---|---|
| Q42 | ✓ CLI | None. The emitted IIFE is plain ES6+ standalone code. |
| Q43 | ✓ CLI | Bundled — single static IIFE, no dynamic imports, no CDN references. |
| Q44 | ✓ CLI | IIFE scope plus __cdx* prefix on every internal helper (__cdxFetch, __cdxEsc, etc.). |
| Q45 | ✓ CLI | None introduced. (No window.* writes.) |
Section 12 — FI Compatibility (Q46-54)
| # | Status | Evidence / How |
|---|---|---|
| Q46 | ✓ CLI | IIFE-scoped; no global pollution; no inline onclick= (compatible with strict CSP); CSP-nonce-aware via --csp-nonce. Co-exists with analytics, fraud, a11y, tag-manager scripts. |
| Q47 | ✓ CLI | None. oidc-snippet does not read dbk.*. |
| Q48 | ✓ CLI | No framework dependency. Works under React / Angular / Vue / jQuery / AMD without modification. |
| Q49 | ✓ CLI | Only el.addEventListener('animationend', ...) and closeBtn.addEventListener('click', ...) — both attached to elements the snippet itself created. No window / document / message listeners. |
| Q50 | ✓ CLI | Listeners attached to specific elements (toast, dismiss button) — not delegated. |
| Q51 | ✓ CLI | All async paths wrapped in .catch(...) that logs and shows the error toast. No throw escapes the IIFE. |
| Q52 | ✓ CLI | Minimal page-load impact. Single fetch, no DOM observers, no event-loop work post-render. |
| Q53 | ✓ CLI | __cdxFetch is Promise-based; setTimeout for the timeout abort. |
| Q54 | ✓ CLI | Self-contained. No global mutation, no DOM mutation outside the toast element. |
Section 13 — Change Management (Q55-58)
| # | Status | Evidence / How |
|---|---|---|
| Q55 | ✓ CLI | All changes are static-loader updates. There is no separate runtime config. Each forge aspect submit produces a new IIFE. |
| Q56 | ◯ FI | FI's responsibility to communicate Aspect changes through their internal release process. |
| Q57 | ✓ CLI submit-time | The dbk-API contract is the long-running compatibility surface; templates always type-check dbk.* before use, so missing methods degrade gracefully. |
| Q58 | ◯ FI | Standard Git revert on the FI extension repo's submission PR + redeploy. |
Section 14 — Compliance & Assurance (Q59-60)
| # | Status | Evidence / How |
|---|---|---|
| Q59 | ◯ FI | The Forge CLI's internal AppSec review is documented in cdx-forge-cli/SECURITY_IMPLEMENTATION_PLAN.md. Each FI deployment requires the FI's own AppSec review of the submitted PR — see Deployment Security Checklist. |
| Q60 | ◯ FI | FI's responsibility post-deployment. |
hidden-iframe-sso — Completed Response
Mounts a 0×0 sandboxed iframe pointed at a vendor SSO handoff URL; receives a token via postMessage; dispatches a validated custom event for FI consumers.
Section 1 — Architecture (Q1-4)
| # | Status | Evidence / How |
|---|---|---|
| Q1 | ✓ CLI | Parent window IIFE → mounts hidden iframe → receives postMessage from sandboxed iframe → dispatches cdx-aspect:sso-token CustomEvent. See Trust Zones. |
| Q2 | ✓ CLI | FI, Candescent (CLI), SSO endpoint provider (FI's IdP or federated partner). |
| Q3 | ✓ CLI | Same as oidc-snippet. SSO endpoint provider owns the iframe handoff page + postMessage payload schema. |
| Q4 | ✓ CLI | Static loader = FI-hosted; SSO endpoint = FI or federated IdP; UI rendering = none (iframe is invisible). |
Section 2 — Trust Boundaries (Q5-8)
| # | Status | Evidence / How |
|---|---|---|
| Q5 | ✓ CLI | Outer IIFE runs in parent. Inner SSO logic runs in sandboxed iframe (separate execution context). |
| Q6 | ✓ CLI | Mixed: parent DOM (mount logic + message listener) + sandboxed iframe (SSO endpoint code). No Shadow DOM. |
| Q7 | ✓ CLI | Iframe is the trust boundary; postMessage is the only data path. Sandbox attribute caps iframe permissions. See SSO iframe hardening. |
| Q8 | ✓ CLI | Iframe origin always trusted. Extra origins via --allowed-origins 'https://idp.partner.com,*.federation.example.com' (validated at generation; bad origins dropped silently). Inlined __cdxValidateMessageOrigin enforces at runtime. |
Section 3 — Static vs Dynamic / SRI (Q9-11)
| # | Status | Evidence / How |
|---|---|---|
| Q9 | ✓ CLI | Static loader: iframe mount, sandbox attribute, message listener wiring, schema validation, custom-event dispatch. |
| Q10 | ✓ CLI | Dynamic content = SSO token payload. Schema-validated by __cdxValidateSsoMessage. Unknown fields stripped before dispatch. |
| Q11 | ✓ CLI | Static loader is immutable per submission. SRI on the iframe content is the SSO endpoint's CSP responsibility, not the parent. |
Section 4 — Context Handling (Q12-16)
| # | Status | Evidence / How |
|---|---|---|
| Q12 | ✓ CLI | Optional dbk.isWebview() gate for mobile-only execution. No personally identifying data passed to iframe; iframe authenticates via parent-window cookies (same-origin sandbox token). |
| Q13 | ✓ CLI | Iframe src URL only. Cookies via allow-same-origin sandbox token. |
| Q14 | ✓ CLI | iframeSrc validated as parseable URL at generation time. dbk.isWebview() return value type-checked at runtime. SSO payload validated by __cdxValidateSsoMessage. |
| Q15 | ✓ CLI | cdx-aspect:sso-token CustomEvent dispatched on window with bubbles:false, composed:false. Detail: {type, token, expiry?, signature?} only — unknown fields stripped. |
| Q16 | ✓ CLI + ◯ FI | Origin allowlist prevents foreign windows from posting forged tokens. Token expiry validated (Date.now() < expiry). Signature is type-checked only — FI must perform HMAC verification in their cdx-aspect:sso-token consumer. |
Section 5 — Communication Back to Parent (Q17-20)
| # | Status | Evidence / How |
|---|---|---|
| Q17 | ✓ CLI | DOM event: window.dispatchEvent(new CustomEvent('cdx-aspect:sso-token', {detail, bubbles:false, composed:false})). |
| Q18 | ✓ CLI | Strict schema: type === 'sso-token'; token non-empty string ≤ 4096 chars; expiry optional future Unix-ms; signature optional string ≤ 1024 chars. |
| Q19 | ✓ CLI | event.origin matched against inlined __cdxAllowedOrigins array (iframe origin + caller-supplied entries). Untrusted origins logged and dropped. |
| Q20 | ✓ CLI | Only the dispatched cdx-aspect:sso-token event. FI consumer code decides what to do with the token. |
Section 6 — Rendering & XSS (Q21-24)
| # | Status | Evidence / How |
|---|---|---|
| Q21 | ✓ CLI | Hidden iframe (0×0, aria-hidden="true"). No visible UI. |
| Q22 | ✓ CLI | No innerHTML of dynamic data. The iframe's own content is opaque to the parent IIFE. |
| Q23 | ✓ CLI | Iframe sandbox + origin allowlist + message-schema validation jointly prevent XSS through the SSO channel. |
| Q24 | ✓ CLI | No eval / new Function / inline scripts / inline event handlers. |
Section 7 — UI / Design System (Q25-28)
| # | Status | Evidence / How |
|---|---|---|
| Q25 | n/a | No visible UI. |
| Q26 | n/a | No visible UI. |
| Q27 | n/a | Iframe is invisible; CSS isolation only matters for the SSO endpoint's internal styling (its CSP responsibility). |
| Q28 | n/a | No visible UI. |
Section 8 — Resiliency (Q29-33)
| # | Status | Evidence / How |
|---|---|---|
| Q29 | ✓ CLI | iframe load failure: silent (FI consumer never receives token, falls back to its own timeout). Untrusted origin: dropped + logged. Schema-validation failure: dropped + logged. |
| Q30 | ◯ FI | No timeout on the iframe load itself. FI's responsibility to set a wall-clock fallback in the consumer of cdx-aspect:sso-token. |
| Q31 | ◯ FI | No UX (template renders no UI). FI's downstream consumer drives any UI. |
| Q32 | ✓ CLI | Fail-closed. Untrusted origins, malformed payloads, expired tokens — all silently dropped. The custom event never fires for invalid input. |
| Q33 | ◯ FI | No retry. Single iframe load; if it fails, the FI consumer's fallback handles it. |
Section 9 — Troubleshooting (Q34-37)
| # | Status | Evidence / How |
|---|---|---|
| Q34 | ✓ CLI | All hidden-iframe-sso log lines tagged with [cdx-aspect:<correlation-id>]. Common signals: blocked message from untrusted origin, sso-token payload failed schema validation, host element not found. |
| Q35 | ✓ CLI | Auto-generated correlation id; override via --correlation-id. |
| Q36 | ◯ FI | iframe content / postMessage payload changes → SSO endpoint owner. Mount-time issues (host selector not found) → FI front-end team. |
| Q37 | ◯ FI | Typically 2 parties (FI + SSO endpoint provider). |
Section 10 — Logging (Q38-41)
Same as oidc-snippet: correlation-tagged console.* only; FI's browser-log pipeline consumes; no PII; FI controls retention.
Section 11 — Libraries (Q42-45)
| # | Status | Evidence / How |
|---|---|---|
| Q42 | ✓ CLI | None. |
| Q43 | ✓ CLI | Bundled IIFE. |
| Q44 | ✓ CLI | IIFE scope, __cdx* prefixed helpers (__cdxValidateMessageOrigin, __cdxValidateSsoMessage, __cdxAllowedOrigins). |
| Q45 | ✓ CLI | None introduced. (Iframe element id cdx-sso-iframe is on document, not window.) |
Section 12 — FI Compatibility (Q46-54)
| # | Status | Evidence / How |
|---|---|---|
| Q46 | ✓ CLI | Same as oidc-snippet. |
| Q47 | ✓ CLI | Reads dbk.isWebview (optional, type-checked) when webviewGate: true. |
| Q48 | ✓ CLI | No framework dependency. |
| Q49 | ✓ CLI + ◯ documented | One window.addEventListener('message', ...) listener — origin-validated against the inlined allowlist, payload schema-validated. This is the only template that registers a global listener. |
| Q50 | ✓ CLI | The message listener filters by origin before processing; foreign messages return early. |
| Q51 | ✓ CLI | Listener body wraps only schema-validated dispatch; no throw paths. |
| Q52-54 | ✓ CLI | Negligible overhead — single iframe, single message listener, no animation, no DOM polling. |
Section 13 — Change Management (Q55-58)
Same model as oidc-snippet: each forge aspect submit is a new immutable static loader; FI versioning policy applies.
Section 14 — Compliance & Assurance (Q59-60)
Same as oidc-snippet: Forge CLI internal review documented; FI deployment review per the checklist.
mobile-vendor-chat-jsbridge — Completed Response
Mobile-only WebView template. Requests session token via native iOS / Android JSBridge; falls back to a configurable --token-endpoint for browser preview.
Section 1 — Architecture (Q1-4)
| # | Status | Evidence / How |
|---|---|---|
| Q1 | ✓ CLI | WebView IIFE → JSBridge tokenApiDetails (iOS webkit.messageHandlers / Android JSBridge) → native app issues HTTPS to FI backend → window.onTokenApiResponse(response) → load vendor SDK with token. Fallback path: __cdxFetch to --token-endpoint. |
| Q2 | ✓ CLI | FI (mobile app, native bridge implementation, token endpoint), Vendor (chat SDK), Candescent (CLI). |
| Q3 | ✓ CLI | FI native: bridge implementation, credential injection. FI backend: token issuance. Vendor: chat SDK. CLI: bridge invocation, token-response validation, vendor-SDK init. |
| Q4 | ✓ CLI | Static loader = FI-hosted (HTML wrapped). Token endpoint = FI. Vendor SDK = vendor's CDN. UI = vendor's chat widget. |
Section 2 — Trust Boundaries (Q5-8)
| # | Status | Evidence / How |
|---|---|---|
| Q5 | ✓ CLI | All JS runs inside the WebView (the only "window" in mobile execution). |
| Q6 | ✓ CLI | WebView DOM only. No iframe, no Shadow DOM. |
| Q7 | ✓ CLI | WebView ↔ native app (JSBridge). WebView ↔ vendor CDN (HTTPS, optional SRI). WebView ↔ FI backend (HTTPS fallback). |
| Q8 | ◯ FI | Vendor SDK URL hardcoded at submission via --vendor-script-url. Token endpoint via --token-endpoint. FI verifies these in the submission PR. |
Section 3 — Static vs Dynamic / SRI (Q9-11)
| # | Status | Evidence / How |
|---|---|---|
| Q9 | ✓ CLI | Static loader (HTML+IIFE): JSBridge invocation, fallback fetch, vendor-SDK script-tag construction (with optional SRI), event dispatch. |
| Q10 | ✓ CLI | Dynamic = vendor SDK (its own logic loads after the script tag), session token (opaque). Token does not introduce new entry points. |
| Q11 | ◯ FI | Static loader immutable per submission. SRI on vendor SDK supported via --integrity flag; FI provides the published vendor hash. |
Section 4 — Context Handling (Q12-16)
| # | Status | Evidence / How |
|---|---|---|
| Q12 | ✓ CLI | Session token (from FI native app via JSBridge, or fallback fetch). Vendor org id / app name (configured at submit time). |
| Q13 | ✓ CLI | iOS: window.webkit.messageHandlers.tokenApiDetails.postMessage('cdx-aspect'). Android: window.JSBridge.tokenApiDetails('cdx-aspect'). Response: window.onTokenApiResponse(JSON-or-string). |
| Q14 | ✓ CLI | Response parsed (string → JSON tolerantly), token extracted from access_token or token field, type-checked. Empty / missing token logs a warning and degrades to vendor SDK without auth. |
| Q15 | ✓ CLI | Token written to window.VendorAuthToken for vendor SDK to consume. CustomEvent cdx-mobile-vendor-ready dispatched after SDK loads. |
| Q16 | ◯ FI | Token comes from FI's native app or FI backend over HTTPS — trust transferred from FI's native auth. Vendor SDK's own token validation is the vendor's responsibility. |
Section 5 — Communication Back to Parent (Q17-20)
| # | Status | Evidence / How |
|---|---|---|
| Q17 | ✓ CLI | DOM event: cdx-mobile-vendor-ready (detail = {token, app, org, source}). Vendor SDK behavior beyond that is vendor-specific. |
| Q18 | ✓ CLI | Token-response shape tolerant: {access_token: string} or {token: string} accepted. Other fields ignored. |
| Q19 | ◯ FI | window.onTokenApiResponse is a global function callable by anyone with WebView access. In a real WebView, only the native bridge calls it; in browser preview, the fallback __cdxFetch calls it. FI is responsible for ensuring no other JS in the WebView is hostile. |
| Q20 | ✓ CLI | Loading the vendor SDK + dispatching cdx-mobile-vendor-ready. No further parent-site actions. |
Section 6 — Rendering & XSS (Q21-24)
| # | Status | Evidence / How |
|---|---|---|
| Q21 | ✓ CLI | Vendor SDK draws its own UI inside the WebView. The CLI's IIFE renders nothing visible. |
| Q22 | ✓ CLI | None in the IIFE. The vendor SDK's innerHTML usage is the vendor's responsibility (covered by their own security review). |
| Q23 | ✓ CLI | Token / org id / app name written to window.* properties via property assignment, not innerHTML. No string concatenation into HTML. |
| Q24 | ✓ CLI | No eval / new Function / inline scripts in the IIFE. (Vendor SDK's own use is out of scope.) |
Section 7 — UI / Design System (Q25-28)
| # | Status | Evidence / How |
|---|---|---|
| Q25-28 | ◯ FI / vendor | UI is the vendor SDK's. FI must validate vendor's design-system fit and CSS isolation in the WebView. |
Section 8 — Resiliency (Q29-33)
| # | Status | Evidence / How |
|---|---|---|
| Q29 | ✓ CLI | JSBridge unavailable → falls back to __cdxFetch to --token-endpoint. Vendor SDK load failure → existing partner-script onerror diagnostics fire. Token-endpoint timeout → user sees [cdx-aspect:<id>] mobile-vendor-chat: token fallback timed out (<ms>). |
| Q30 | ✓ CLI | 10 000 ms default on the fallback fetch; override via --timeout-ms. |
| Q31 | ◯ FI / vendor | No CLI-rendered UX (template's UI is the vendor's). FI / vendor own the failure UX. |
| Q32 | ✓ CLI | Token missing → vendor SDK loads with empty token (fail-open with logged warning). |
| Q33 | ✓ CLI | Same as oidc-snippet: 3 retries default with exponential backoff on 5xx / network errors via __cdxFetch. |
Section 9 — Troubleshooting (Q34-37)
Same as hidden-iframe-sso: correlation-id-tagged log lines, browser-log pipeline. Common signals: JSBridge call failed, token response missing access_token, token fallback timed out.
Section 10 — Logging (Q38-41)
Same as oidc-snippet. The vendor SDK's own logging is vendor-controlled.
Section 11 — Libraries (Q42-45)
| # | Status | Evidence / How |
|---|---|---|
| Q42 | ◯ FI | The vendor SDK is loaded dynamically. Its libraries are out of CLI scope. The CLI's IIFE itself uses none. |
| Q43 | ✓ CLI / ◯ vendor | CLI's IIFE bundled. Vendor SDK loaded dynamically from --vendor-script-url. |
| Q44 | ✓ CLI | CLI side: IIFE scope, __cdx* prefix. Vendor SDK conflict prevention is the vendor's responsibility. |
| Q45 | ◯ documented | Globals introduced: window.VendorAppName, window.VendorOrgId, window.VendorAuthToken, window.onTokenApiResponse. Documented for FI awareness. |
Section 12 — FI Compatibility (Q46-54)
| # | Status | Evidence / How |
|---|---|---|
| Q46 | ✓ CLI | Compatible with WebView execution. No conflict with native bridges other than the documented tokenApiDetails. |
| Q47 | ✓ CLI documented | Reads: window.webkit.messageHandlers.tokenApiDetails, window.JSBridge.tokenApiDetails. Writes: window.VendorAppName, window.VendorOrgId, window.VendorAuthToken, window.onTokenApiResponse. |
| Q48 | ✓ CLI | No framework dependency. |
| Q49 | ✓ CLI | None added by the IIFE itself. (window.onTokenApiResponse is a function, not a listener.) |
| Q50 | ✓ CLI | cdx-mobile-vendor-ready event uses cdx- prefix. |
| Q51 | ✓ CLI | try/catch around bridge invocation; fallback fetch wrapped in .catch. |
| Q52-54 | ✓ CLI | Async <script> tag for vendor SDK. Bridge call is synchronous but native side is non-blocking. |
Section 13 — Change Management (Q55-58)
Same model as the others.
Section 14 — Compliance & Assurance (Q59-60)
Same as the others.
Other Templates — Shared Response Summaries
The remaining 12 templates fall into three families with shared questionnaire responses. Differences are noted inline.
Family A — Context-less UI Templates
Templates: banner, toast, card, modal, countdown, floating-action-button
These render a UI element (banner / toast / card / modal / countdown timer / floating button) directly into the parent DOM. They do not read user identity, do not call external services, and do not communicate back to the parent beyond a click handler.
| Section | Headline answer |
|---|---|
| 1 — Architecture (Q1-4) | Static IIFE → DOM render. No runtime APIs. FI hosts the loader; Candescent provides the template. |
| 2 — Trust boundaries (Q5-8) | Parent DOM only. No iframe, no Shadow DOM, no external network. |
| 3 — Static vs dynamic / SRI (Q9-11) | Static loader is immutable. No dynamic content. SRI n/a (no external scripts loaded). |
| 4 — Context (Q12-16) | n/a — no contextual data read. |
| 5 — Communication (Q17-20) | None back to the parent except: (a) modal / card navigate via validated --cta-url (http: / https: only); (b) floating-action-button opens a new tab via window.open(url, '_blank', 'noopener,noreferrer'). |
| 6 — Rendering / XSS (Q21-24) | innerHTML used; --message, --cta-text, validated --cta-url, all __cdxEsc-escaped at generation time. No eval / new Function / inline event handlers. |
| 7 — UI / design (Q25-28) | --bg-color, --text-color, --position flags supported. Shadow DOM not implemented — FI verifies parent-CSS impact. CSP nonce on <style> via --csp-nonce. |
| 8 — Resiliency (Q29-33) | No failure modes (no network calls). Render failure (e.g. document.body missing) is silent. |
| 9-10 — Troubleshooting / Logging (Q34-41) | Minimal console.*. No correlation id (no telemetry consumer). |
| 11 — Libraries (Q42-45) | None. countdown introduces window._cdxCountdownIv (cleared on dismiss). Otherwise no globals. |
| 12 — Compatibility (Q46-54) | No framework dependency. No dbk.* reads. No global event listeners (only element-scoped addEventListener on close buttons). |
| 13-14 — Governance (Q55-60) | Standard: each submit = new immutable loader; FI controls rollback. AppSec review per FI policy. |
Family B — Personalized UI Templates
Templates: welcome-banner, personalized-toast
Same as Family A, but additionally read dbk.sessionInfo() for the user's first name. Differences from Family A:
| Section | Difference |
|---|---|
| 4 — Context (Q12-16) | Reads dbk.sessionInfo() (Q12, Q13). Validated by inlined __cdxValidateSession (Q14): type, length ≤ 200, Unicode-letter allowlist, optional sessionExpiry future-check. Falls back to "Valued Customer" / "there" on validation failure (Q16). |
| 6 — Rendering / XSS (Q21-24) | Validated user name passes through __cdxEsc before insertion into innerHTML (Q23). Same XSS guarantees as Family A. |
| 12 — Compatibility (Q47) | Depends on dbk.sessionInfo (parent-site global). Type-checked before use; degrades gracefully when absent. |
Family C — Vendor-Loader Templates
Templates: vendor-script-loader, vendor-script-with-config, tag-manager, vendor-sdk-personalized
Load an external vendor script (and, in vendor-script-with-config, an external CSS file). The vendor SDK then runs in the parent window with whatever permissions the FI's CSP allows.
| Section | Headline answer |
|---|---|
| 1 — Architecture (Q1-4) | Parent IIFE → <script> (and optional <link>) loads vendor SDK. Vendor SDK owns runtime behavior thereafter. |
| 2 — Trust boundaries (Q5-8) | Parent DOM. Vendor SDK domain set at submission via --vendor-script-url / --css-url; FI verifies in the submission PR (Q8). |
| 3 — Static vs dynamic / SRI (Q9-11) | SRI supported for both vendor JS and (for vendor-script-with-config) CSS via --integrity / --css-integrity. CLI bypasses dbk.loadScript when SRI is set. Malformed hashes fail-open with console.error. |
| 4 — Context (Q12-16) | vendor-sdk-personalized reads dbk.sessionInfo() and pre-seeds the vendor SDK with userFullName, userGuid via window.PreChatFields etc. — same __cdxValidateSession enforcement as Family B. Other vendor loaders read no context. |
| 5 — Communication (Q17-20) | n/a — vendor-controlled after load. |
| 6 — Rendering / XSS (Q21-24) | CLI-side: no innerHTML of dynamic data, no eval. Vendor SDK's own behavior is the vendor's responsibility. |
| 7 — UI / design (Q25-28) | Vendor-styled. Shadow DOM not enforced. |
| 8 — Resiliency (Q29-33) | Script load failure: s.onerror fires partner-script diagnostics (probes /health on loopback hosts to detect "mock not running"). No retry on script load. Fetch resiliency in vendor-script-with-config config-globals: n/a (no fetch). |
| 11 — Libraries (Q42-45) | Vendor SDK is dynamically loaded (Q42-43). CLI scope: bundled IIFE only. vendor-sdk-personalized introduces globals: window.PreChatFields, window.VendorOrgId, window.VendorAppName, plus the configured --vendor-init-fn path (Q45). vendor-script-with-config introduces window.AspectConfigContent plus any extras from --config-globals. |
| 12 — Compatibility (Q46-54) | CLI side compatible. Vendor SDK conflict prevention is the vendor's responsibility (Q44, Q48). |
| 9-10, 13-14 | Standard. |
tag-manager is web-only; the others support both platforms. tag-manager additionally validates the GTM container id format (GTM-[A-Z0-9]+) at generation time — invalid ids emit console.error instead of a broken script tag.
Related Documents
- Security Architecture — Trust zones, party responsibilities, defense layers
- Deployment Security Checklist — Pre-deployment review worksheet (uses these answers as the verification baseline)
- Web Technical Reference — Security model — Per-template threat detail
- Template Families — Built-in Security Controls — Per-template control matrix