landjail: npm/npx fails with EACCES when installing packages at runtime (works with nsjail)
- Dominant language
- Go
- Stars
- 25
- Forks
- 7
- PR merge metrics
- No merged PRs in 30d
Description
Full disclosure, below is result of conversation with Coder blink. Testing was performed by me.
## Summary
When using `jail_type: landjail`, npm/npx operations that occur at runtime inside the boundary jail (e.g., MCP tool installation via Codex) fail with `EACCES` errors. The same configuration works correctly with `jail_type: nsjail`.
## Environment
- Codex module: 4.3.0
- Codex CLI: 0.114.0
- Node: v24.13.0
- npm: 11.6.2
- Kernel: Linux 6.12.73
- Boundary jail_type: landjail
## Root Cause Analysis
The two jail types use fundamentally different approaches to route traffic through the boundary proxy:
### nsjail (transparent interception)
- Creates a separate network namespace with a veth pair
- Uses iptables `PREROUTING REDIRECT` to transparently capture **all TCP traffic** and redirect it to the proxy port
- Processes inside the jail do not need to be proxy-aware — any direct TCP connection (port 80, 443, etc.) is intercepted automatically
- `HTTP_PROXY`/`HTTPS_PROXY` env vars are **not set** (not needed)
### landjail (env-var-based proxy)
- Uses Landlock V4 to restrict `connect()` syscalls — the child process can **only** connect to the proxy port (default 8080)
- Sets `HTTP_PROXY`, `HTTPS_PROXY`, `http_proxy`, `https_proxy` env vars pointing to `http://localhost:`
- Processes **must** respect these proxy env vars to make network requests
- Any process that attempts a direct TCP connection to a port other than the proxy port gets `EACCES`
## Problem
When Codex launches MCP servers that use `npx` to auto-install npm packages (e.g., `npx -y @zereight/mcp-gitlab`), the npm fetch layer attempts direct HTTPS connections to `registry.npmjs.org:443` instead of routing through the proxy. Landlock blocks these connections, resulting in:
```
http fetch GET https://registry.npmjs.org/@zereight%2fmcp-gitlab attempt 1 failed with EACCES
http fetch GET https://registry.npmjs.org/@zereight%2fmcp-gitlab attempt 2 failed with EACCES
http fetch GET https://registry.npmjs.org/@zereight%2fmcp-gitlab attempt 3 failed with EACCES
error code EACCES
error errno EACCES
error FetchError: request to https://registry.npmjs.org/@zereight%2fmcp-gitlab failed, reason:
The operation was rejected by your operating system.
```
This suggests that npm/npx is not respecting the `HTTP_PROXY`/`HTTPS_PROXY` environment variables when spawned as a subprocess inside the boundary jail. Possible causes:
1. Codex's MCP server `env` configuration block may replace the process environment (stripping the proxy vars set by boundary) rather than merging with it
2. npx may spawn sub-shells or child processes that don't inherit the proxy env vars
3. npm's `minipass-fetch` may bypass proxy settings in certain execution paths
## What was tested
The following workarounds were attempted and **did not resolve** the issue:
- Setting `npm config set proxy http://localhost:8080` and `npm config set https-proxy http://localhost:8080`
- Explicitly setting `HTTP_PROXY` and `HTTPS_PROXY` env vars in the MCP server configuration
- `npm install -g @zereight/mcp-gitlab` (failed due to permission issues)
The following **did work** as a workaround:
- Pre-installing the package locally (`npm install @zereight/mcp-gitlab`) outside of the boundary jail before Codex starts, so the package is already on disk when the MCP server is launched
## Expected Behavior
landjail should handle npm/npx network requests the same way nsjail does — either by ensuring proxy env vars are reliably propagated to all child processes, or by providing an alternative transparent interception mechanism.
## Suggested Improvements
1. Investigate why npm/npx ignores proxy env vars when spawned inside landjail and whether boundary can enforce proxy settings more reliably (e.g., via npm config files or additional env var propagation)
2. Document the known limitation that landjail relies on proxy env var compliance, which may not work for all tools
3. Consider whether landjail could use a supplementary mechanism (e.g., LD_PRELOAD-based connect() interception) to transparently route traffic for proxy-unaware tools
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.