Frontend Security: Isolating Sensitive Input with Sandbox Iframes
How we isolated address and document input from the main checkout page using sandbox iframes and a middleware layer — with minimal changes to existing code.
The Problem: Compliance Pressure vs. Legacy Code
E-commerce checkout pages handle sensitive data by nature — addresses, ID numbers, tax IDs. What makes it worse: the rise of AI tools has dramatically lowered the barrier for attackers. XSS injection and MITM attacks that once required real skill can now be automated — LLMs can generate exploit scripts, scan for vulnerabilities, and even mimic normal user behavior to bypass security controls. Security audits are getting stricter: sensitive input should not happen in the main page context.
But here's the reality — checkout address modules accumulate years of iteration, deep coupling, and fragile dependencies. A full rewrite isn't practical when you have a shipping deadline.
So the question became: how do we isolate sensitive input without rewriting the main checkout flow?
Why Not "Rewrite Everything"
We evaluated several approaches:
| Approach | Pros | Cons |
|---|---|---|
| Full page rewrite | Clean slate | Long timeline, high regression risk |
| Client-side encryption | Small changes | Key management is a new attack surface |
| Tokenization | Most secure | Requires backend model changes across all consumers |
| Sandbox iframe + middleware | Minimal changes, effective isolation | Read-only data still visible on main page |
We went with the last option. The core judgment: isolating the input process solves the biggest security pain point in phase one. Read-only display on the main page can be addressed later.
Architecture: Three Layers, Clear Boundaries
1. Parent Page (Checkout)
- Continues handling address list queries and display (unchanged in phase one)
- Add/Edit buttons now open an iframe modal
- Requests a short-lived session token for each operation
- Listens for save-success messages from the iframe, then refreshes the address list
What the parent page does not do: render sensitive forms, read iframe DOM, or observe user input keystrokes.
2. Collector (Sandbox Iframe)
- Renders the full address/document form independently
- Manages its own form state and validation
- Fetches initialization data (country lists, edit prefill) from the middleware using the session token
- Submits through the middleware — never connects directly to backend APIs
- Notifies the parent via
postMessageon successful save
Key design choice: a single collector supports two modes via a scope parameter — full address form or document-only form. One page, two use cases.
3. Middleware (Node Facade)
This is the funnel point for all sensitive operations:
- Manages short-lived session tokens (30-minute TTL, invalidated immediately after successful submit)
- Aggregates country lists and edit prefill data for the iframe
- Forwards address save and document save requests to real backend services
- Applies uniform log sanitization and parameter filtering
The middleware does not store address plaintext, maintain long-term drafts, or replace the existing address list data source.
Session Management: Security Meets UX
Session token design is the security backbone:
- Short-lived: Fixed 30-minute expiry, immediate invalidation after successful submission
- User-bound: Tokens are bound to the current user, site, and operation mode
- Single-session constraint: Only one active session per page; creating a new one automatically invalidates the old
- Edit permission check: In edit mode, the middleware verifies the user owns the address being edited
Even if a token leaks, the attack window is narrow and cross-user usage is impossible.
Submit Strategy: Handling Multi-API Failure Scenarios
Real-world saves involve multiple backend calls (address body, document info, default address sync). The failure handling strategy needed careful thought:
Execution order: Save address body → Save document info → Handle default address and billing address sync
Failure scenarios:
- Address saved, document save failed: No compensating delete (in create mode). Return "partial save" status, prompt user to verify
- Address and document saved, default address sync failed: Same "partial save" treatment
- Partial failure in edit mode: No automatic rollback promised. Prompt user to retry or manually refresh
Core principle: It's better to honestly tell the user "please verify" than to pretend everything succeeded.
Message Validation: Don't Let postMessage Become a New Attack Surface
Parent-iframe communication via postMessage is itself a potential vector. Our defenses:
- Verify message source is the iframe's
contentWindow - Generate a random nonce per session; iframe must include it in responses
- Only handle whitelisted message types (e.g., save-success); ignore everything else
- Don't rely on
event.originas the sole trust signal
What We Didn't Do (Being Honest)
Phase one has clear boundaries:
- ❌ Main page still displays full addresses in the list
- ❌ Middleware and backend still see full addresses during save/prefill
- ❌ No frontend rewrite for delete address or set-default-address flows
These aren't oversights — they're deliberate trade-offs. Phase one's goal is input process isolation, not full-pipeline data desensitization.
Rollout: Starting with a Single Site
Phase one is controlled via feature flags, launching first on a single site (Brazil). Key metrics we're watching:
- Session expiration rate
- Mobile collector open success rate
- Create/edit save success rate
- Partial save error rate
Expansion to other sites happens only after stability is confirmed.
Takeaways
Looking back, the biggest lesson: security improvements don't always require a big-bang rewrite.
Find the smallest meaningful cut, solve the biggest risk first, then expand incrementally. It's more practical than waiting for a "perfect" solution that never ships.
Of course, sandbox iframes aren't a silver bullet. Full-pipeline desensitization (including main page display) will require deeper data model changes. But that's phase two's problem.
Solve what's in front of you first. Idealism can wait.