security: fix 3 critical vulnerabilities

1. Remove raw API key from get_settings response
   - getServerSettings() no longer returns gemini_key in plain text
   - Only gemini_key_set (boolean) and settings_token_set (boolean)
   - JS updated to only check gemini_key_set (removes stale gemini_key fallback)

2. Protect save_settings with SETTINGS_TOKEN
   - If SETTINGS_TOKEN is set in .env, all save_settings calls must
     include matching X-Settings-Token header (uses hash_equals)
   - Empty token = no protection (backwards-compatible default)
   - Settings UI (Security tab) has a token input field
   - Wrong/missing token returns HTTP 403 with error 'unauthorized'
   - JS shows '🔒 Token non valido o mancante' on 403

3. DEMO_MODE native blocking in PHP
   - DEMO_MODE=false added to .env (default off)
   - When DEMO_MODE=true, all write actions return HTTP 403 before routing
   - Blocked: save_settings, product_save/delete/merge, inventory_add/use/update/remove,
     dismiss_anomaly, bring_add/remove/sync
   - demo_mode flag exposed via get_settings so JS can adapt UI
This commit is contained in:
dadaloop82
2026-05-04 06:20:23 +00:00
parent 529c09fda3
commit bf27469228
3 changed files with 59 additions and 9 deletions
+10
View File
@@ -870,6 +870,16 @@
</div>
<!-- Security Tab -->
<div class="settings-panel" id="tab-security">
<div class="settings-card">
<h4>🔑 Token Impostazioni</h4>
<p class="settings-hint">Se <code>SETTINGS_TOKEN</code> è configurato nel <code>.env</code> server, inserisci qui il token prima di salvare le impostazioni. Lascia vuoto se non configurato.</p>
<div class="form-group">
<label>Token di accesso</label>
<input type="password" id="setting-settings-token" class="form-input" placeholder="(vuoto = nessuna protezione)">
<button class="btn btn-small btn-secondary mt-2" onclick="togglePasswordVisibility('setting-settings-token')">👁️ Mostra/Nascondi</button>
</div>
<p class="settings-hint" id="settings-token-status-hint" style="display:none;color:var(--accent)">🔒 Questo server richiede un token per salvare le impostazioni.</p>
</div>
<div class="settings-card">
<h4>🔒 Certificato HTTPS</h4>
<p class="settings-hint">Se il browser mostra l'errore "La connessione non è privata" (ERR_CERT_AUTHORITY_INVALID), devi installare il certificato CA nel dispositivo.</p>