The Varnish management CLI (varnishadm, the -T flag, default port 6082) is not a monitoring endpoint. It is a full administrative control plane. Through it, an authenticated user can load arbitrary VCL, inject bans, change every runtime parameter, and stop the cache child process. If VCL inline-C is enabled, loading a VCL is code execution on the Varnish host, running as the cache child user.
When -T is bound to 0.0.0.0 or a public IP, any network actor who can reach the port and authenticate gets total control of the service. The authentication mechanism is a shared-secret (pre-shared key) handshake over a plaintext TCP connection. It provides authentication but not encryption. If the secret file is missing, readable by unauthorized users, or authentication is disabled, the CLI is either unauthenticated or trivially compromisable.
What this means
The management process (varnishd root process) listens on two classes of sockets: the data-plane HTTP listener (default :6081) and the management CLI listener (default :6082, or a random localhost port). The CLI listener is the -T argument to varnishd. It speaks a line-oriented ASCII protocol authenticated by a challenge-response using a shared secret file specified by -S.
flowchart TD
A["varnishd startup"] --> B{"-T flag value?"}
B -->|"localhost:PORT or omitted"| C["CLI bound to loopback only"]
B -->|"0.0.0.0:6082 or public IP"| D["CLI exposed to network"]
B -->|"none"| E["CLI disabled entirely"]
C --> F{"-S secret configured?"}
D --> F
F -->|"valid secret file"| G["Authenticated but plaintext"]
F -->|"none or missing"| H["No authentication at all"]
G --> I["Attacker needs secret file access"]
H --> J["Any network actor has full control"]
I --> K["Full VCL load, ban, param.set, stop"]
J --> K
K --> L["If inline-C enabled: arbitrary code execution"]The commands available through the CLI include vcl.load, vcl.use, ban, param.set, backend.set_health, start, and stop. The stop command terminates the cache child process. A vcl.load with a crafted VCL can rewrite the entire request pipeline, exfiltrate request data to an attacker-controlled backend, or, if vcc_feature allow_inline_c is set, execute arbitrary C code within the child process.
The exposure is a configuration problem, not a software vulnerability. The Varnish process is doing exactly what it was told to do: listen on the specified address and accept authenticated CLI commands. The risk is that the specified address is reachable by parties who should not have administrative control.
Common causes
| Cause | What it looks like | First thing to check |
|---|---|---|
-T 0.0.0.0:6082 in startup args | ss -tlnp shows varnishd listening on all interfaces for the management port | ps aux | grep varnishd | grep -oP '\-T\s+\S+' |
| Authentication disabled | CLI connects without any secret challenge | Check startup args for missing -S or explicit disable |
| Secret file world-readable | -S /path/to/secret exists with broad read permissions | ls -la on the secret file path |
| Container or pod with host networking | Management port reachable from outside the container network | Inspect pod spec or docker run flags for --network host |
Reverse CLI mode (-M) | varnishd connects outbound to a management facility | Check startup args for -M |
| Load balancer or NAT forwarding port 6082 | External traffic reaches the CLI port through infrastructure | Audit firewall, security group, and LB rules for port 6082 |
Quick checks
Run these read-only checks to assess exposure. None of them modify Varnish state.
# Check the management interface bind address from the running process
ps aux | grep varnishd | grep -oP '\-T\s+\S+'
# Check what varnishd is listening on (look for port 6082 or the -T port)
ss -tlnp | grep varnishd
# Check active connections to the management port (replace 6082 with your -T port)
ss -tnp | grep 6082
# Check the -S shared-secret file path and permissions
ps aux | grep varnishd | grep -oP '\-S\s+\S+'
# Check for recent CLI activity in the Varnish log
varnishlog -g session -q 'CLI'
# Check whether syslog CLI logging is enabled
varnishadm param.show syslog_cli_traffic
# Check whether inline-C is enabled in VCL (code execution risk)
varnishadm param.show vcc_feature
If the -T grep shows localhost:6082 or 127.0.0.1:6082, the interface is loopback-only. If it shows 0.0.0.0:6082, *:6082, or a routable IP, the interface is exposed.
Active connections to port 6082 from IPs outside your management infrastructure or jump hosts warrant immediate investigation.
How to diagnose it
Identify the bind address. Extract the
-Tvalue from the running process. If it contains0.0.0.0,::, or a public IP, the interface is network-exposed.Identify the authentication state. Extract the
-Svalue. If-Sis absent entirely, authentication is disabled. If-Spoints to a file, check its permissions withls -la. The secret file should be readable only by root or the management user.Check who is listening and who is connected. Run
ss -tlnp | grep varnishdto confirm the actual listen address, since the process args may differ from systemd unit defaults. Runss -tnp | grep <port>to see active CLI sessions.Audit CLI activity. Run
varnishlog -g session -q 'CLI'to see recent CLI commands. Ifsyslog_cli_trafficis enabled (check withvarnishadm param.show syslog_cli_traffic), review syslog for persistent command history. Look for VCL loads, ban operations, or parameter changes you did not initiate.Check for inline-C exposure. Run
varnishadm param.show vcc_feature. Ifallow_inline_cis enabled, any VCL loaded via the CLI can contain arbitrary C code. This elevates a CLI compromise from service control to full code execution on the host.Review infrastructure forwarding. Check firewall rules, security groups, load balancer configs, and NAT rules for anything that forwards traffic to port 6082. A correctly bound
-T localhost:6082is still exposed if a load balancer or port-forwarding rule maps external traffic to that port.Check the systemd unit or init script. The running process args may differ from the configured startup. Inspect the unit file with
systemctl cat varnishon systemd systems. Some distribution packages override the default bind address.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
| Management port listener address | Confirms whether the CLI is bound to a routable interface | ss -tlnp shows varnishd on 0.0.0.0:6082 or a public IP |
| Active connections to port 6082 | Detects unauthorized CLI sessions | Connections from IPs outside management infrastructure |
CLI log entries (varnishlog -q 'CLI') | Records administrative commands issued to the daemon | VCL loads, bans, or param changes at unexpected times |
syslog_cli_traffic parameter | Enables persistent CLI command logging to syslog | Disabled when it should be enabled for audit trail |
| Ban/purge rate anomalies | Unauthorized CLI access often starts with cache invalidation | MAIN.bans_added or MAIN.n_purges spiking beyond baseline |
| Secret file permissions | If the shared secret is readable, authentication is bypassable | -S file readable by non-root users |
vcc_feature allow_inline_c | If enabled, CLI access enables code execution, not just config control | Parameter set to on in production |
Fixes
Rebind the management interface to localhost
The safest fix is to bind -T to localhost. Edit the systemd unit or startup configuration:
# Inspect the current systemd unit
systemctl cat varnish
Change the -T argument from 0.0.0.0:6082 (or the public IP) to localhost:6082. To disable the CLI entirely, omit -T or use -T none if supported by your version. This is appropriate for nodes managed purely through configuration management.
After changing the unit file, reload and restart:
systemctl daemon-reload
systemctl restart varnish
Warning: This restarts the management process and the cache child. The cache is lost on restart, so expect a cold-cache warmup period. Schedule this during a maintenance window or ensure sufficient backend capacity for the warmup spike.
Protect the shared-secret file
If you must keep the CLI enabled for operational tooling, orchestration, or debugging, ensure the -S file is protected:
# Check current permissions on the secret file
ls -la /etc/varnish/secret
# Restrict to root only
chmod 600 /etc/varnish/secret
chown root:root /etc/varnish/secret
If the secret file has been exposed (committed to version control, shared broadly, or world-readable), rotate it. Generate a new secret, place it in the file with 600 permissions, and restart the management process. Any automation or operators using varnishadm will need the updated secret.
Never disable authentication
Missing or disabled authentication means any network actor who can reach the -T port gets full administrative control with no challenge. If you find authentication disabled in production, treat it as a security incident: rotate secrets, audit CLI logs for unauthorized access, and fix the configuration immediately.
Disable inline-C in production
If vcc_feature allow_inline_c is enabled, disable it unless you have a specific, audited reason for using inline-C in VCL. With inline-C disabled (the default since Varnish 4), a VCL load cannot execute arbitrary code, limiting a CLI compromise to service disruption and configuration manipulation rather than host-level code execution.
# Check current state
varnishadm param.show vcc_feature
# Disable inline-C (if currently enabled)
<!-- TODO: verify exact param.set syntax for vcc_feature flags across versions -->
varnishadm param.set vcc_feature +no_inline_c
Restrict network access at the firewall layer
Even with -T localhost:6082, add a defense-in-depth firewall rule that drops traffic to port 6082 from non-localhost sources. This catches cases where the bind address changes accidentally or a container networking mode exposes the port.
# Example iptables rule (IPv4 only): drop all non-loopback traffic to port 6082
# Use -I to insert at the top of the chain; -A may not match if an earlier rule accepts
iptables -I INPUT -p tcp --dport 6082 ! -s 127.0.0.1 -j DROP
Adjust for your firewall management tool (nftables, firewalld, cloud security groups).
Prevention
- Audit
-Ton every deploy. Include a check in your deployment pipeline that verifies the management interface bind address. Fail the deploy if-Tis set to a routable address. - Enable
syslog_cli_traffic. This parameter logs all CLI commands to syslog, providing a persistent audit trail of administrative activity. - Monitor connections to port 6082. Alert on any connection to the management port from non-localhost, non-management-infrastructure IPs.
- Rotate the secret file periodically. Treat the
-Sfile like any other privileged credential. Rotate on staff turnover and after any suspected exposure. - Review reverse CLI mode (
-M). If using-Mfor centralized management, verify the outbound connection target and ensure the management facility is secured. The-Mconnection carries the same CLI capabilities and uses the same-Sauthentication. - Document the CLI as a privileged interface. Ensure operators understand that
varnishadmis not a read-only tool. It can stop the service, rewrite the entire request pipeline, and (if inline-C is enabled) execute code.
How Netdata helps
- Process and network monitoring. Netdata collects per-process metrics and network connection data, which can surface unexpected connections to the management port. Correlating new connections on port 6082 with process-level changes helps detect unauthorized CLI sessions.
- Ban and purge rate tracking. Netdata monitors
MAIN.bans_addedand related ban counters. A spike in ban activity that does not correlate with a known deployment or CMS publish event may indicate unauthorized CLI access. - Child process stability. Netdata tracks
MGT.child_panic,MGT.child_died, andMGT.child_start. A CLIstopcommand or a malicious VCL load that crashes the child shows up immediately as a child restart event. Correlating child restarts with CLI log entries helps distinguish operational restarts from attack-driven ones. - VCL state changes. Netdata monitors
MAIN.n_vcl,MAIN.n_vcl_avail, andMAIN.n_vcl_discard. An unexpected increase in loaded VCLs can indicate avcl.loadfrom an unauthorized CLI session. - Hit rate correlation. A sudden hit-rate collapse combined with elevated
MAIN.bans_addedis consistent with either a botched deployment or an attacker injecting bans via the CLI. Netdata’s per-second granularity and anomaly detection help distinguish between the two by showing the exact timing and pattern of the change.
Related guides
- Varnish Error 503 Backend fetch failed: what the error page actually means
- Varnish backend_fail, backend_unhealthy, and backend_busy: three different backend problems
- Varnish backend connection reuse low: keepalive not working and slow TTFB
- Varnish backend probe configuration: threshold, window, interval, and initial
- Varnish backend is sick: health probes, all-backends-sick, and grace
- Varnish backend TTFB high: the leading indicator of thread pool death
- Varnish ban list growing: O(n) lookups and the lurker falling behind
- Varnish ban lurker not keeping up: contention and ban_lurker_sleep
- Varnish cache hit ratio dropped: hit rate collapse and backend overload
- Varnish cache stampede: a popular object expires and the herd hits the backend
- Varnish child panic: Child died signal, core dumps, and the crash loop
- Varnish ESI errors: broken pages and workspace pressure from Edge Side Includes






