Skip to content

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.

Authorhopes75 minutesfrontend-security, iframe, sandbox, security-architecture, e-commerce

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 postMessage on 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.origin as 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.

#frontend-security#iframe#sandbox#security-architecture#e-commerce