#!/usr/bin/env bash set -euo pipefail NETWORK=${NETWORK:-cve-2025-27407-net} GITLAB_CONTAINER=${GITLAB_CONTAINER:-cve-27407-gitlab} LEGACY_EVIL_CONTAINER=${LEGACY_EVIL_CONTAINER:-cve-27407-evil} GITLAB_IMAGE=${GITLAB_IMAGE:-docker.io/gitlab/gitlab-ce:16.11.8-ce.0} GITLAB_HTTP_PORT=${GITLAB_HTTP_PORT:-8080} GITLAB_SSH_PORT=${GITLAB_SSH_PORT:-2224} GITLAB_ROOT_PASSWORD=${GITLAB_ROOT_PASSWORD:-Cve27407Password!} MARKER=${MARKER:-/tmp/cve_2025_27407_gitlab_marker} TIMEOUT_SECONDS=${TIMEOUT_SECONDS:-1200} usage() { cat < Commands: start Start the vulnerable GitLab container wait Wait for GitLab/Rails and enable lab settings up Run start, then wait verify Poll for MARKER inside the GitLab container cleanup Remove lab containers/network help Show this help Common environment overrides: GITLAB_HTTP_PORT=${GITLAB_HTTP_PORT} GITLAB_SSH_PORT=${GITLAB_SSH_PORT} GITLAB_ROOT_PASSWORD=${GITLAB_ROOT_PASSWORD} MARKER=${MARKER} EOF } start_lab() { podman network exists "$NETWORK" || podman network create "$NETWORK" >/dev/null podman rm -f "$GITLAB_CONTAINER" >/dev/null 2>&1 || true podman run -d \ --name "$GITLAB_CONTAINER" \ --hostname gitlab.local \ --network "$NETWORK" \ --shm-size 256m \ -p "$GITLAB_HTTP_PORT:$GITLAB_HTTP_PORT" \ -p "$GITLAB_SSH_PORT:22" \ -e GITLAB_OMNIBUS_CONFIG="external_url 'http://127.0.0.1:${GITLAB_HTTP_PORT}'; nginx['listen_addresses'] = ['0.0.0.0']; gitlab_rails['initial_root_password'] = '${GITLAB_ROOT_PASSWORD}'; gitlab_rails['gitlab_shell_ssh_port'] = ${GITLAB_SSH_PORT}; puma['worker_processes'] = 1; sidekiq['concurrency'] = 2; prometheus_monitoring['enable'] = false;" \ "$GITLAB_IMAGE" >/dev/null cat </dev/null 2>&1; do if (( SECONDS > deadline )); then echo "[-] Timed out waiting for GitLab HTTP" >&2 podman logs --tail 120 "$GITLAB_CONTAINER" >&2 || true exit 1 fi sleep 10 done echo "[*] Waiting for gitlab-rails runner" until podman exec "$GITLAB_CONTAINER" gitlab-rails runner 'puts "rails-ready"' 2>/dev/null | grep -q rails-ready; do if (( SECONDS > deadline )); then echo "[-] Timed out waiting for Rails" >&2 podman logs --tail 120 "$GITLAB_CONTAINER" >&2 || true exit 1 fi sleep 10 done echo "[*] Enabling Direct Transfer and local lab callbacks" podman exec "$GITLAB_CONTAINER" gitlab-rails runner ' settings = ApplicationSetting.current settings.update!(bulk_import_enabled: true, allow_local_requests_from_web_hooks_and_services: true) puts({ bulk_import_enabled: settings.bulk_import_enabled?, allow_local_requests: settings.allow_local_requests_from_web_hooks_and_services? }.inspect) ' echo "[+] GitLab is ready" } verify_marker() { echo "[*] GitLab marker path: $MARKER" for _ in $(seq 1 60); do if podman exec "$GITLAB_CONTAINER" test -f "$MARKER"; then break fi sleep 1 done if podman exec "$GITLAB_CONTAINER" test -f "$MARKER"; then echo "[+] vulnerable: marker file exists inside GitLab container" podman exec "$GITLAB_CONTAINER" ls -l "$MARKER" else echo "[-] marker not found inside GitLab container" exit 1 fi } cleanup_lab() { podman rm -f "$GITLAB_CONTAINER" "$LEGACY_EVIL_CONTAINER" >/dev/null 2>&1 || true podman network rm "$NETWORK" >/dev/null 2>&1 || true echo "[+] Cleaned lab containers/network" } command=${1:-help} case "$command" in start) start_lab ;; wait) wait_ready ;; up) start_lab wait_ready ;; verify) verify_marker ;; cleanup) cleanup_lab ;; help|-h|--help) usage ;; *) usage >&2 exit 1 ;; esac