Skip to content

Commit 2f8b2b9

Browse files
codeslakeclaude
andcommitted
docs: genericize sibling-component references for upstream
The comments named the specific account-switching proxy this was measured against. Upstream readers have no such component; the hazard is generic to any second MITM on the same host, so name the shape rather than the tool. Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 251dc6f commit 2f8b2b9

2 files changed

Lines changed: 11 additions & 9 deletions

File tree

bin/claude-via-proxy.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,8 @@ if (remoteControl) {
214214
claudeEnv.https_proxy = proxyUrl;
215215
// Publish our MITM CA where other components can find it. NODE_EXTRA_CA_CERTS
216216
// takes ONE file, so whoever assigns it last wins and every other CA is
217-
// silently untrusted — measured 2026-07-30 against cswap's pin proxy, which
217+
// silently untrusted — measured 2026-07-30 against an account-switching pin
218+
// proxy, which
218219
// also MITMs api.anthropic.com and also set the var, breaking Remote Control
219220
// inbound on the work Mac. The fix is a directory each component publishes its
220221
// own file into, so a bundle can be built from all of them.

test/proxy-wrapper.test.mjs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ describe("launch wrapper (claude-via-proxy)", { concurrency: 1 }, () => {
228228

229229
// --- ca-trust.d: coexisting with another component that also MITMs ---------
230230
// NODE_EXTRA_CA_CERTS takes ONE file, so a plain assignment silently untrusts
231-
// whatever else needed trusting. Measured 2026-07-30: cswap's pin proxy also
231+
// whatever else needed trusting. Measured 2026-07-30: an account-switching pin proxy also
232232
// MITMs api.anthropic.com and also set this var; last writer won and broke
233233
// Remote Control inbound on the work Mac. The contract: each component
234234
// publishes ONLY its own ca-trust.d/<name>.pem, one external writer builds the
@@ -298,7 +298,7 @@ describe("launch wrapper (claude-via-proxy)", { concurrency: 1 }, () => {
298298
const configDir = mkdtempSync(join(tmpdir(), "cfftrust-"));
299299
const trustDir = join(configDir, "ca-trust.d");
300300
mkdirSync(trustDir, { recursive: true });
301-
const sibling = join(trustDir, "cswap-pin.pem");
301+
const sibling = join(trustDir, "other-component.pem");
302302
const SIBLING_BYTES = "# another component's CA — must survive untouched\n";
303303
writeFileSync(sibling, SIBLING_BYTES);
304304
const script = 'process.stdout.write("OK\\n")';
@@ -354,9 +354,9 @@ describe("launch wrapper (claude-via-proxy)", { concurrency: 1 }, () => {
354354
// with a leaf signed by the CCF CA and a bundle = good.pem + torn.pem:
355355
// torn AFTER -> "Ignoring extra certs ... bad end line", verify still ok
356356
// torn BEFORE -> "... ASN1 lib", verify FAILS UNABLE_TO_VERIFY_LEAF_SIGNATURE
357-
// The builder concatenates sort(ca-trust.d/*.pem), and "ccf.pem" sorts before
358-
// "cswap-pin.pem", so a torn OURS lands in the fatal position and takes every
359-
// other component CA and corporate root down with it. A plain
357+
// The builder concatenates sort(ca-trust.d/*.pem), so a torn OURS lands ahead
358+
// of any sibling that sorts later and takes every other component CA and
359+
// corporate root down with it. A plain
360360
// writeFileSync(dst) is exactly what leaves that state visible to a
361361
// concurrent builder, so the write must be rename-into-place.
362362
//
@@ -474,7 +474,8 @@ describe("launch wrapper (claude-via-proxy)", { concurrency: 1 }, () => {
474474
// the very proxy it is about to be routed through: every request fails TLS
475475
// instead of merely losing another component's CA. A stale builder is the
476476
// normal state right after a CCF upgrade, so this is not a corner case.
477-
// (cswap hit the same hazard from the other side and guards it identically.)
477+
// (a sibling component hit the same hazard from the other side and guards
478+
// it identically.)
478479
const configDir = mkdtempSync(join(tmpdir(), "cfftrust-"));
479480
const bundle = join(configDir, "ca-trust.pem");
480481
// A plausible stale bundle: real PEM content, just not ours.
@@ -513,8 +514,8 @@ describe("launch wrapper (claude-via-proxy)", { concurrency: 1 }, () => {
513514
//
514515
// Counting BEGIN vs END markers catches exactly this and nothing else; the
515516
// containment check catches the stale bundle and cannot see a tear. Both are
516-
// needed, neither subsumes the other (independently reproduced by cswap, whose
517-
// pin proxy is both producer and consumer of the same directory).
517+
// needed, neither subsumes the other (independently reproduced by a sibling
518+
// component that is both producer and consumer of the same directory).
518519
//
519520
// Reader beware: this is a cheap pre-flight guard, not proof. Balanced markers
520521
// and containment together still do not prove Node verifies with the result —

0 commit comments

Comments
 (0)