Skip to content

RSSHub's `docker-test-cont.yml` workflow is vulnerable to Artifact Poisoning which may lead to a full repository takeover.

Critical
DIYgod published GHSA-9mqc-fm24-h8cw Sep 26, 2024

Package

No package listed

Affected versions

< 64e00e7

Patched versions

64e00e7

Description

Artifact Poisoning in docker-test-cont.yml workflow. (GHSL-2024-178)

The docker-test-cont.yml workflow gets triggered when the PR - Docker build test workflow completes successfully:

on:
  workflow_run:
    workflows: [PR - Docker build test] # open, reopen, synchronized, edited included
    types: [completed]

It then collects some information about the Pull Request that triggered the triggering workflow and set some labels depending on the PR body and sender. If the PR also contains a routes markdown block, it will set the TEST_CONTINUE environment variable to true.

The workflow then downloads and extracts an artifact uploaded by the triggering workflow which is expected to contain a single rsshub.tar.zst file. However, this is not validates and the contents are extracted in the root of the workspace overriding any existing files:

- name: Fetch Docker image
  if: (env.TEST_CONTINUE)
  uses: dawidd6/action-download-artifact@v6
  with:
    workflow: ${{ github.event.workflow_run.workflow_id }}
    run_id: ${{ github.event.workflow_run.id }}
    name: docker-image

After a few steps, the workflow installs the pnpm dependencies with:

- name: Install dependencies (pnpm) # require js-beautify
  if: (env.TEST_CONTINUE)
  run: pnpm i

Since the contents of the artifact have not been validated, it is possible for a malicious actor to send a Pull Request which uploads, not just the rsshub.tar.zst compressed docker image, but also a malicious package.json file with a script to run arbitrary code in the context of the privileged workflow.

PoC

  • Clone the repository
  • Modify docker-test.yml workflow. Keep the original content but perform the following modifications:
    • Add the following step before the upload artifact step:
- name: Test Docker image
  run: bash scripts/docker/test-docker.sh

- name: Export Docker image
  run: |
    mkdir payload
    cd payload
    docker save rsshub:latest | zstdmt -o rsshub.tar.zst
    cat <<EOF > package.json
    ADD HERE THE CONTENTS OF THE ORIGINAL PACKAGE.JSON (ommitted for clarity) AND ADD A NEW PREINSTALL SCRIPT:
        `"preinstall": "echo COMPROMISED",`
    EOF

- name: Upload Docker image
  uses: actions/upload-artifact@v4
  with:
    name: docker-image
    path: payload
    retention-days: 1
  • Create a Pull Request and add a valid routes comment in the body of the Pull Request
  • Watch the execution of the vulnerable workflow log and look for the word COMPROMISED in it.

Impact

The workflow runs with full-write privieges which may allow a malicious actor to take over the Repository:

  Actions: write
  Attestations: write
  Checks: write
  Contents: write
  Deployments: write
  Discussions: write
  Issues: write
  Metadata: read
  Packages: write
  Pages: write
  PullRequests: write
  RepositoryProjects: write
  SecurityEvents: write
  Statuses: write

Remediation

Extract the artifact to a temporary directory and validate its contents.

Resources

Disclosure Policy

This report is subject to a 90-day disclosure deadline, as described in more detail in our coordinated disclosure policy.

Severity

Critical

CVE ID

CVE-2024-47179

Weaknesses

No CWEs

Credits