Update CSP to allow external fonts, scripts, and add corresponding test coverage
This commit is contained in:
+1
-1
@@ -439,7 +439,7 @@
|
|||||||
integrity="sha512-rCQgmUulW6f6QegOvTntKKb5IAoxTpGVCdWqYjkXEpzAns6XUFs8NKVqWe+KQpctp/EoRSFSuykVputqknLYMg=="
|
integrity="sha512-rCQgmUulW6f6QegOvTntKKb5IAoxTpGVCdWqYjkXEpzAns6XUFs8NKVqWe+KQpctp/EoRSFSuykVputqknLYMg=="
|
||||||
crossorigin="anonymous" defer></script>
|
crossorigin="anonymous" defer></script>
|
||||||
<script src="/vendor/dompurify.js" defer></script>
|
<script src="/vendor/dompurify.js" defer></script>
|
||||||
<script type="module" src="/js/script.js?v=20260930-chat-usability"></script>
|
<script type="module" src="/js/script.js?v=20261007-chat-csp-fix"></script>
|
||||||
<script type="module" src="/js/workspaceNavigation.js?v=20260909-account-controls"></script>
|
<script type="module" src="/js/workspaceNavigation.js?v=20260909-account-controls"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1017,7 +1017,7 @@ if (headerModelButton) headerModelButton.addEventListener("click", (event) => {
|
|||||||
});
|
});
|
||||||
saveGenerationSettingsBtn.addEventListener("click", () => { void saveGenerationSettings(); });
|
saveGenerationSettingsBtn.addEventListener("click", () => { void saveGenerationSettings(); });
|
||||||
roleplayNewPersonaBtn.addEventListener("click", closeRoleplayStarter);
|
roleplayNewPersonaBtn.addEventListener("click", closeRoleplayStarter);
|
||||||
clearUserPersonaBtn.addEventListener("click", () => {
|
if (clearUserPersonaBtn) clearUserPersonaBtn.addEventListener("click", () => {
|
||||||
closeChatDrawer();
|
closeChatDrawer();
|
||||||
void clearChatUserPersona();
|
void clearChatUserPersona();
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -221,7 +221,7 @@ function sameOriginProtection(config) {
|
|||||||
|
|
||||||
function browserSecurityHeaders(config) {
|
function browserSecurityHeaders(config) {
|
||||||
return (_req, res, next) => {
|
return (_req, res, next) => {
|
||||||
res.setHeader("Content-Security-Policy", "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: blob:; media-src 'self' blob:; connect-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'; font-src 'self' data:; worker-src 'self' blob:");
|
res.setHeader("Content-Security-Policy", "default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; img-src 'self' data: blob:; media-src 'self' blob:; connect-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; script-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; font-src 'self' data: https://fonts.gstatic.com; worker-src 'self' blob:");
|
||||||
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
|
res.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
|
||||||
res.setHeader("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=(), usb=()");
|
res.setHeader("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=(), usb=()");
|
||||||
res.setHeader("X-Content-Type-Options", "nosniff");
|
res.setHeader("X-Content-Type-Options", "nosniff");
|
||||||
|
|||||||
@@ -127,6 +127,16 @@ test("public health checks reach the backend without exposing diagnostics or req
|
|||||||
assert.equal((await request(server.baseUrl, "/admin/diagnostics")).status, 403);
|
assert.equal((await request(server.baseUrl, "/admin/diagnostics")).status, 403);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("CSP permits the pinned chat markdown script and the app's hosted fonts", async t => {
|
||||||
|
const server = await startTestServer();
|
||||||
|
t.after(() => server.close());
|
||||||
|
const response = await fetch(`${server.baseUrl}/`);
|
||||||
|
const policy = response.headers.get("content-security-policy");
|
||||||
|
assert.match(policy, /style-src[^;]*https:\/\/fonts\.googleapis\.com/);
|
||||||
|
assert.match(policy, /script-src[^;]*https:\/\/cdnjs\.cloudflare\.com/);
|
||||||
|
assert.match(policy, /font-src[^;]*https:\/\/fonts\.gstatic\.com/);
|
||||||
|
});
|
||||||
|
|
||||||
test("personality API keeps prompts private, validates IDs, and enforces chat ownership", async t => {
|
test("personality API keeps prompts private, validates IDs, and enforces chat ownership", async t => {
|
||||||
const server = await startTestServer();
|
const server = await startTestServer();
|
||||||
t.after(() => server.close());
|
t.after(() => server.close());
|
||||||
|
|||||||
Reference in New Issue
Block a user