Skip to content

Commit 19830f4

Browse files
committed
security: tighten CSP and navigation guards
1 parent 6dff7df commit 19830f4

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

desktop/src/main.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ async function createWindow() {
5454
webPreferences: {
5555
contextIsolation: true,
5656
nodeIntegration: false,
57+
sandbox: true,
58+
webSecurity: true,
59+
enableRemoteModule: false,
5760
preload: path.join(__dirname, "preload.js"),
5861
},
5962
});
@@ -62,6 +65,49 @@ async function createWindow() {
6265

6366
win.webContents.setWindowOpenHandler(() => ({ action: "deny" }));
6467

68+
// Block unexpected navigations
69+
win.webContents.on("will-navigate", (event, url) => {
70+
const allowed =
71+
url.startsWith("file://") ||
72+
(isDev && url.startsWith("http://localhost:5174")) ||
73+
(isDev && url.startsWith("http://127.0.0.1:5174"));
74+
if (!allowed) {
75+
event.preventDefault();
76+
console.warn("Blocked navigation to", url);
77+
}
78+
});
79+
80+
// Apply a restrictive CSP on all responses
81+
const connectSrc = [
82+
"'self'",
83+
"https://push.forward.computer",
84+
"https://push-1.forward.computer",
85+
"https://schedule.forward.computer",
86+
];
87+
const styleSrc = ["'self'", "'unsafe-inline'"];
88+
const scriptSrc = ["'self'"];
89+
const imgSrc = ["'self'", "data:"];
90+
win.webContents.session.webRequest.onHeadersReceived((details, callback) => {
91+
const csp = [
92+
`default-src 'self';`,
93+
`base-uri 'self';`,
94+
`object-src 'none';`,
95+
`frame-ancestors 'none';`,
96+
`img-src ${imgSrc.join(" ")};`,
97+
`script-src ${scriptSrc.join(" ")};`,
98+
`style-src ${styleSrc.join(" ")};`,
99+
`connect-src ${connectSrc.join(" ")} http://localhost:5174 http://127.0.0.1:5174;`,
100+
`font-src 'self' data:;`,
101+
`media-src 'self';`,
102+
`form-action 'self';`,
103+
].join(" ");
104+
const headers = {
105+
...details.responseHeaders,
106+
"Content-Security-Policy": [csp],
107+
};
108+
callback({ responseHeaders: headers });
109+
});
110+
65111
win.on("ready-to-show", () => {
66112
if (!win.isDestroyed()) win.show();
67113
});

0 commit comments

Comments
 (0)