Research CommonsResearch Commons
gpu-train/Security

Security

The gpu-train security model — loopback bind, bearer-token auth, dashboard obfuscation, the local credential store, and cost safety.

gpu-train is a single-user, local control plane. It assumes it runs on a machine you trust and talks outbound to providers, W&B, and artifact sinks.

Network exposure

  • The dashboard/API server (gpu-train serve) binds to 127.0.0.1 by default.
  • It rejects any request whose Host header isn't loopback (anti-DNS-rebinding).
  • CORS is restricted to loopback origins; WebSocket upgrades validate Host and Origin.

Because the server can submit and cancel jobs, an unauthenticated, internet-exposed instance would be a remote-code-execution and cost risk. The loopback defaults plus a bearer token prevent this. For remote access, put it behind an authenticating reverse proxy or an SSH tunnel and set GPU_TRAIN_ALLOWED_HOSTS to the proxy host.

Bearer-token auth (default on)

gpu-train serve generates a token, persists it to ~/.gpu-train/server_token (chmod 600), prints it, and opens the browser at /#token=…. The dashboard stores it and sends Authorization: Bearer <token> on every API call; the checkpoint download link and the log WebSocket accept a ?token= query param (headers aren't possible there). The static shell, /health, and /api stay open so the login gate can load. Token comparison is constant-time.

gpu-train serve                         # generate + print a token, require it
gpu-train serve --token my-secret       # bring your own (or GPU_TRAIN_SERVER_TOKEN=…)
gpu-train serve --no-auth               # open, loopback-only (old behavior)

Dashboard obfuscation

Release builds run javascript-obfuscator over the dashboard's Next.js app/shared chunks (conservative settings: hex identifiers, base64 string-array, string splitting; runtime chunks skipped so React keeps working). CI asserts there are no source maps, no cleartext control-plane identifiers, and a minimum count of obfuscated identifiers, plus a serve smoke test. The Python SDK ships as readable source — only the shipped UI bundle is obfuscated.

Secrets

  • Credentials are referenced via secret_ref URIs (env://, file://, store://) and resolved at runtime. The package never logs secret values.
  • Keys entered in the dashboard are written to ~/.gpu-train/credentials.json (chmod 600), returned masked (last 4 chars), and read back only by the control plane via store://. This includes S3 (secret_access_key) and GCS (service_account_json) sink credentials.
  • Secrets injected into remote training (e.g. WANDB_API_KEY, HF_TOKEN) are written to owner-only files on the rented box, and known values are redacted from stored/streamed logs.
  • Environment variables win: a credential configured via env:// is read-only in the UI.

See Credentials & secrets for the resolvers and store schema.

Cost safety

  • Instances are terminated on job completion/failure, idle timeout, kill_all(), control-plane exit (atexit), and server shutdown.
  • On startup the control plane reconciles and terminates instances orphaned by a prior crash.

See Cost safety for the guardrails, and the repository's SECURITY.md for the canonical model.