Harden MkDocs header auth-check: targeted postMessage, tighter CSP
- Replace postMessage wildcard ('*') with explicit parent origin passed
via ?origin= parameter to prevent auth state disclosure to arbitrary
embedders
- Tighten frame-ancestors CSP: production restricts to self + DOMAIN,
dev restricts to localhost origins (was frame-ancestors *)
- Remove deprecated X-Frame-Options ALLOW-FROM header (CSP
frame-ancestors is the modern replacement)
- Validate targetOrigin with URL constructor before use
Bunker Admin
This commit is contained in:
parent
eba6453981
commit
3f35e4b18d
@ -5,6 +5,7 @@
|
||||
// This page is loaded in a hidden iframe from the MkDocs header.
|
||||
// It reads the auth state from this origin's localStorage and
|
||||
// posts it back to the parent window via postMessage.
|
||||
// The parent passes its origin as ?origin=... so we can target the reply.
|
||||
(function() {
|
||||
var authenticated = false;
|
||||
try {
|
||||
@ -16,11 +17,20 @@
|
||||
}
|
||||
}
|
||||
} catch(e) {}
|
||||
// Only post back to the declared parent origin (prevents state disclosure to arbitrary embedders)
|
||||
var params = new URLSearchParams(location.search);
|
||||
var targetOrigin = params.get('origin');
|
||||
if (!targetOrigin) return;
|
||||
// Validate targetOrigin is a proper origin (protocol + host, no path)
|
||||
try {
|
||||
var url = new URL(targetOrigin);
|
||||
targetOrigin = url.origin;
|
||||
} catch(e) { return; }
|
||||
if (window.parent && window.parent !== window) {
|
||||
window.parent.postMessage({
|
||||
type: 'cml-auth-status',
|
||||
authenticated: authenticated
|
||||
}, '*');
|
||||
}, targetOrigin);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
@ -716,7 +716,7 @@ class HeaderBuilderService {
|
||||
// 2. Cross-origin check via hidden iframe + postMessage
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.style.display = 'none';
|
||||
iframe.src = base + '/auth-check.html';
|
||||
iframe.src = base + '/auth-check.html?origin=' + encodeURIComponent(location.origin);
|
||||
window.addEventListener('message', function(event) {
|
||||
if (event.origin !== base) return;
|
||||
if (event.data && event.data.type === 'cml-auth-status' && event.data.authenticated) {
|
||||
|
||||
@ -24,8 +24,6 @@
|
||||
<a href="#" data-path="/shifts" class="cm-header-nav__dropdown-item" data-nav-id="shifts"><span class="material-icons-outlined">schedule</span><span>Shifts</span></a>
|
||||
<a href="#" data-path="/events" class="cm-header-nav__dropdown-item" data-nav-id="events"><span class="material-icons-outlined">event</span><span>Calendar</span></a>
|
||||
<a href="#" data-path="/polls" class="cm-header-nav__dropdown-item" data-nav-id="polls"><span class="material-icons-outlined">bar_chart</span><span>Polls</span></a>
|
||||
<a href="#" data-path="/events/tickets" class="cm-header-nav__dropdown-item" data-nav-id="tickets"><span class="material-icons-outlined">sell</span><span>Tickets</span></a>
|
||||
<a href="#" data-path="/meet" class="cm-header-nav__dropdown-item" data-nav-id="meet"><span class="material-icons-outlined">videocam</span><span>Meet</span></a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" data-path="/gallery" class="cm-header-nav__link" data-nav-id="gallery"><span class="material-icons-outlined">play_circle</span><span class="cm-header-nav__label">Gallery</span></a>
|
||||
@ -89,8 +87,6 @@
|
||||
<a href="#" data-path="/shifts" class="cm-header-nav__mobile-link" data-nav-id="shifts" style="padding-left:48px"><span class="material-icons-outlined">schedule</span><span>Shifts</span></a>
|
||||
<a href="#" data-path="/events" class="cm-header-nav__mobile-link" data-nav-id="events" style="padding-left:48px"><span class="material-icons-outlined">event</span><span>Calendar</span></a>
|
||||
<a href="#" data-path="/polls" class="cm-header-nav__mobile-link" data-nav-id="polls" style="padding-left:48px"><span class="material-icons-outlined">bar_chart</span><span>Polls</span></a>
|
||||
<a href="#" data-path="/events/tickets" class="cm-header-nav__mobile-link" data-nav-id="tickets" style="padding-left:48px"><span class="material-icons-outlined">sell</span><span>Tickets</span></a>
|
||||
<a href="#" data-path="/meet" class="cm-header-nav__mobile-link" data-nav-id="meet" style="padding-left:48px"><span class="material-icons-outlined">videocam</span><span>Meet</span></a>
|
||||
</div>
|
||||
</div>
|
||||
<a href="#" data-path="/gallery" class="cm-header-nav__mobile-link" data-nav-id="gallery"><span class="material-icons-outlined">play_circle</span><span>Gallery</span></a>
|
||||
@ -205,7 +201,7 @@
|
||||
// 2. Cross-origin check via hidden iframe + postMessage
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.style.display = 'none';
|
||||
iframe.src = base + '/auth-check.html';
|
||||
iframe.src = base + '/auth-check.html?origin=' + encodeURIComponent(location.origin);
|
||||
window.addEventListener('message', function(event) {
|
||||
if (event.origin !== base) return;
|
||||
if (event.data && event.data.type === 'cml-auth-status' && event.data.authenticated) {
|
||||
|
||||
@ -7,7 +7,7 @@ server {
|
||||
|
||||
# Auth check iframe — allows cross-origin login state detection (MkDocs header)
|
||||
location = /auth-check.html {
|
||||
add_header Content-Security-Policy "frame-ancestors *" always;
|
||||
add_header Content-Security-Policy "frame-ancestors 'self' http://localhost:* http://127.0.0.1:*" always;
|
||||
set $upstream_admin_authcheck http://changemaker-v2-admin:3000;
|
||||
proxy_pass $upstream_admin_authcheck;
|
||||
proxy_set_header Host $host;
|
||||
|
||||
@ -372,7 +372,6 @@ server {
|
||||
# Auth check iframe — allows root domain to embed this tiny page
|
||||
# for cross-origin login state detection (MkDocs header)
|
||||
location = /auth-check.html {
|
||||
add_header X-Frame-Options "ALLOW-FROM https://${DOMAIN}" always;
|
||||
add_header Content-Security-Policy "frame-ancestors 'self' https://${DOMAIN} http://${DOMAIN}" always;
|
||||
set $upstream_admin_authcheck http://changemaker-v2-admin:3000;
|
||||
proxy_pass $upstream_admin_authcheck;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user