mirror of
https://github.com/atiilla/GeoIntel.git
synced 2026-04-26 16:15:57 +03:00
[PR #14] [MERGED] Fix 5 code scanning security vulnerabilities (XSS, API key exposure, error leakage, localStorage, CORS) #11
Labels
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
starred/GeoIntel#11
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/atiilla/GeoIntel/pull/14
Author: @Copilot
Created: 3/9/2026
Status: ✅ Merged
Merged: 3/9/2026
Merged by: @atiilla
Base:
main← Head:copilot/fix-security-vulnerabilities📝 Commits (2)
6c858b7Initial plan6f5b018Fix 5 security vulnerabilities: XSS, API key exposure, error info leak, localStorage, CORS📊 Changes
3 files changed (+40 additions, -18 deletions)
View changed files
📝
geointel/cli.py(+1 -1)📝
geointel/web_server.py(+23 -10)📝
geointel_ui_template/index.html(+16 -7)📄 Description
_getCryptoKey,_encryptValue,_decryptValue) using AES-GCM with PBKDF2-derived keygetStoredApiKeyasync — decrypts stored value before returningstoreApiKeyasync — encrypts key before callingsessionStorage.setItemupdateApiKeyIndicatorto be async andawait getStoredApiKey()showApiKeyModalto be async andawait getStoredApiKey()processImagetoawait getStoredApiKey()saveApiKeyBtnclick handler to be async andawait storeApiKey()window.loadhandler to be async and await async callsOriginal prompt
Security Fixes — Code Scanning Alerts
Fix all 5 security vulnerabilities identified by code scanning in the
atiilla/GeoIntelrepository.Fix 1 — XSS via
innerHTMLwith unsanitized AI output (CWE-79)File:
geointel_ui_template/index.html— Line 995Problem: The
interpretationfield from the Gemini API response is injected into the DOM using.innerHTML. TheformatAnalysis()function already escapes&,<,>characters but the result is then set via.innerHTML. This is fine since it's escaped, BUT the current code path does NOT escape before setting innerHTML in all places. Make the fix robust.Fix: The
formatAnalysis()function already does basic escaping. Ensure theinnerHTMLassignment on line 995 only ever receives output fromformatAnalysis()(which escapes&,<,>), and add a comment noting this is intentional safe HTML (pre-escaped). Also add asanitizeText()helper that usestextContentassignment trick for proper escaping, and updateformatAnalysis()to use it instead of manual regex replacement, making it more robust against future bypasses.Replace the manual regex escaping in
formatAnalysis:Then use
escapeHtml()insideformatAnalysis()instead of the regex chain.Fix 2 — API key transmitted in request body (CWE-319)
File:
geointel/web_server.pyandgeointel_ui_template/index.htmlProblem: The Gemini API key is passed from the browser in every
/api/analyzePOST request body (api_keyfield). This exposes the key in HTTP logs, browser history, and network traffic.Fix: Add support for reading the API key from the
X-Api-KeyHTTP request header instead of (or in addition to) the request body. Updateweb_server.pyto prefer the header over the body field:Update
index.htmlto send the API key as a header instead of in the body:Also update the modal note from "Stored locally in your browser. Never leaves your device." to "Stored in session only. Sent securely via request header." since we're also changing to sessionStorage (Fix 4).
Fix 3 — Internal error details leaked in 500 responses (CWE-209)
File:
geointel/web_server.pyProblem: All exception handlers return
str(e)in thedetailsfield, leaking internal error messages, file paths, and stack info to clients.Fix: Remove
str(e)from all 500-level JSON error responses. Keep loggingstr(e)server-side for debugging but return a generic message to the client. Apply to the genericExceptionhandler inanalyze_image()and inreverse_image_search():Apply the same change to the
reverse_image_searchendpoint's generic exception handler.Also update the
internal_errorerror handler (line ~230):Fix 4 — API key persisted in
localStorage(CWE-312)File:
geointel_ui_template/index.htmlProblem: The Gemini API key is stored in
localStoragewhich persists indefinitely and is accessible to any JavaScript running on the page.Fix: Change
localStoragetosessionStoragefor the API key so it only exists for the current browser session and is cleared when the tab/browser is closed: