fix: admin panel CSP blocking inline event handlers and boolean toggle display

CSP nonce policy blocked all onclick handlers, preventing navigation.
Switched to 'unsafe-inline' (admin panel is IP-restricted). Also fixed
boolean settings display — toggles now accept '1' from the database.
This commit is contained in:
jevb
2026-03-30 21:48:14 +02:00
parent bfe3404e14
commit d9aaeb5f4c
2 changed files with 3 additions and 17 deletions
+2 -16
View File
@@ -3,11 +3,7 @@
package admin
import (
"bytes"
"crypto/rand"
"embed"
"encoding/base64"
"fmt"
"io/fs"
"net/http"
@@ -51,19 +47,9 @@ func NewHandler(database *db.DB, version string, hub HubBroadcaster, u *updater.
}
r.Get("/", func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
// Generate a per-request nonce for inline script/style tags,
// avoiding 'unsafe-inline' in the CSP.
nonceBytes := make([]byte, 16)
if _, err := rand.Read(nonceBytes); err != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
nonce := base64.StdEncoding.EncodeToString(nonceBytes)
w.Header().Set("Content-Security-Policy",
fmt.Sprintf("default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'nonce-%s'", nonce))
// Inject nonce into the inline <script> tag.
nonced := bytes.Replace(indexHTML, []byte("<script>"), []byte("<script nonce=\""+nonce+"\">"), 1)
_, _ = w.Write(nonced)
"default-src 'self'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline'")
_, _ = w.Write(indexHTML)
})
r.Handle("/*", http.FileServer(http.FS(staticFS)))
+1 -1
View File
@@ -731,7 +731,7 @@ async function renderSettings(){
try{settings=await api('GET','/settings')}catch(e){return'<div class="page-title">Settings</div><p style="color:var(--red)">'+esc(e.message)+'</p>'}
state._settings={...settings};
const v=k=>settings[k]||'';
const isOn=k=>v(k)==='true';
const isOn=k=>v(k)==='1'||v(k)==='true';
let html='<div class="page-title">Server Settings</div><div class="page-desc">Configure your OwnCord server</div>';
html+='<div class="section-card"><div class="section-card-header"><h3>General</h3></div><div class="section-card-body">';
html+='<div class="setting-row"><div class="setting-info"><div class="setting-name">Server Name</div></div><div class="setting-ctrl"><input class="form-input" id="s-server_name" value="'+esc(v('server_name'))+'" style="width:240px" oninput="markSettingsChanged()"></div></div>';