Skip to content

Commit

Permalink
Add to frame-ancestors instead of replacing
Browse files Browse the repository at this point in the history
  • Loading branch information
GarboMuffin committed May 13, 2024
1 parent b106ae0 commit c4c7f8d
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src-main/windows/abstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class AbstractWindow {
}

this.initialURL = null;
this.protocol = null;

const cls = this.constructor;
if (!windowsByClass.has(cls)) {
Expand Down Expand Up @@ -194,6 +195,7 @@ class AbstractWindow {

loadURL (url) {
this.initialURL = url;
this.protocol = new URL(url).protocol;
return this.window.loadURL(url);
}

Expand Down
3 changes: 2 additions & 1 deletion src-main/windows/packager.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ class PackagerWindow extends AbstractWindow {
});

this.window.webContents.on('did-create-window', (newWindow) => {
new PackagerPreviewWindow(this.window, newWindow);
const childWindow = new PackagerPreviewWindow(this.window, newWindow);
childWindow.protocol = this.protocol;
});

this.loadURL('tw-packager://./standalone.html');
Expand Down
37 changes: 29 additions & 8 deletions src-main/windows/project-running-window.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,36 @@ class ProjectRunningWindow extends AbtractWindow {
// Headers from Electron are not normalized, so we have to make sure to remove uppercased
// variations on our own.
const normalized = key.toLowerCase();
if (normalized === 'access-control-allow-origin' || normalized === 'x-frame-options') {

if (
// Above we forced this header to be *, so ignore any other value
normalized === 'access-control-allow-origin' ||
// Remove x-frame-options so that embedding is allowed
normalized === 'x-frame-options'
) {
// Ignore header.
} else if (normalized === 'content-security-policy') {
// Remove frame-ancestors header while preserving the rest of the CSP.
// frame-ancestors does not fall back to default-src so we just need to remove, not overwrite.
// Regex based on ABNF from https://www.w3.org/TR/CSP3/#grammardef-serialized-policy
newHeaders[key] = details.responseHeaders[key].map(csp => (
csp.replace(/(?:;[\x09\x0A\x0C\x0D\x20]*)?frame-ancestors[\x09\x0A\x0C\x0D\x20]+[^;,]+/ig, '')
));
} else if (
normalized === 'content-security-policy' ||
// We include the report-only header so that we send fewer useless reports
normalized === 'content-security-policy-report-only'
) {
// Seems to be an Electron quirk where CSP with custom protocols can't do specific
// origins, only an entire protocol. We use a lot of separate protocols so that's fine.
// It is possible for protocol to be null, so handle that.
const extraSources = this.protocol ? this.protocol : null;

if (extraSources) {
// If the page has a frame-ancestors directive, add ourselves to it so that we can embed
// the page without compromising security more than absolutely necessary.
// frame-ancestors does not fall back to default-src so we don't need to worry about that.
// Regex based on ABNF from https://www.w3.org/TR/CSP3/#grammardef-serialized-policy
newHeaders[key] = details.responseHeaders[key].map(csp => (
csp.replace(
/((?:;[\x09\x0A\x0C\x0D\x20]*)?frame-ancestors[\x09\x0A\x0C\x0D\x20]+)([^;,]+)/ig,
(_, directiveName, directiveValue) => `${directiveName}${directiveValue} ${extraSources}`
)
));
}
} else {
newHeaders[key] = details.responseHeaders[key];
}
Expand Down

0 comments on commit c4c7f8d

Please sign in to comment.