soulmate
Challenge
Imported from local notes.md.
Solution
Original Notes
soulmate
Challenge Summary
- Given: A web app plus a source archive,
starting_files/soulmate.zip, containing the FastAPI backend, frontend, model wrapper code, and the PCA artifact used for latent controls. - Goal: Make the service classify a generated face as Tom Cruise strongly enough to pass the threshold and return the flag.
- Constraints: The live site only exposes a birthday picker in the UI, but the backend may expose more endpoints.
Initial Recon / Triage
- Observations: The frontend only calls
/generate-randomwith a date-derived seed, but the backend also exposes/healthand a hidden/submit-uendpoint./submit-uaccepts an 8-dimensional control vectoru, returns the Tom Cruise score directly, and leaks the flag immediately when the score crosses the threshold. - File identification:
backend/app.pycontains the live API surface and the flag gate.models/inference.pyexposesTOM_SCORE_THRESHOLD = 0.15and the PCA control dimension.checkpoints/pca_basis_d8_tom_weighted.npzholds the 8-D latent basis and bounds. - Entry points: Query
/healthto obtain control bounds and threshold, then optimize the hidden/submit-uoracle instead of using the birthday UI.
Hypotheses & Approach
- Hypothesis 1: The intended bug is API exposure, not model inversion through the date field. The frontend hides the powerful endpoint, but the backend does not.
- Hypothesis 2: Because the PCA artifact is explicitly Tom-weighted and the service returns
tom_score, a simple black-box search over the 8 bounded controls should be enough to cross the low0.15threshold.
The useful exposed facts were:
GET /healthreturnscontrol_dim = 8, the exact lower/upper bounds for each control, andtom_score_threshold = 0.15.POST /submit-ureturnstom_score,top_predictions, and the flag whentom_score >= 0.15.- The UI path through
/generate-randomis a distraction; direct latent control is much easier.
Execution Steps (Reproducible)
Stage 1
Commands:
cd /root/squ1rrel2026CTF
python3 squ1rrel2026_live_challenges.py --stdout-json | jq '.challenges[] | select(.name=="soulmate")'
cd /root/squ1rrel2026CTF/soulmate/starting_files
unzip -o soulmate.zip -d extracted
python3 - <<'PY'
import requests
print(requests.get('https://soulmate.squ1rrel.dev/health', timeout=20).json())
PY
Results:
- Confirmed the source archive contains the backend, model wrapper, and PCA checkpoint.
- Confirmed the live service exposes
/healthpublicly. - Retrieved:
control_dim = 8- exact
u_lower/u_upperbounds tom_score_threshold = 0.15
Stage 2
Commands:
cd /root/squ1rrel2026CTF/soulmate
python3 artifacts/coordinate_search.py
Results:
- The hidden
POST /submit-uoracle was optimized directly instead of using birthdays. - Simple probes showed the zero vector already gave a nontrivial Tom score around
0.0691, so the threshold was reachable. - Coarse and then fine coordinate ascent over the 8 bounded PCA controls produced the winning vector:
u = [2.0, 2.0, 8.0, -3.0, 1.0, 7.0, -2.0, 0.0]- The accepted response was:
tom_score = 0.15429021418094635threshold = 0.15success = true
The final accepted payload from the service returned:
flag = squ1rrel{7h3_church_c0n6r47ul4735_mr5_cru153!!}
Artifacts Produced
artifacts/probe_remote.py— baseline oracle probes against the live service.artifacts/random_search.py— coarse bounded random search.artifacts/coordinate_search.py— the search that found the winning latent control vector.artifacts/hybrid_search.py— alternate stochastic local search.artifacts/powell_search.py— bounded SciPy optimizer prototype.artifacts/coordinate_best.json— accepted live response, winning vector, and final flag.
Flag
squ1rrel{7h3_church_c0n6r47ul4735_mr5_cru153!!}