#!/usr/bin/env bash # # extract.sh — pre-extract symlink scan + cpmove untar. # # Usage: extract.sh # # Calls scripts/lib/scan-symlinks.php first; if it reports any DANGEROUS # findings we abort BEFORE tar runs (per spec §0 step 2). On clean, # extracts with the same hardening flags CpanelBackupImporter::extractBackup # uses on the panel today (see web-files/libs/CpanelBackupImporter.php). set -euo pipefail TARBALL="${1:?usage: extract.sh }" DEST="${2:?usage: extract.sh }" USERNAME="${3:?usage: extract.sh }" ts() { date -u +'%Y-%m-%dT%H:%M:%SZ'; } log() { printf '[%s] extract: %s\n' "$(ts)" "$*"; } [[ -f "$TARBALL" ]] || { log "tarball not found: $TARBALL"; exit 2; } mkdir -p "$DEST" # --- pre-extract symlink scan --------------------------------------------- log "scanning tarball for dangerous symlinks (cpmove vector check)" SYMLINK_REPORT=$(mktemp -p /tmp scan-symlinks.XXXXXX.json) if ! php /scripts/lib/scan-symlinks.php \ --tarball "$TARBALL" \ --username "$USERNAME" \ --report "$SYMLINK_REPORT"; then log "scan-symlinks.php exited non-zero" cat "$SYMLINK_REPORT" >&2 || true log "ABORT: tarball contains dangerous symlinks; aborting" # Propagate the report on stdout so entrypoint.sh can include it # in the failure record. exit 3 fi log "symlink scan clean (no DANGEROUS findings)" # --- extract -------------------------------------------------------------- # Detect compression. cpmove can be .tar.gz / .tar.bz2 / .tar. TAR_FLAGS="-xf" case "$TARBALL" in *.tar.gz|*.tgz) TAR_FLAGS="-xzf" ;; *.tar.bz2|*.tbz2) TAR_FLAGS="-xjf" ;; *.tar.xz|*.txz) TAR_FLAGS="-xJf" ;; *.tar) TAR_FLAGS="-xf" ;; esac log "extracting with hardened tar flags into $DEST" # Hardening flags (mirrored from CpanelBackupImporter::extractBackup): # --no-same-owner / --no-same-permissions: drop archive-recorded # uid/perm bits so the cpmove can't drop setuid binaries at us. # --no-overwrite-dir: refuse to clobber existing directory metadata, # closing one historical tar-symlink-escape vector. # --absolute-names is NOT used — leading / in a member name is stripped. cd "$DEST" tar --no-same-owner --no-same-permissions --no-overwrite-dir $TAR_FLAGS "$TARBALL" log "extracted OK ($(find "$DEST" -type f | wc -l) files)" exit 0