You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while verifying #18 hands-on (2026-08-19, real container, --stacks java).
Problem
For devbox-installed JDKs, sandcat points every JVM at the mitmproxy-aware trust store via an env export appended to the tail of ~/.bashrc (baked in Dockerfile.app):
Debian's stock ~/.bashrc early-returns for non-interactive shells (case $- in *i*) ;; *) return;; esac), so anything appended after that guard is only visible in interactive shells.
Reproduction (fresh sandcat init --agent claude --stacks java project)
Interactive terminals — the primary human workflow — are fine. But non-interactive contexts miss the trust store: scripts run via bash -lc, CI-style invocations inside the sandbox, and potentially JVM commands spawned by the AI agent itself (agent tool-calls typically execute non-interactive shells). Result: Maven/Gradle/java invoked non-interactively fails PKIX against the transparent proxy even though the trust store copy exists and contains the CA.
Same failure class as the SSL_CERT_FILE-only-in-login-shells issue that #91 fixed for uv (by moving the knob to compose-level environment).
Suggested fix
Move the two exports out of .bashrc-tail into a scope that all shells (and the agent process tree) inherit — candidates, roughly in order of robustness:
sandcat.env (sourced by app-init.sh into the agent process env and copied to /etc/profile.d/ — covers login shells AND the agent's inherited environment), or
a dedicated /etc/profile.d/sandcat-java.sh written by app-user-init.sh after it prepares the cacerts copy, or
compose-level services.agent.environment (like Set uv TLS env vars automatically for the python stack #91 did for UV_SYSTEM_CERTS) — though the trust-store path is only valid once app-user-init.sh has created the copy, so a start-time-written profile.d file may fit better than a static compose entry.
The guards ([ -L ... ], [ -f ... ]) should move with the exports.
Notes
The apt-JDK path is unaffected — ca-certificates-java's hook regenerates /etc/ssl/certs/java/cacerts from the system store and the Debian JDK symlinks its own cacerts to it, so no env var is involved (verified in the same session: HTTP 200 with JAVA_TOOL_OPTIONS explicitly unset).
scala-cli's dedicated config (~/.local/share/scalacli/secrets/config.json) is also unaffected — it doesn't rely on the env var.
Found while verifying #18 hands-on (2026-08-19, real container,
--stacks java).Problem
For devbox-installed JDKs, sandcat points every JVM at the mitmproxy-aware trust store via an env export appended to the tail of
~/.bashrc(baked inDockerfile.app):Debian's stock
~/.bashrcearly-returns for non-interactive shells (case $- in *i*) ;; *) return;; esac), so anything appended after that guard is only visible in interactive shells.Reproduction (fresh
sandcat init --agent claude --stacks javaproject)(
Fetch.java= 10-linejava.net.http.HttpClientGET, single-file source mode.)Why it matters
Interactive terminals — the primary human workflow — are fine. But non-interactive contexts miss the trust store: scripts run via
bash -lc, CI-style invocations inside the sandbox, and potentially JVM commands spawned by the AI agent itself (agent tool-calls typically execute non-interactive shells). Result: Maven/Gradle/javainvoked non-interactively fails PKIX against the transparent proxy even though the trust store copy exists and contains the CA.Same failure class as the
SSL_CERT_FILE-only-in-login-shells issue that #91 fixed foruv(by moving the knob to compose-levelenvironment).Suggested fix
Move the two exports out of
.bashrc-tail into a scope that all shells (and the agent process tree) inherit — candidates, roughly in order of robustness:sandcat.env(sourced byapp-init.shinto the agent process env and copied to/etc/profile.d/— covers login shells AND the agent's inherited environment), or/etc/profile.d/sandcat-java.shwritten byapp-user-init.shafter it prepares the cacerts copy, orservices.agent.environment(like Set uv TLS env vars automatically for the python stack #91 did forUV_SYSTEM_CERTS) — though the trust-store path is only valid onceapp-user-init.shhas created the copy, so a start-time-written profile.d file may fit better than a static compose entry.The guards (
[ -L ... ],[ -f ... ]) should move with the exports.Notes
ca-certificates-java's hook regenerates/etc/ssl/certs/java/cacertsfrom the system store and the Debian JDK symlinks its own cacerts to it, so no env var is involved (verified in the same session: HTTP 200 withJAVA_TOOL_OPTIONSexplicitly unset).~/.local/share/scalacli/secrets/config.json) is also unaffected — it doesn't rely on the env var.