Measured. Binding the proxy to the Docker bridge instead of loopback is
enough to make container traffic reach it, and needs no code change in
either pmg or the agent. The agent reads the address from the proxy state
file, so the redirect target follows.
127.0.0.1 container connection failed, never reached the proxy
172.17.0.1 curl exit 60, reached the proxy and refused the certificate
Exit 60 is a certificate error, so TCP completed and TLS began. Host
traffic was unaffected in the same run.
CA trust inside the container stays unsolved and is probably unsolvable
from the host, since a container has its own trust store and injecting
into it requires whoever starts the container to mount it. For containers
the guarantee therefore degrades to fail closed.
Only the default bridge is covered. Compose and custom networks use other
gateways, which needs bpf_get_netns_cookie to select a target per
namespace. A non loopback bind also exposes the proxy, so it wants a
firewall rule outside an isolated runner.
SETUP.md gains an optional Docker section with the commands and the
expected exit code, and Current Limits is corrected.
Went through every step against a clean machine. Six problems:
Step 4 still claimed the setup command uses npm to write certificate
config. That stopped being true when npm handling was removed. npm is
now needed only for the test.
Step 5 did not say where to clone, while later steps assume ~/pmg.
Step 7 told the reader to verify the build after the command block had
already copied the binary. The block now builds, verifies, then installs.
Step 9 pre-created the proxy state directory. The proxy creates it
itself through os.MkdirAll, at 0700 rather than the 0755 the manual
command produced.
Steps 13 and 14 showed hardcoded uids 999 and 1001. They are assigned by
the system and differed on the next machine, which read as a mismatch.
Step 15 was wrong in a way that hid a real gap. On a dual stack machine
curl prefers IPv6, the hook is connect4 only, so the connection bypassed
enforcement entirely and returned the real package. The step now uses
curl -4 and explains why. Current Limits records the measurement.
v1 owns one trust mechanism: the system trust store. Every user and every
program that reads it gets the proxy CA with no configuration. Programs
that carry their own certificate list are documented rather than managed,
because each keeps that list in a different place and format.
ca install now calls truststore.Install with system scope and verifies the
result. ca remove untrusts before deleting, since a CA left trusted after
its files are gone is worse than one never installed: nothing points at
it, but whoever holds the old key can still intercept every user.
Only the public certificate reaches the trust store. The private key stays
0600 under the proxy user, which is the entire security boundary here.
Deletes npm_ca.go and the npm half of ca.go: the per user cafile handling,
the previous value save and restore, the read back verification, and the
--npm-user and --npm-bin flags.
Verified on Ubuntu with no per tool configuration anywhere: curl without
--cacert, npm without cafile, and a malicious package still blocked with
403. Removal confirmed to leave zero matches in ca-certificates.crt.
A fresh Ubuntu machine can have gcc without the C library headers. PMG
builds runtime/cgo, so the build fails with 'fatal error: errno.h: No
such file or directory'. Also adds a check that the build succeeded
before installing the binary, since a failed build leaves the previous
file in place.
SETUP.md walks a fresh Linux machine through the POC end to end, in
short numbered steps.
The design doc gains two measured sections. CA Trust records which
clients honour the system trust store and which ship their own roots,
along with the config file settings that work without environment
variables. Container Reachability records that the hook does reach into
containers but the redirect target does not, because loopback is
network namespaced.