Security hardening offline UI#577
Conversation
|
Thanks @lahirunirmalx — reviewed this closely and it's genuinely good, and actually security-positive: the drill-down explorer addresses the >10k-node OOM, and the hardening is all welcome (strict CSP, removing the Google Fonts CDN for a fully-offline UI, fail-closed self-update, and the read-only, fully-parameterized Two things before it can land:
Once it's rebased and trimmed, this is good to go. 🙏 |
Remove the runtime dependency on third-party font CDNs when viewing a codebase in the graph UI: - 2D UI (Inter + JetBrains Mono): drop the Google Fonts <link> in index.html and self-host via @fontsource packages imported in main.tsx; Vite bundles the woff/woff2 locally. - 3D node labels (troika/drei <Text>): troika only calls its unicode-font-resolver (a cdn.jsdelivr.net fetch) for characters not covered by an explicit font. Vendor DejaVu Sans (Latin/Greek/Cyrillic) under public/fonts and pass it via the font prop, so code identifiers render with zero external requests. DejaVu license included. Signed-off-by: lahiru <lahirunirmalx@gmail.com>
Security and build-portability fixes: - self-update (cli.c): fail closed. download_verify_install now aborts and deletes the archive on any non-zero checksum result, not only an explicit mismatch. Previously a 'could not verify' (missing checksums.txt, archive not listed, or no sha256 tool) fell through and installed an unverified binary. Offline hosts can opt in with CBM_ALLOW_UNVERIFIED_UPDATE=1 (loud warning). - startup update check (mcp.c): add CBM_NO_UPDATE_CHECK=1 opt-out so restricted-egress / air-gapped setups can disable the GitHub call. - UI server (http_server.c): send a strict Content-Security-Policy on the document. Egress is pinned to 'self' (connect-src/font-src/img-src), so the browser refuses any external request when viewing a proprietary codebase. script-src allows blob: (three.js/troika spawn blob: workers that importScripts blob URLs); blob: is local and does not widen egress. - build (Makefile.cbm): link -ldl on non-Windows. SQLite's dlopen/dlsym live in a separate libdl on glibc < 2.34, breaking the link otherwise. - embed-frontend.sh: add .ttf/.otf content types for vendored fonts. Signed-off-by: lahiru <lahirunirmalx@gmail.com>
This file is produced by scripts/embed-frontend.sh during the --with-ui build (base64 of the bundled graph UI); it is a build artifact, not source, and should not be tracked. Signed-off-by: lahiru <lahirunirmalx@gmail.com>
d84ca69 to
998bf2d
Compare
Rendering the whole graph (299k nodes / 1.07M edges) OOM-killed the server building the layout and overwhelmed the browser. Replace it with a semantic-zoom explorer that represents every node while only ever materializing one level at a time. Backend: - cbm_store_expand_tree: group nodes one level below a qualified_name prefix and aggregate cross-group relationship edges into weighted super-edges. Parameterized SQL with a range predicate on the (project, qualified_name) index; memory-safe at any repo size. - /api/graph?project=&parent=: aggregated children + super-edges with Fibonacci-sphere positions, behind an in-memory memo cache (the index is static per run: cold ~6s once, warm ~10ms). - search params gain an optional include_labels whitelist (label IN (...)); cbm_layout_compute takes a label arg and balances multi-label requests per label so one label cannot crowd out the rest. Frontend: - useGraphData fetches /api/graph per level; GraphTab drills on click with breadcrumb navigation up the path. - LevelList: aim-free clickable list of the current level. The 3D bloom glow is far larger than the clickable sphere, so clicks on the halo missed; also enlarge the hit spheres and widen node spread. Verified: ASan suite (no sanitizer hits); headless-Chrome CDP confirms both list-row and 3D-node clicks drill in with no JS errors. Signed-off-by: lahiru <lahirunirmalx@gmail.com>
998bf2d to
cfc0897
Compare
Done ! check its good enough |
What does this PR do?
Replaces the graph UI's whole-graph layout — which OOM-killed the server trying to lay out 299k nodes / 1.07M edges, and froze the browser — with a hierarchical drill-down explorer that represents a codebase of any size while only ever materializing one level at a time.
Backend: new cbm_store_expand_tree + GET /api/graph?project=&parent= — groups nodes one level below a qualified-name prefix and aggregates cross-group relationship edges into weighted super-edges. Parameterized SQL with a range scan on the (project, qualified_name) index, results memoized (index is static per run). Memory-safe at any size (root view ~7 KB, RSS ~13 MB vs the old ~14 GB).
Frontend: overview → click-to-drill → breadcrumbs, plus an aim-free LevelList and larger 3D hit targets (the bloom glow was bigger than the clickable sphere, so halo clicks missed).
Adds an include_labels whitelist (label IN (...)) to search params; cbm_layout_compute gains a label arg with per-label balancing.
Checklist
git commit -s) — required, CI rejectsunsigned commits (DCO, see CONTRIBUTING.md)
make -f Makefile.cbm test)make -f Makefile.cbm lint-ci)