Railway Sandbox Security Review for Untrusted Learner Code Execution
Anonymous
FREEOP

6 days ago

Hi Railway team,

We are evaluating Railway Sandbox for a multi-tenant programming education platform where untrusted learner code would execute in isolated environments. Before using it, we need confirmation on the following security controls:

  1. Can outbound networking be fully disabled per Sandbox, including public internet, DNS, Railway private networking, project services, Postgres/Redis, localhost-equivalent endpoints, and metadata endpoints?
  2. What guest/host isolation boundary is guaranteed? Do separate Sandboxes share a kernel?
  3. Are project/environment/service variables inherited automatically by Sandbox.create(), or can we guarantee an empty environment except explicitly supplied values?
  4. What provider-enforced limits exist for CPU, memory/OOM, process/thread count, disk/workspace, stdout/stderr, and execution duration?
  5. Is there a provider-enforced maximum Sandbox lifetime or TTL that still terminates the VM if the controller crashes or loses connectivity?
  6. What is the minimum API-token scope required to create/execute/destroy Sandboxes? Is there a sandbox-only scoped credential?
  7. What happens to a Sandbox if the controller crashes, SDK call fails, or network connectivity is lost? Is automatic cleanup guaranteed?
  8. What concurrency/rate limits apply to Sandbox creation and execution?
  9. Are Railway Sandboxes officially supported for hostile/untrusted multi-tenant code execution in production, and what production availability/SLA or regional guarantees apply?

We specifically need technical guarantees rather than application-level workarounds because learner code is treated as hostile.

I would appreciate confirmation from a Railway team member, as these answers will be used for a production security architecture decision.

Awaiting User Response

3 Replies

Railway
BOT

6 days ago

Outbound internet can't be disabled. Every sandbox has outbound internet access through a NAT gateway. The default ISOLATED mode blocks private networking in both directions, so a sandbox can't reach your environment's services, Postgres or Redis, and they can't reach it. Each sandbox is a separate, fully isolated Linux VM.

Nothing is inherited from the project. A sandbox only gets the variables you pass in env, and forks don't inherit them either.

Size is fixed at creation, and on Trial that's 2 vCPU / 2 GB. timeoutSec kills a command at a deadline. Output that runs too long is truncated, and the result reports truncated.

A sandbox outlives the process that created it. If the controller disappears, Railway destroys the sandbox once its idle timeout expires, which is 1 to 5 minutes on Trial. Teardown waits while an exec command is still running, so a command that never exits keeps its sandbox alive. On Hobby and Pro the idle timeout can be turned off, and then nothing destroys the sandbox until you call destroy.

Concurrency is capped per environment: 10 sandboxes on Trial, 50 on Hobby, 100 on Pro. Creating a sandbox past the cap fails with an error.

Details are in the Sandboxes docs.


Status changed to Awaiting User Response Railway • 6 days ago


Railway

Outbound internet can't be disabled. Every sandbox has outbound internet access through a NAT gateway. The default `ISOLATED` mode blocks private networking in both directions, so a sandbox can't reach your environment's services, Postgres or Redis, and they can't reach it. Each sandbox is a separate, fully isolated Linux VM. Nothing is inherited from the project. A sandbox only gets the variables you pass in `env`, and forks don't inherit them either. Size is fixed at creation, and on Trial that's 2 vCPU / 2 GB. `timeoutSec` kills a command at a deadline. Output that runs too long is truncated, and the result reports `truncated`. A sandbox outlives the process that created it. If the controller disappears, Railway destroys the sandbox once its idle timeout expires, which is 1 to 5 minutes on Trial. Teardown waits while an `exec` command is still running, so a command that never exits keeps its sandbox alive. On Hobby and Pro the idle timeout can be turned off, and then nothing destroys the sandbox until you call destroy. Concurrency is capped per environment: 10 sandboxes on Trial, 50 on Hobby, 100 on Pro. Creating a sandbox past the cap fails with an error. Details are in the [Sandboxes docs](https://docs.railway.com/sandboxes).

Anonymous
FREEOP

6 days ago

Thanks. This is very helpful.

The statement that outbound internet cannot be disabled is important for our threat model, because our learner code is treated as hostile and our required security baseline is deny-all networking by default.

Before we rule out Railway Sandbox for this execution tier, could a Railway engineer please confirm the following:

  1. Is there any supported or undocumented mechanism—firewall, egress policy, network namespace policy, or otherwise—to completely disable public internet/DNS egress for an individual Sandbox?
  2. Are there provider-enforced limits for process/thread count, disk/workspace size, and generated file size, in addition to CPU/memory and command timeout?
  3. What is the minimum API token scope required to create, execute in, and destroy Sandboxes? Is there a sandbox-only scoped credential?
  4. Are Railway Sandboxes officially intended/supported for multi-tenant hostile/untrusted code execution in production?
  5. What production availability/SLA or reliability guarantees apply?
  6. Is there any provider-supported architecture for keeping private/hidden tests unreadable by learner code running inside the same Sandbox VM, or should private evaluation be performed outside the learner VM?

If outbound internet truly cannot be disabled, please confirm that explicitly so we can make a final architecture decision.

We need a human/engineering confirmation because this response will determine our production security architecture.


Status changed to Awaiting Railway Response Railway • 6 days ago


6 days ago

To confirm explicitly: outbound internet can't be disabled for a sandbox. Every sandbox has outbound internet access through a NAT gateway. The only network setting is isolation mode, which controls private networking. There is no supported egress firewall, allowlist, or deny-all option.

Beyond the VM size set at creation (2 vCPU / 2 GB on Trial) and the optional per-command timeoutSec, we don't publish process/thread, disk/workspace, or output-size limits for sandboxes.

The SDK authenticates with an API token (RAILWAY_API_TOKEN) plus a target environment ID. Our documentation doesn't describe a sandbox-only scoped credential.

Sandboxes are currently in beta, and breaking changes to the API and behavior may happen. We don't recommend building a production system on them, and we have no timeline for them leaving beta. Trial, Hobby and Pro plans don't include an SLA.

There is also no built-in way to hide hidden tests from learner code running in the same sandbox VM.

Taken together, a deny-all networking baseline for hostile code isn't something sandboxes meet today.


Status changed to Awaiting User Response brody • 6 days ago


Welcome!

Sign in to your Railway account to join the conversation.

Loading...