---
title: 'Tunnel Security Model: SSH, Dedicated VMs, Credentials'
description: 'How TestingBot Tunnel secures local testing: SSH-encrypted channel,
  dedicated ephemeral VMs, credential best practices.'
source_url:
  html: https://testingbot.com/support/tunnel/security
  md: https://testingbot.com/support/tunnel/security.md
---

# Built for production traffic

Every tunnel session runs inside its own ephemeral virtual machine, all traffic is encrypted in transit, and credentials never have to appear on the command line.

- SSH encrypted 
- Dedicated VM 
- Ephemeral 
- MIT licensed 

## Encrypted channel

The tunnel opens a single outbound SSH connection from your machine to a TestingBot edge endpoint. All test traffic (HTTP, HTTPS, WebSocket, SSE) is multiplexed over that SSH connection.

Inbound ports on your network are not required. The tunnel only initiates outbound connections to ports **443** (HTTPS) and **22** (SSH) on `*.testingbot.com`.

## Pinning the tunnel server's host key

The tunnel's control connection is SSH, and your account secret is its password. Whatever answers on the tunnel port receives it, so the tunnel can verify the server's SSH host key before it sends anything.

```bash
java -jar testingbot-tunnel.jar --ssh-host-key SHA256:xxxx... --ssh-host-key-policy require
```

- `--ssh-host-key` pins the SHA-256 fingerprint the server must present, in the form `ssh-keygen -lf <key> -E sha256` prints. Repeat it, or comma-separate several, where the server may present more than one key. MD5 fingerprints are refused.
- Where the TestingBot API has a fingerprint for your tunnel server, it sends it over its authenticated HTTPS connection and the tunnel checks it. A pin you give outranks it.
- With neither, the tunnel connects anyway and logs a warning on every connect, which is what 4.x tunnels did. `--ssh-host-key-policy require` refuses to connect instead.
- `--doctor` reports which of these cases applies before anything connects.

## Local listeners bind loopback

The Selenium relay, local proxy, metrics port and `--web` server do not authenticate. Since 5.0 they listen on `127.0.0.1` only.

That matters because the Selenium relay attaches your TestingBot key and secret to everything it forwards, and the local proxy will connect anywhere your machine can. If tests run on another machine, set `--bind-address 0.0.0.0` and restrict the ports with a firewall. See [upgrading](https://testingbot.com/support/tunnel/upgrading#bind).

## Limiting what the tunnel can reach

A tunnel can reach whatever the machine running it can reach. On a CI runner or jump host, narrow that to what your tests need.

```bash
java -jar testingbot-tunnel.jar --allow-hosts 'staging.example.com,*.internal.example' --localhost-policy deny
```

Both are enforced on plain HTTP, `CONNECT` and WebSocket upgrades. The localhost check is applied to the address actually dialled, so a DNS answer pointing at `127.0.0.1` cannot get around it. See [traffic rules](https://testingbot.com/support/tunnel/traffic-rules).

## Dedicated VM lifecycle

Every tunnel session provisions a dedicated virtual machine in the TestingBot cloud. The VM exists only for the lifetime of your tunnel.

01

Provision

A fresh VM is allocated when your tunnel starts.

02

Use

Only your account (or your team if `--shared`) can route traffic.

03

Teardown

The VM is destroyed when the tunnel shuts down. No state persists.

VMs are not reused between accounts. There is no cross-tenant traffic on the tunnel VM.

## Certificates and SSL bumping

By default, the tunnel performs SSL interception (also called SSL bumping) for outbound HTTPS so that the cloud browser can validate certificates seamlessly. The TestingBot CA used for bumping is preinstalled on every cloud VM and device.

For apps that pin certificates, you have two options:

Trust the TB CA

[Download the certificate](https://testingbot.com/downloads/testingbot-ssl-bumping.crt) and add it to your app's trust store.

Disable bumping

Start the tunnel with `--nobump` and HTTPS is forwarded transparently with no decryption.

## Credential handling

Your TestingBot key and secret authenticate the tunnel against the TestingBot grid. Treat them like passwords.

The tunnel accepts credentials from three sources, in order of precedence:

1. Positional arguments on the command line.
2. Environment variables: `TESTINGBOT_KEY` and `TESTINGBOT_SECRET`.
3. A `.testingbot` file in your `$HOME` directory.

For CI pipelines and shared machines, prefer the environment-variable approach so credentials never appear in shell history, process lists or build logs. See the [CLI reference](https://testingbot.com/support/tunnel/commandline#env) for the full list.

## Credentials stay out of logs

Tunnel logs end up in CI artifacts and support tickets, so credentials are redacted before anything is written.

- Credential-bearing headers such as `Authorization`, `Proxy-Authorization` and cookies.
- The `user:password@` part of URLs and credential-shaped query values.
- Capabilities logged with `--log-http forwarder:body`, by key name.
- Upstream proxy credentials are only ever sent to the proxy they were issued for, never to a proxy named by a PAC file. See [authentication](https://testingbot.com/support/tunnel/authentication#scoping).

## Metrics endpoint

The tunnel exposes a Prometheus-compatible metrics endpoint on port 8003 by default. The endpoint is unauthenticated unless you set `--metrics-auth user:password` (or `TESTINGBOT_METRICS_AUTH`).

Since 5.0 the endpoint binds `127.0.0.1` by default. If you set `--bind-address 0.0.0.0`, enable metrics auth and restrict the port with a firewall rule. The `/healthz` and `/readyz` endpoints are not behind metrics auth, and disclose only up or down. See the [monitoring guide](https://testingbot.com/support/tunnel/monitoring).

## Data residency

Test traffic flowing through the tunnel is routed via TestingBot edge endpoints in the EU. No traffic is stored after the tunnel ends. For specific data-residency or compliance information, please see the [TestingBot trust center](https://trust.testingbot.com).

## Looking for more help?

Have questions or need more information? Reach out via email or Slack.

[Email us](https://testingbot.com/contact/new) [Join our Slack](https://join.slack.com/t/testingb0t/shared_invite/zt-3bcw9xch-jk19~6XPs_xBrsAgAedkCw)
