Skip to content

Fix/sanitize non utf8 source bytes - #571

Open
seanmaher-scrape wants to merge 2 commits into
helixml:mainfrom
seanmaher-scrape:fix/sanitize-non-utf8-source-bytes
Open

seanmaher-scrape wants to merge 2 commits into
helixml:mainfrom
seanmaher-scrape:fix/sanitize-non-utf8-source-bytes

Conversation

@seanmaher-scrape

Copy link
Copy Markdown

Problem
SourceText.Text() (the default plain-text extractor in infrastructure/extraction/source.go) only checks for null bytes to detect binary content — it does no encoding validation. string(content) reinterprets raw bytes without transcoding, so a source file saved in a non-UTF-8 encoding (e.g. Windows-1252/Latin-1 — common in older codebases with characters like ä/ö/ü) passes through extraction and chunking untouched.

This fails downstream at persistence: the enrichment store's INSERT hits Postgres with invalid UTF-8, which Postgres's UTF-8 client/server encoding rejects outright (SQLSTATE 22021, invalid byte sequence for encoding "UTF8").

The impact is worse than a single dropped file: ChunkFiles.persistChunks propagates that error with a hard return, and its caller's file loop has no continue around it — so one non-UTF-8 file aborts the rest of that commit's chunk extraction entirely, not just its own enrichment.

Confirmed there's no existing UTF-8 handling anywhere in the extraction/persistence path (grepped the whole module for unicode/utf8 usage — the only hit is unrelated query-token counting in domain/search/token_budget.go).

Fix
SourceText.Text() now runs the extracted content through strings.ToValidUTF8, replacing invalid byte sequences with U+FFFD instead of passing them through raw. Minimal, no charset auto-detection needed — just stops the hard failure.

Testing
go build ./... and go vet ./... clean.
New tests in source_test.go: plain UTF-8 content unchanged, binary detection still works, and a real non-UTF-8 byte sequence (0xe4 0xf6 0xfc) gets sanitized to valid UTF-8.
Ran the full infrastructure/extraction package suite — 4 pre-existing failures in pdfium_text_renderer_test.go (Windows/WebAssembly path handling, unrelated) confirmed present with this change reverted too, so not a regression introduced here.

seanmaher-scrape and others added 2 commits September 21, 2026 12:07
/healthz always returns 200 with no DB check, so it can't serve as a
real Kubernetes readiness probe -- a pod could be marked ready and
receive traffic while unable to reach Postgres. /readyz pings the
database (via a new exported Client.Ping, reusing the existing GORM
connection pool rather than opening a new connection) with a 2-second
timeout, and returns 503 if unreachable.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Fixes CBST-2721: source files saved in a non-UTF-8 encoding (e.g.
Windows-1252/Latin-1, common in older codebases with characters like
a-umlaut/o-umlaut/u-umlaut) passed through extraction unmodified, then
failed the Postgres INSERT outright when persisted (client/server
encoding is UTF-8, SQLSTATE 22021). Because persistChunks propagates
that error with a hard return (no continue), a single bad file aborted
the rest of that commit's chunk extraction entirely.

SourceText.Text() now runs the extracted content through
strings.ToValidUTF8, replacing invalid byte sequences with U+FFFD
instead of passing them through raw. Confirmed no existing UTF-8
validation exists anywhere in the extraction/persistence path before
this change (grepped the whole module for unicode/utf8 usage).

This branch has not been deployed

No deployments
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.

1 participant