Skip to content

fix: csv formula injection + local web server hardening#5

Merged
hamidi-dev merged 2 commits into
hamidi-dev:mainfrom
Gheat1:fix/security
Jul 7, 2026
Merged

fix: csv formula injection + local web server hardening#5
hamidi-dev merged 2 commits into
hamidi-dev:mainfrom
Gheat1:fix/security

Conversation

@Gheat1

@Gheat1 Gheat1 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Two security fixes:

CSV export formula injection β€” session titles, project dirs, and model names are written verbatim into the e-key export, so a cell starting with =, +, -, @, tab, or CR executes as a formula when the CSV is opened in Excel/LibreOffice/Sheets (titles come straight from prompts, so the content is attacker-influenced when browsing shared transcripts). Strings that would be read as formulas now get a leading apostrophe; plain-number strings (negative costs) and non-string cells pass through untouched, applied centrally in export_current so every dataset is covered.

--serve/--web hardening β€” /api/reload mutated state on a plain GET, so any webpage could fire it cross-origin (<img src="http://localhost:8321/api/reload"> β€” CSRF plus a cheap DoS since each hit re-parses the sources). It is POST-only now (GET answers 405, the page's refresh button posts). On the default loopback bind the Host header must name localhost/127.0.0.1/[::1] or the request gets 403, closing DNS rebinding; an explicit --bind beyond loopback keeps working as before. Every response now carries a CSP fitting the self-contained page plus X-Content-Type-Options: nosniff.

Tested: 3 new tests (sanitizer matrix incl. negative numbers, end-to-end export write, live server checks for 405/POST/403-on-foreign-Host); suite 307/307, ruff clean. Manually verified with --demo --serve + curl.

Gheat1 added 2 commits July 7, 2026 06:31
A session title, project dir, or model name starting with =, +, -, @,
tab, or CR is executed as a formula when the exported CSV is opened in
Excel/LibreOffice/Sheets. Prefix such strings with an apostrophe on
export; strings that are plain numbers (a negative cost) pass through
untouched, and non-string cells are never affected.
Harden --serve/--web against hostile webpages: /api/reload mutated
state on a plain GET, so any page could fire it cross-origin (CSRF /
cheap DoS -- every hit re-parses the sources); it is POST-only now, GET
answers 405 and the page's refresh button posts. On a loopback bind the
Host header must name localhost/127.0.0.1/[::1] (port optional) or the
request is refused with 403, closing DNS rebinding; an explicit --bind
beyond loopback keeps working and already warns. Every response carries
a deny-everything CSP fitting the self-contained page (inline JS/CSS,
data: favicon, same-origin fetches) plus X-Content-Type-Options.
@hamidi-dev

Copy link
Copy Markdown
Owner

Nice work - thanks for this. The CSV formula-injection one is a genuinely good catch; titles being prompt-derived makes it a real vector, and I like that the sanitizer leaves negative-number cells alone. Host-check + POST-only reload are the right call too. Pulled it locally, tests green - merging. πŸ™
Heads up I'm going through the other four you opened as well, so those'll trickle in over the next bit.

@hamidi-dev hamidi-dev merged commit 3356fd2 into hamidi-dev:main Jul 7, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants