Skip to Content
Legacy PlatformReferenceSecret Proxying

Secret Proxying

Iron.sh lets you store credentials and have the egress proxy inject them into outbound requests on behalf of your workloads. The workload never sees the real secret. It only sees a placeholder value that is meaningless outside the proxy.

How It Works

When you create a secret, Iron.sh returns a proxy_value, an opaque placeholder string. At sandbox creation time, the platform sets the environment variable you specified (e.g. GITHUB_TOKEN) to this placeholder value inside the VM:

GITHUB_TOKEN=IRONSH_PROXY_github-main

When the workload makes an outbound HTTP request, the egress proxy scans all HTTP headers for known proxy values and replaces them with the real secret before forwarding upstream. There is no per-provider logic — the proxy is generic. The response travels back through the proxy unmodified.

┌──────────┐ ┌────────────┐ ┌──────────────┐ │ Sandbox │──req──▶ │ Egress │──req──▶ │ Provider │ │ │ │ Proxy │ │ (upstream) │ │ uses │ │ │ │ │ │ placeholder │ swaps in │ │ sees real │ │ value │◀──res── │ real secret│◀──res── │ credential │ └──────────┘ └────────────┘ └──────────────┘

This means:

  • The workload code and process environment never contain the actual credential.
  • Even if the sandbox is compromised, the attacker only obtains the placeholder, which cannot be used outside the Iron.sh proxy.
  • The real secret is only held by the proxy and is never written to disk inside the VM.
  • Every secret replacement is recorded in the egress audit log, so you have a full trail of when and where credentials were injected.

Host Scoping

By default, secrets are injected on requests to any host allowed by your egress policy (hosts: ["*"]). To restrict a secret to specific destinations, provide a hosts array when creating the secret. Supported formats:

PatternExampleMatches
Exact hostnameapi.github.comOnly api.github.com
Wildcard (one level)*.github.comapi.github.com, raw.github.com
Any host*All hosts allowed by egress policy

If a request goes to a host not in the secret’s hosts list, the proxy value is left as-is and the upstream receives a meaningless placeholder.

Proxy Value Format

The proxy_value returned when you create a secret follows the pattern:

IRONSH_PROXY_<name>

For example, a secret named github-main produces:

IRONSH_PROXY_github-main

This value is safe to log, commit, or expose in CI output. It is inert outside the Iron.sh egress proxy.

Environment Variable Injection

When a sandbox starts, Iron.sh sets one environment variable per secret. The variable name is the env_var you specified when creating the secret, and its value is the proxy_value:

# Inside the sandbox echo $GITHUB_TOKEN # IRONSH_PROXY_github-main

Your workload uses the environment variable normally. Standard tools and libraries (e.g. git, npm, curl) read the token from the environment and include it in outbound requests. The proxy handles the rest.

If you update or add secrets while a sandbox is already running, existing shell sessions will not pick up the changes automatically. To reload secrets in an active shell, source the secrets profile:

source /etc/profile.d/irons-secrets.sh

Alternatively, start a new login shell. New SSH sessions will load the updated secrets automatically.

Example: GitHub Token

  1. Create a secret via the API or CLI:
curl -X POST https://api.iron.sh/v1/secrets \ -H "Authorization: Bearer $IRONS_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "github-main", "secret": "ghp_abc123def456...", "env_var": "GITHUB_TOKEN", "hosts": ["api.github.com", "github.com", "*.githubusercontent.com"] }'
  1. Create a sandbox. The VM starts with GITHUB_TOKEN=IRONSH_PROXY_github-main in its environment.

  2. Inside the sandbox, clone a private repo:

git clone https://github.com/my-org/private-repo.git

Git reads GITHUB_TOKEN from the environment and sends it in the Authorization header. The egress proxy intercepts the request to github.com, replaces the placeholder with ghp_abc123def456..., and forwards it upstream. GitHub authenticates the request normally.

Secret Lifecycle

  • Write-only. The real secret value is never returned by any API endpoint. Once stored, it can only be replaced or deleted.
  • Update. Use PATCH /v1/secrets/{secret_id} to rotate a secret. The proxy_value does not change, so running sandboxes continue to work without reconfiguration.
  • Delete. Use DELETE /v1/secrets/{secret_id} to remove a secret. Sandboxes created after deletion will no longer have the environment variable set.

Interaction with Egress Rules

Secret proxying works alongside egress rules. For the proxy to intercept and inject a secret, the destination host must be allowed by your egress policy. If a request to a host is blocked by an egress rule, the proxy never sees it, and injection does not occur.

Make sure the hosts your secrets target are included in your egress allowlist.

Security Model

PropertyGuarantee
Secret at restEncrypted. Never stored on the VM’s file system.
Secret in transitInjected over TLS between the proxy and the provider. Never sent in plaintext.
Sandbox exposureOnly the placeholder is visible inside the VM.
Placeholder outside proxyInert. Cannot be exchanged for the real secret without the proxy.
Audit trailEvery secret replacement is recorded in the egress audit log, including the target host, protocol, and timestamp.
Last updated on