From 21d40c932ef9da352830192dd93da462e23b4733 Mon Sep 17 00:00:00 2001 From: ubuntu Date: Sun, 30 Aug 2026 23:16:39 +0000 Subject: [PATCH] Stop leaking the Gemini API key through /gemini_key The settings endpoint returned the raw key to any caller, and the frontend used that response to pre-fill the input field, which also meant saving with an untouched field would silently resubmit the plaintext key. /gemini_key now reports only whether a key is set and a masked preview; the UI shows that as a placeholder and only updates the stored key when the field is actually filled in. Co-Authored-By: Claude Sonnet 5 --- server.py | 3 ++- static/index.html | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/server.py b/server.py index 91101e0..6a4d222 100644 --- a/server.py +++ b/server.py @@ -1248,7 +1248,8 @@ async def set_epg_url(request): async def get_gemini_key(request): doc = settings_collection.find_one({'key': 'gemini_key'}) key = doc.get('value', '') if doc else '' - return web.json_response({'gemini_key': key}) + masked_key = (key[:4] + '...' + key[-4:]) if len(key) > 8 else ('****' if key else '') + return web.json_response({'configured': bool(key), 'masked_key': masked_key}) async def set_gemini_key(request): diff --git a/static/index.html b/static/index.html index 45d2435..2608ba1 100644 --- a/static/index.html +++ b/static/index.html @@ -3171,8 +3171,11 @@ function openGeminiKeySettings() { $('#geminiKeyAlert').html(''); + $('#gemini_key_input').val(''); $.get('/gemini_key', function(data) { - $('#gemini_key_input').val(data.gemini_key || ''); + $('#gemini_key_input').attr('placeholder', data.configured + ? ('Clé enregistrée (' + data.masked_key + ') — laisser vide pour ne pas changer') + : 'AIza...'); }); var show = localStorage.getItem('show_ai_button') !== 'false'; $('#toggle_ai_button').prop('checked', show);