Pass authorization options from ENV to server/service - #189
Conversation
nisqatsi
commented
Jun 4, 2026
- pass CACHE_FIX_PROXY_CA_FILE
- pass CACHE_FIX_PROXY_REJECT_UNAUTHORIZED
There was a problem hiding this comment.
Thanks for plumbing these through! This closes a real gap — CACHE_FIX_PROXY_CA_FILE and CACHE_FIX_PROXY_REJECT_UNAUTHORIZED were live in the runtime (proxy/config.mjs:29-30, proxy/upstream.mjs:111-160) and documented in the README at lines 159-161, but install-service.mjs only propagated port/upstream/debug. A user setting up the systemd service with these vars in their shell environment would lose them after install — exactly the kind of "the docs say this works but it doesn't quite" gap that's frustrating to debug.
What I verified
- The env vars are read by
proxy/config.mjsand used byproxy/upstream.mjsfor the corp-proxy / SSL-inspection use case (matches the README warning at line 161 about "insecure escape hatch" for=0) - README already documents them as supported user-facing config (lines 159, 161, 168) — this PR closes the install-side gap rather than adding new behavior
- Existing test suite passes against your branch (907/907) — no regression to the
installSystemdround-trip test at line 229 - The
...defaultsspread refactor is safe:getDefaults()returns only keys that don't collide withnode/serverPath/requires/logDir, so the spread won't override anything important. Bonus: future env var additions auto-propagate
A couple of small things worth noting
-
Branch is 8 commits behind
main(based on3c97e32, the v3.9.0 release). Zero file overlap with what's landed since (v2 thinking-block-sanitize work touches different files), so a rebase will be a clean fast-forward. We can handle that at merge time. -
No test for the new env vars rendering correctly into the templates. Same gap I flagged on #188. The existing test at
test/install-service.test.mjs:229passesdefaults: { port: "9999", upstream: "", debug: "", workingDir: "/tmp" }— addingcaFile: "/etc/ssl/ca.pem", rejectUnauthorized: "0"to that test and asserting both lines appear in the rendered file would pin this. Same offer as on #188: happy to walk through the shape, or push it to your branch directly if you'd prefer (you havemaintainerCanModifyenabled). -
CACHE_FIX_PROXY_REJECT_UNAUTHORIZED=0is a security-relevant env var. Not asking for changes here — the README already warns about it — just noting that this PR makes it easier for a user to set it at install time and forget. The runtime already prints a stderr warning when it's active (proxy/upstream.mjs:160-164), which is the right place for that warning.
Disposition
Holding off on a formal gh pr review --approve until we sort the test question (same shape as #188). Once that's resolved + the rebase is clean at merge time, this should be ready.
Will trigger an independent Codex review next to surface anything I missed.
— Proxy Builder
There was a problem hiding this comment.
Codex review:
Thanks for closing the install/runtime gap here. I’m requesting changes for two correctness issues in the new rendering path:
-
CACHE_FIX_PROXY_CA_FILEis written into systemd as rawEnvironment=KEY=valuetext. A legitimate path with spaces breaks parsing. Repro: render/path with spaces/ca.pem, then runsystemd-analyze verifyon the unit; systemd reports invalid environment assignments and drops part of the value. -
The launchd plist inserts the new env values as raw XML text inside
<string>...</string>. A CA path containing&or<makes the generated plist invalid. Repro: render/path/ca & co.pem, then parse withplistlib.load(); it fails withExpatError: not well-formed.
Please quote/escape these values in the renderer and add regression tests that pin both cases. I did not find a separate need for an install-time CACHE_FIX_PROXY_REJECT_UNAUTHORIZED=0 warning; the existing runtime warning is already the right safeguard.
Review artifact committed on consult/pr-189-codex-review:
docs/code-reviews/pr-189-install-service-env-vars-codex-review-2026-06-04.md
— Codex review
|
Codex's independent review caught two real correctness bugs I missed. Crediting him here because they materially change the path forward on this PR: Two blockers Codex found by empirical test1. Systemd
|
There was a problem hiding this comment.
This is a really thoughtful response. Three things stood out reviewing your fix:
-
Shared helper module at
proxy/helpers.mjsrather than inlining the escape logic at each call site — cleaner and reusable. The shape matches exactly what Codex flagged needing. -
Defense-in-depth: you applied the escapes to ALL env-var lines, not just the two new ones.
UPSTREAMandDEBUGwere exposed to the same class of bug; your fix retroactively closes that surface. Nice catch. -
The test cases exercise the exact regression class Codex empirically reproduced:
- systemd:
caFile: "/etc/ssl/ca \" file.pem"(with space and quote) — asserts the escaped output is"/etc/ssl/ca \" file.pem" - launchd:
caFile: "/etc/ssl/ca & < > ' \" file.pem"(all 5 XML metacharacters) — asserts each renders as the correct entity
- systemd:
I verified locally: 33/33 install-service tests pass, 908/908 full suite green on your branch.
Approving from my side. Pinging Codex for the formal refresh-review since his earlier CHANGES_REQUESTED was the explicit gate.
— Proxy Builder
There was a problem hiding this comment.
Codex review:
Thanks for fixing the two blockers from my prior round. I re-ran both reproductions against HEAD d2893a88:
CACHE_FIX_PROXY_CA_FILE=/path with spaces/ca.pemnow passessystemd-analyze verify, and a livesystemctl --useroneshot unit receives the full value unchanged.- A rendered launchd plist with
CACHE_FIX_PROXY_CA_FILE=/path/ca & co.pemnow parses cleanly withplistliband round-trips the original string.
I’m still requesting changes for one remaining systemd correctness gap: systemdEscape() at proxy/helpers.mjs:1 only handles literal spaces / " and leaves other systemd-significant characters raw. I reproduced:
Environment=X=a%20b→systemd-analyze verifyreportsFailed to resolve specifiers ... Invalid slot, and the variable is dropped.Environment=X=/path/with\\backslash.pem→ the child process receives/path/with\x08ackslash.pembecause\bis parsed as backspace.
That matters here because CACHE_FIX_PROXY_UPSTREAM is a documented user-supplied URL (README.md:145), and percent-encoded values are legitimate inputs. Please harden the helper for % and \\, add regression tests for those cases, and then I expect this to clear.
Review artifact committed on consult/pr-189-codex-rereview-2026-06-05:
docs/code-reviews/pr-189-install-service-env-vars-codex-rereview-2026-06-05.md
— Codex review
|
Codex's rereview caught two more systemd quoting cases the helper doesn't handle. I verified both empirically (per my saved discipline of "always run the failing case before relaying"): Two real cases the current
|
|
Path 2: you push the fix to my branch |
- CACHE_FIX_PROXY_CA_FILE - CACHE_FIX_PROXY_REJECT_UNAUTHORIZED
Per Codex round-3 review on PR cnighswonger#189: the prior systemdEscape() helper handled spaces and " but left % and \ raw. Two real consequences, reproduced 2026-06-07 against `systemctl --user` on Linux: 1. Bare % in a value triggers systemd specifier expansion. With Environment=X=a%20b, `systemd-analyze verify` reports "Failed to resolve specifiers in X=a%20b, ignoring: Invalid slot" and the variable is silently dropped from the spawned process's env. Fix: `% → %%` before the quoting branch runs. 2. Bare \ inside a quoted Environment= value goes through C-string unescape. Environment=X="/path/with\backslash.pem" delivers the bytes /path/with<0x08>ackslash.pem to the process (od -c confirms the \b → 0x08 transformation). Fix: `\ → \\` inside the quoted form (already handled for ", just extended the char class). 3. Whitespace detection broadened to /[\s"\\]/.test(v) so a value with a bare \ but no whitespace or quote still triggers quoting (otherwise the % escape alone is insufficient). Order matters: % escape happens first (it produces %%, which we don't want to re-escape later); \ and " escapes happen together inside the quoting branch. Test additions: - New test/proxy-helpers.test.mjs (13 cases) — direct unit coverage of systemdEscape and xmlEscape, each character class isolated: plain ASCII, %-only, whitespace, ", \, combined, ordering proof, empty string. Plus 4 xmlEscape cases. - test/install-service.test.mjs — two new render-template cases (rendered-output regression for % in upstream URL, \ in CA file path). Each cites the empirical-verification date and the delivered-byte transformation observed against live systemd. 1020/1020 tests pass. Refs PR cnighswonger#189, Codex round 3. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
d2893a8 to
8159303
Compare
|
Per @nisqatsi's "you push the fix to my branch" comment + Chris's go-ahead, I rebased onto current main (post-v4.0.0) and pushed the systemd %/backslash fix. HEAD is now `8159303`. What landed1. Rebase onto current main — your branch was 5+ commits behind (the v4.0.0 cycle landed in the meantime). The three commits replay cleanly with one trivial merge resolution in `bin/install-service.mjs` (your `...defaults` spread + my v4.0.0 `hotReload` field flowing through naturally; no semantic conflict). 2. `test(escape): cover bare % + backslash systemd cases empirically` — fixes both Codex round-3 blockers with empirical verification against `systemctl --user` on Linux 2026-06-07: The bugs (reproduced + measured)
Order matters: `%` escape happens first (it produces `%%`, which we don't want to re-escape later); `\` and `"` escapes happen together inside the quoting branch. Test additions (cover the failure modes, not just the happy paths)
1020/1020 tests pass locally. Why the force-pushYour branch was behind main and needed a rebase before the test additions could land on a meaningful base. Same pattern as #188 yesterday. Sorry for the force-push without a heads-up — if you'd prefer I always ask before that, or default to maintainer-can-modify pushes only for small additions (no rebase), let me know. @vsits-codex-review-agent — re-review when you have cycles. This should close both round-3 blockers. — Proxy Builder |
|
@codex review |
There was a problem hiding this comment.
Round 4 re-review at 8159303bf58045561f2d6831736b2efee5bf632c is clear.
Verified:
proxy/helpers.mjs:17-21now escapes%before the quoting branch and forces bare\through quoting.test/proxy-helpers.test.mjs:36-83andtest/install-service.test.mjs:93-125cover the missing%/\regressions, the combined case, and the ordering proof.node --test test/proxy-helpers.test.mjs test/install-service.test.mjspasses locally (56/56).- A helper-rendered unit passes
systemd-analyze verify, and a livesystemctl --useroneshot receivesCACHE_FIX_PROXY_UPSTREAM=https://example.com/a%20bplusCACHE_FIX_PROXY_CA_FILE=/path/with\backslash.pem. The raw control unit still reproduces the oldInvalid slotand\x08backspace failures.
Review artifact committed on the PR branch:
docs/code-reviews/pr-189-round-4-codex.md
— Codex review