The Same-Origin Policy (SOP) is one of the most important security mechanisms in browsers, which restricts how a document or script loaded from one origin can interact with resources from another origin. An iframe creates an independent browsing context, and its content must comply with the same-origin policy.
Definition of Same Origin
Two pages have the same origin if all three of the following conditions are met simultaneously:
- Same Protocol: Such as both using https://
- Same Domain: Such as both using example.com
- Same Port: Such as both using 443 (https default port)
Same-Origin Examples
javascript// The following URLs are same-origin with https://example.com/page.html https://example.com/other.html https://example.com/sub/page.html // The following URLs are NOT same-origin with https://example.com/page.html https://www.example.com/page.html // Different subdomain http://example.com/page.html // Different protocol https://example.com:8080/page.html // Different port
iframe Same-Origin Policy Restrictions
1. DOM Access Restrictions
javascript// Parent page const iframe = document.getElementById('myIframe'); // Same-origin: Can access if (iframe.contentDocument) { const title = iframe.contentDocument.title; } // Different-origin: Cannot access, will throw SecurityError try { const title = iframe.contentDocument.title; } catch (e) { console.error('Cross-origin access denied:', e); }
2. JavaScript Access Restrictions
javascript// Parent page const iframe = document.getElementById('myIframe'); // Same-origin: Can call functions inside iframe if (iframe.contentWindow) { iframe.contentWindow.someFunction(); } // Different-origin: Cannot call try { iframe.contentWindow.someFunction(); } catch (e) { console.error('Cross-origin call denied:', e); }
3. Cookie and LocalStorage Access Restrictions
javascript// Code inside iframe // Same-origin: Can access parent page's cookies const cookies = document.cookie; // Different-origin: Cannot access parent page's cookies // Can only access cookies of its own origin
Solutions for Cross-Origin iframes
1. postMessage API (Recommended)
javascript// Parent page const iframe = document.getElementById('myIframe'); // Send message to iframe iframe.postMessage({ type: 'getData', payload: { key: 'value' } }, 'https://child-domain.com'); // Receive messages from iframe window.addEventListener('message', (event) => { // Verify message source if (event.origin !== 'https://child-domain.com') { return; } console.log('Received iframe message:', event.data); }); // Code inside iframe // Receive parent page message window.addEventListener('message', (event) => { if (event.origin !== 'https://parent-domain.com') { return; } // Handle message if (event.data.type === 'getData') { const result = processData(event.data.payload); // Send response window.parent.postMessage({ type: 'dataResponse', payload: result }, 'https://parent-domain.com'); } });
2. document.domain (Only for Same Main Domain)
javascript// Parent page https://www.example.com document.domain = 'example.com'; // iframe https://sub.example.com document.domain = 'example.com'; // Now can access each other const iframe = document.getElementById('myIframe'); const iframeContent = iframe.contentDocument;
Limitations:
- Only applicable to subdomains under the same main domain
- Not applicable to completely different domains
- Not applicable to mixing HTTPS and HTTP
3. CORS (Cross-Origin Resource Sharing)
javascript// Server-side set CORS headers Access-Control-Allow-Origin: https://parent-domain.com Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type Access-Control-Allow-Credentials: true // Frontend use fetch fetch('https://api.example.com/data', { credentials: 'include' }) .then(response => response.json()) .then(data => console.log(data));
4. JSONP (Deprecated, Not Recommended)
javascript// Not recommended to use JSONP, security risks exist // Use postMessage or CORS instead
iframe Same-Origin Policy Security Best Practices
1. Always Verify Message Source
javascriptwindow.addEventListener('message', (event) => { // Strictly verify source const allowedOrigins = [ 'https://trusted-domain.com', 'https://another-trusted-domain.com' ]; if (!allowedOrigins.includes(event.origin)) { console.warn('Reject message from unauthorized source:', event.origin); return; } // Verify data format if (!event.data || typeof event.data !== 'object') { return; } // Handle message handleMessage(event.data); });
2. Use Specific targetOrigin
javascript// Not recommended: Allow all origins iframe.postMessage(data, '*'); // Recommended: Specify specific origin iframe.postMessage(data, 'https://trusted-domain.com');
3. Limit iframe Permissions
html<!-- Use sandbox to limit permissions --> <iframe src="https://external-content.com" sandbox="allow-scripts allow-same-origin"> </iframe>
4. Use CSP (Content Security Policy)
httpContent-Security-Policy: frame-src 'self' https://trusted-domain.com; Content-Security-Policy: child-src 'self' https://trusted-domain.com;
5. Avoid Sensitive Data Transmission
javascript// Not recommended: Transmit sensitive data through postMessage iframe.postMessage({ type: 'auth', token: 'sensitive-token' }, 'https://external-domain.com'); // Recommended: Use secure authentication flow // 1. Parent page initiates authentication request // 2. iframe handles authentication // 3. Return authentication result through secure channel
Common Questions about iframe Same-Origin Policy
1. How to Detect if iframe is Same-Origin?
javascriptfunction isSameOrigin(iframe) { try { // Try to access contentDocument const doc = iframe.contentDocument; return true; } catch (e) { // Access denied, means cross-origin return false; } } const iframe = document.getElementById('myIframe'); if (isSameOrigin(iframe)) { console.log('iframe is same-origin'); } else { console.log('iframe is cross-origin'); }
2. How to Get iframe's Actual Origin?
javascriptconst iframe = document.getElementById('myIframe'); console.log('iframe src:', iframe.src); console.log('iframe origin:', new URL(iframe.src).origin);
3. How to Handle iframe Load Errors?
html<iframe src="https://example.com/content" onerror="handleIframeError(this)" onload="handleIframeLoad(this)"> </iframe> <script> function handleIframeError(iframe) { console.error('iframe load failed:', iframe.src); iframe.src = '/error-page.html'; } function handleIframeLoad(iframe) { console.log('iframe loaded successfully:', iframe.src); } </script>
Browser Compatibility for iframe Same-Origin Policy
All modern browsers support iframe same-origin policy:
- Chrome (all versions)
- Firefox (all versions)
- Safari (all versions)
- Edge (all versions)
- IE (all versions)
Summary
The iframe same-origin policy is an important mechanism for protecting webpage security. Key points:
- Understand Same-Origin Definition: Protocol, domain, and port must be the same
- Comply with Access Restrictions: Cross-origin iframes cannot directly access DOM and JavaScript
- Use Secure Communication: Use postMessage API for cross-origin communication
- Verify Message Source: Always verify the source of postMessage
- Limit iframe Permissions: Use sandbox and CSP to limit iframe permissions
- Avoid Sensitive Data Transmission: Do not transmit sensitive data through insecure methods