Main #15

Merged
Fretux merged 14 commits from main into dev 2026-10-12 08:59:14 +02:00
4 changed files with 13 additions and 3 deletions
Showing only changes of commit 5624eead82 - Show all commits
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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");
+10
View File
@@ -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());