fix(process): keep network approval fail-closed

This commit is contained in:
morluto
2026-07-13 03:30:17 +00:00
parent 329fdf6fe8
commit 9526389f81
3 changed files with 5 additions and 23 deletions
+3 -3
View File
@@ -361,9 +361,9 @@ Closing a REA session shuts down its bridge and removes its private socket direc
Process capture is disabled by default. Enabling it requires
`REA_PROCESS_CAPTURE_ENABLED=true`, approved executable and working roots in
`REA_PROCESS_EXECUTABLE_ROOTS_JSON` and `REA_PROCESS_WORKING_ROOTS_JSON`, and an
environment allowlist in `REA_PROCESS_ALLOWED_ENV_JSON`. Scenarios use the
owned loopback replay by default; a scenario requesting host networking also
requires `REA_PROCESS_ALLOW_EXTERNAL_NETWORK=true`.
environment allowlist in `REA_PROCESS_ALLOWED_ENV_JSON`. Because the current PTY
adapter uses host networking, it also requires
`REA_PROCESS_ALLOW_EXTERNAL_NETWORK=true`.
If the native PTY backend is unavailable, install Xcode command-line tools and
run `npm run rebuild:native`. Linux source builds require Python, `make`, and a
+1 -1
View File
@@ -42,7 +42,7 @@ export const processScenarioSchema = z
environment: z.record(environmentName, z.string()).default({}),
inherit_environment: z.array(environmentName).max(64).default([]),
secret_aliases: z.array(environmentName).max(64).default([]),
network_access: z.enum(["loopback", "host"]).default("loopback"),
network_access: z.literal("host").default("host"),
filesystem_roots: z.array(z.string().startsWith("/")).max(16).default([]),
events: z
.array(
+1 -19
View File
@@ -72,12 +72,8 @@ describe("process capture domain", () => {
});
it("requires explicit operator approval for host network access", () => {
const scenario = parseProcessScenario({
...base,
network_access: "host",
});
expect(
authorizeProcessScenario(scenario, {
authorizeProcessScenario(parseProcessScenario(base), {
enabled: true,
executableRoots: ["/bin"],
workingRoots: ["/tmp"],
@@ -90,20 +86,6 @@ describe("process capture domain", () => {
});
});
it("allows loopback replay without external network approval", () => {
const scenario = parseProcessScenario(base);
expect(scenario.network_access).toBe("loopback");
expect(
authorizeProcessScenario(scenario, {
enabled: true,
executableRoots: ["/bin"],
workingRoots: ["/tmp"],
allowedEnvironment: [],
allowExternalNetwork: false,
}),
).toEqual({ allowed: true });
});
it("refuses paths and environment outside operator policy", () => {
const scenario = parseProcessScenario({
...base,