Security: remote-pack RCE, i18n XSS sink, credential and container hardening - #4
Open
phyersherman wants to merge 3 commits into
Open
Security: remote-pack RCE, i18n XSS sink, credential and container hardening#4phyersherman wants to merge 3 commits into
phyersherman wants to merge 3 commits into
Conversation
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
alloflow-cdn | 0370a81 | Jul 31 2026, 11:08 PM |
Owner
|
Thanks for the push! Ignore the deploy failed I think I need to fix some
tests. Very interersting I never thought the language pack loader could be
a vector but it makes sense. I'm not totally sure we need SearXNG it was
something I set up before learning about serper.dev which I am using for
free now but can pay for in the future. I think it does a great job pretty
much getting the same results as Google. Just a heads up that I'm working
on getting Claude to an AlloFlow remediation MCP so people can just have it
remediate that way as well using their harness. I'm not really sure what
people/institutions will prefer but I think giving multiple options should
be a strong play. I think its at least partially operational if you are
curious.
…On Wed, Jul 29, 2026 at 2:13 PM cloudflare-workers-and-pages[bot] < ***@***.***> wrote:
*cloudflare-workers-and-pages[bot]* left a comment (Apomera/AlloFlow#4)
<#4 (comment)>
Deploying with [image: Cloudflare Workers] <https://workers.dev>
Cloudflare Workers
The latest updates on your project. Learn more about integrating Git with
Workers
<https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/>.
Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
<https://dash.cloudflare.com/?to=/37d398da2811e2beead8fe41dac52058/workers/services/view/alloflow-cdn/production/builds/e5c12e13-b874-42bd-8d9a-db3f32f763d8>
alloflow-cdn 9c8d60b
<9c8d60b> Jul
29 2026, 03:06 PM
—
Reply to this email directly, view it on GitHub
<#4?email_source=notifications&email_token=BABWTLHQQREIOZYFDM4MXXL5HI5FPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGE3TQMRSGQ4KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5121782248>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BABWTLDNHQSOBWXTXT6RHBT5HI5FPAVCNFSNUABGKJSXA33TNF2G64TZHMYTCMBYHE2TONJVGA5US43TOVSTWNJQGEZDGNJUGMYDTILWAI>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/BABWTLGRMLEVUXCFR2EWOY35HI5FPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGE3TQMRSGQ4KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/BABWTLF6J4T3WKRHSG7T3HT5HI5FPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGE3TQMRSGQ4KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Collaborator
Author
|
That sounds like a great idea. I will take a look at it tomorrow.
Sent from [Proton Mail](https://proton.me/mail/home) for iOS.
…-------- Original Message --------
On Wednesday, 07/29/26 at 20:55 Aaron H Pomeranz ***@***.***> wrote:
Apomera left a comment [(Apomera/AlloFlow#4)](#4 (comment))
Thanks for the push! Ignore the deploy failed I think I need to fix some
tests. Very interersting I never thought the language pack loader could be
a vector but it makes sense. I'm not totally sure we need SearXNG it was
something I set up before learning about serper.dev which I am using for
free now but can pay for in the future. I think it does a great job pretty
much getting the same results as Google. Just a heads up that I'm working
on getting Claude to an AlloFlow remediation MCP so people can just have it
remediate that way as well using their harness. I'm not really sure what
people/institutions will prefer but I think giving multiple options should
be a strong play. I think its at least partially operational if you are
curious.
On Wed, Jul 29, 2026 at 2:13 PM cloudflare-workers-and-pages[bot] <
***@***.***> wrote:
> *cloudflare-workers-and-pages[bot]* left a comment (Apomera/AlloFlow#4)
> <#4 (comment)>
> Deploying with [image: Cloudflare Workers] <https://workers.dev>
> Cloudflare Workers
>
> The latest updates on your project. Learn more about integrating Git with
> Workers
> <https://developers.cloudflare.com/workers/ci-cd/builds/git-integration/>.
> Status Name Latest Commit Updated (UTC)
> ❌ Deployment failed
> View logs
> <https://dash.cloudflare.com/?to=/37d398da2811e2beead8fe41dac52058/workers/services/view/alloflow-cdn/production/builds/e5c12e13-b874-42bd-8d9a-db3f32f763d8>
> alloflow-cdn 9c8d60b
> <9c8d60b> Jul
> 29 2026, 03:06 PM
>
> —
> Reply to this email directly, view it on GitHub
> <#4?email_source=notifications&email_token=BABWTLHQQREIOZYFDM4MXXL5HI5FPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGE3TQMRSGQ4KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5121782248>,
> or unsubscribe
> <https://github.com/notifications/unsubscribe-auth/BABWTLDNHQSOBWXTXT6RHBT5HI5FPAVCNFSNUABGKJSXA33TNF2G64TZHMYTCMBYHE2TONJVGA5US43TOVSTWNJQGEZDGNJUGMYDTILWAI>
> .
> Triage notifications, keep track of coding agent tasks and review pull
> requests on the go with GitHub Mobile for iOS
> <https://github.com/notifications/mobile/ios/BABWTLGRMLEVUXCFR2EWOY35HI5FPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGE3TQMRSGQ4KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJKTGN5XXIZLSL5UW64Y>
> and Android
> <https://github.com/notifications/mobile/android/BABWTLF6J4T3WKRHSG7T3HT5HI5FPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGE3TQMRSGQ4KM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
> Download it today!
> You are receiving this because you were mentioned.Message ID:
> ***@***.***>
>
—
Reply to this email directly, [view it on GitHub](#4?email_source=notifications&email_token=B44ZOJZFSR54MIM6RX4OK6L5HKMG3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGUYDIMBWGI2KM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-5125040624), or [unsubscribe](https://github.com/notifications/unsubscribe-auth/B44ZOJ44E3ZIZPPKPEZL6335HKMG3AVCNFSNUABGKJSXA33TNF2G64TZHMYTCMBYHE2TONJVGA5US43TOVSTWNJQGEZDGNJUGMYDTILWAI).
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for [iOS](https://github.com/notifications/mobile/ios/B44ZOJ7MMWZEKV455NT5RXL5HKMG3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGUYDIMBWGI2KM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG) and [Android](https://github.com/notifications/mobile/android/B44ZOJ3TVGBAHY43LVRTZ7D5HKMG3A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMJSGUYDIMBWGI2KM4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA). Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
…al paths
Language packs are untrusted input: they arrive from a user-chosen file, a CDN
fetch, or LLM translation output, and t() resolves them BEFORE the static
UI_STRINGS, so a pack can override any key.
- Drop the `new Function('return ' + text)` fallback in the pack loader. A
compromised pack host had arbitrary code execution in every client. All 63
shipped packs parse as pure JSON, so the eval was dead code for real packs.
- Sanitize every pack ingest (import, cached, remote, AI partial/final). Only
executable elements are removed; the a11y lab's deliberately-bad HTML samples
and inline <strong> markup are preserved byte-identical across all 63 packs.
Attribute scrubbing is confined to tag markup so prose like "10 ones = 1 ten"
is untouched, and "/" is treated as an attribute separator (<svg/onload=...>).
- Replace Math.random() for the anonymous account password, the live-session
code, and the LAN join PIN with CSPRNG draws. Rejection sampling keeps the
output uniform; chi-square over 2M draws confirms no modulo bias.
- Restrict CORS on the standalone TTS servers to loopback origins and bind
edge-tts to 127.0.0.1, matching piper.
- Write the School Box env file 0600 and chmod pre-existing ones.
- Pass Compress-Archive paths as arguments rather than splicing them into a
PowerShell command string.
Full suite matches the pre-existing baseline exactly (539 failing files, 133
failing tests, all present on clean main) plus 28 new passing tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ring Gemini accepts the key either way. The query-string form leaks: URLs reach browser history, proxy and server access logs, and Referer headers — places the request body never goes. utils_pure already stripped "?key=…" from error strings, which was the tell that these URLs were being captured. Moves all 24 call sites to the x-goog-api-key header across src/aiProvider.js, ai_backend_module.js, tts_module.js and utils_pure_module.js, plus their *_source.jsx originals and desktop/web-app/public mirrors. aiProvider and ai_backend route through a shared _geminiHeaders() helper. The key is added ONLY to generativelanguage.googleapis.com requests. The local Flux image server and the localhost Edge TTS endpoints in ai_backend keep plain headers — sending a user's Google key to another process is the failure this change is meant to avoid, not introduce. Retry paths carry the header too; the TTS retry was a separate call site from its parent request. Removing the key from the URL without adding the header would leave every call unauthenticated and look identical in a diff, so the new test pins both halves, across every duplicated copy, and asserts the non-Google endpoints stay clean. Updates the request-shape fixtures to the new contract (they pinned the old ?key= URL) and re-stamps the tts_module.js content hash in the host loader. Full suite matches the pre-existing baseline exactly: 539 failing files, 133 failing tests, all present on clean main. No new failures. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…aint Resource limits (CIS 16.7) -------------------------- No compose service declared deploy.resources.limits, so any one container could consume the host's CPU and memory — an ollama or flux run that grows without bound takes the whole School Box down with it, including PocketBase. Adds cpu/memory ceilings to all 19 services across the three compose files. The existing GPU device reservations on ollama and flux are preserved alongside the new limits. The values are deliberately generous and env-overridable (OLLAMA_MEMORY etc., documented in the .env.example files). These are safety ceilings, not workload sizing: a limit tight enough to OOM-kill legitimate inference would be a worse outcome than the exhaustion it prevents. Ollama and flux hold model weights in RAM, so their defaults are set high and are the ones to raise for large models. Verified by parsing all three files: every service carries limits, GPU reservations survive, and the top-level volumes key is intact. SearXNG secret -------------- Left in place, with the constraint documented. Moving it to an env var is not possible for this image: SearXNG resolves settings only from YAML (settings_loader.py honors SEARXNG_SETTINGS_PATH and nothing else — there is no env interpolation), and the upstream sed-substitution trick needs a writable settings.yml while ours is mounted read-only. The comment now records what the key actually signs (this instance's own session cookies — not a credential to any account or external service) and how to supply a per-install value by mounting a replacement. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
phyersherman
force-pushed
the
security/phase1-critical-fixes
branch
from
July 31, 2026 23:07
9c8d60b to
0370a81
Compare
Deploying alloflow-cdn with
|
| Latest commit: |
0370a81
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://f2d0538d.alloflow-cdn.pages.dev |
| Branch Preview URL: | https://security-phase1-critical-fix.alloflow-cdn.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 1 of the CIS v8.1 / NIST SSDF review. Reviewed and signed off by @Apomera; the DOMPurify item was resolved differently than originally proposed (see below).
What this fixes
Remote code execution in the language-pack loader (highest severity).
App.jsxrannew Function('return ' + text)()on fetched pack bodies, so a compromised CDN — or anyone landing a file inlang/on main — had arbitrary code execution in every client. All 63 shipped packs parse as pure JSON, so the eval was dead code for legitimate packs and only ever fired on malformed or malicious content. Removed.XSS through the i18n layer.
t()resolves the language pack before the staticUI_STRINGS, so a pack can override any key, and several STEM-lab consumers concatenatet()output intoinnerHTML. Three untrusted writers reach the pack: a user-chosen file (validated only as "is an object"), a CDN fetch, and LLM translation output.Fixed at the source rather than at the sinks. The per-sink approach would have patched 18 sinks in
stem_lab_module.js— a file that is not the one deployed — while leaving 37 instem_tool_solarsystem.js, which is what actually loads at runtime.The sanitizer removes only executable elements. 749 shipped strings legitimately contain markup (
<strong>, plus the a11y lab's deliberately-inaccessible<html>/<img>teaching samples), and it leaves all 1,654,508 strings across 63 packs byte-identical while neutralizing every payload tested.Credentials off
Math.random()— anonymous account password, live-session code, LAN join PIN. Rejection sampling keeps the output uniform; a chi-square test over 2M draws confirms no modulo bias.Gemini key out of URL query strings (24 sites). URLs reach browser history, proxy logs, and Referer headers.
utils_purealready stripped?key=…from error strings, which was the tell these URLs were being captured. The key is added only togenerativelanguage.googleapis.comrequests — the local Flux server and localhost Edge TTS endpoints keep plain headers.Also: loopback-only CORS + bind on the standalone TTS servers,
0600on the School Box env file, PowerShell paths passed as arguments instead of spliced into a command string, and CPU/memory ceilings on all 19 compose services (generous and env-overridable — a cap tight enough to OOM-kill inference would be worse than the exhaustion it prevents).Not fixed
The SearXNG
secret_keystays committed, with the constraint documented. It cannot move to an env var: SearXNG resolves settings only from YAML (settings_loader.pyhonorsSEARXNG_SETTINGS_PATHand nothing else), and the image's sed-substitution needs a writablesettings.ymlwhile ours is mounted read-only. It signs that instance's own session cookies and is not a credential to anything external.Verification
Baseline measured at
origin/main(1fa420161): 442 failing test files, 26 failing tests. This branch is identical — zero new failures — plus 48 new passing tests across two new suites.The new tests pin both halves of each fix. For the key migration that matters: removing the key from the URL without adding the header would leave every call unauthenticated and looks identical in a diff.