Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions github-actions/previews/upload-artifacts-to-firebase/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,34 @@ runs:
- name: Extracting workflow artifact into Firebase public directory.
shell: bash
run: |
set -euo pipefail

extractDir="$RUNNER_TEMP/artifact-unpack"
publicDir='${{inputs.firebase-public-dir}}'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Interpolating ${{ inputs.firebase-public-dir }} directly into the shell script is vulnerable to shell injection if the input contains single quotes (e.g., path'with'quotes). Although this input is marked as TRUSTED in this repository, it is a security best practice in GitHub Actions to pass inputs via environment variables to avoid them being interpreted as part of the script body.


mkdir -p '${{inputs.firebase-public-dir}}'
mkdir -p "$publicDir"
mkdir -p "$extractDir"

unzip unsafe-artifact.zip -d "$extractDir"
tar -xvzf "$extractDir/deploy-artifact.tar.gz" -C '${{inputs.firebase-public-dir}}'
tar -xvzf "$extractDir/deploy-artifact.tar.gz" -C "$publicDir"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

Consider removing the -v (verbose) flag from the tar command. Since the artifact is PR-supplied and potentially malicious, a filename containing a newline followed by a GitHub Actions workflow command (e.g., \n::error ...) could be interpreted by the runner when printed to stdout during extraction.

        tar -xzf "$extractDir/deploy-artifact.tar.gz" -C "$publicDir"


# Defense-in-depth: fail the deploy if the extracted artifact contains
# symlinks. The artifact is attacker-influenced (PR-supplied build
# output); a symlink such as `public/leak -> /proc/self/environ` or
# `public/leak -> ~/.config/gcloud/application_default_credentials.json`
# would otherwise be followed by downstream tooling that walks
# `firebase-public-dir` and reads each entry, ending up on the
# public Firebase Hosting CDN. There is no legitimate reason for a
# `public` artifact destined for static hosting to contain
# symlinks, so refusing them outright is the safest default.
# See https://securitylab.github.com/research/github-actions-preventing-pwn-requests/.
symlinks=$(find "$publicDir" -type l 2>/dev/null || true)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The || true and 2>/dev/null suffixes make this security check "fail-open". If the find command fails for any reason (e.g., due to permission errors on directories created by the untrusted artifact), the symlinks variable will be empty, and the check will silently pass. \n\nSince set -e is active, removing || true ensures the workflow fails if the check cannot be completed. Removing 2>/dev/null ensures that any errors encountered during the scan are visible in the logs for debugging.

        symlinks=$(find "$publicDir" -type l)

if [ -n "$symlinks" ]; then
echo "::error title=Symlinks rejected in artifact::The deploy artifact contains symlinks, which are not permitted in a Hosting public directory for security reasons (a symlink can leak the contents of files outside the source tree onto the public Firebase Hosting CDN)."
echo "Symlinks found:"
echo "$symlinks"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

When printing the list of found symlinks, it is safer to indent the output. This prevents a malicious filename containing a newline from being interpreted as a GitHub Actions workflow command if it happens to start at the beginning of a line. Using printf is also safer than echo for printing arbitrary strings.

          printf '%s\n' "$symlinks" | sed 's/^/  /'

exit 1
fi

- name: Extracting artifact metadata
id: artifact-info
Expand Down
Loading