zwesty
Write-ups / Day 11 / Warmups
Day 11 · Sun, Oct 11 · Warmups

Safe Travels

Prey slaughtered

Layered decoding (Base64url, plus the whole earlier decoder chain), per-line decoding, debugging a false positive

STTMClaude Homebase Both

Flags are shortened to their first 8 and last 4 characters because they're unique per team.

Challenge ID
warmups-day-11 (+ /time_trial, /mastery)
Solved
2026-10-11, all three modes; 14 min 19 s from first start to last CORRECT (09:00:06–09:14:25 ET)
Player
Zwesty (solo), with Claude Code (Opus 5.5); the first two modes by our automated morning solver (a scheduled script on our Kali VM), unattended

The challenge

Our usual base went on a URL-friendly vacation.

One question per set, message: "Decode the assigned blob completely. What exact answer slug does its final non-empty decoded line instruct you to submit?" Format: three lowercase words and a two-digit number, joined by hyphens.

Reading the prompt: what it said we'd need

Clue What it pointed to What I did about it
"Our usual base" Base64, the warmups' running theme Nothing new needed
"URL-friendly" Base64url (- and _ instead of + and /, often unpadded) Already one of Day 1's decoders, so the newest solver handled it with no change

Safety

Text puzzles only; nothing to run. Decoded on our Kali VM.

What was in the files

  • Single Solve / Time Trial: one small blob.txt (147 and 144 bytes): the instruction sentence in Base64url.
  • Mastery: a zip of 53 blobs, each one sentence cut into 11 numbered pieces with a different encoding per piece: Base64, ROT13, hex, space-separated binary, decimal, octal, percent-encoding, HTML entities, \u escapes, Base32, and unpadded Base64url. Joined in number order they read "Nice work decoding this warmup! To solve, submit this exact answer to the Game Master: groovy-raven-maple-48". The answer's first word is often split across two pieces.

Single Solve and Time Trial: solved by the morning solver

This was the first day the morning solver handled Warmups on its own (added the night before, after an offline replay showed the solver never answered wrongly on earlier days). It used the newest Warmups solver, from Day 10.

Single Solve   start 333  artifact 396  solve 0  submit 606  TOTAL 1336 ms   CORRECT c3cadf38…9c6d
               vs started_at: start +77, artifact +473, ready +473, submit +1079 ms
Time Trial     10 s clock: start 487  artifact 344  solve 0  submit 626  TOTAL 1457 ms   CORRECT 15153d32…7a43
               vs started_at: start +192, artifact +536, ready +536, submit +1162 ms

Mastery: one wrong submit, a one-line fix, then CORRECT

09:00:11, INCORRECT. The solver returned well-formed slugs for all 53 sets, but 5 were truncated: ve-pillow-juniper-94 instead of brave-pillow-juniper-94 (also quick-…, handy-…, hearty-…, brave-…).

Why: for each piece the solver tries a few candidate decodings and accepts the first combination whose joined text "looks like the instruction". In those 5 sets it kept the \u escapes piece undecoded, and the joined text still contained "submit … answer" and a slug-shaped tail right after the raw piece's closing quote. The check that rejects leftover encoding in Day 2's shared decoder knew percent-codes and HTML entities but had never been taught the backslash escapes when Day 9 added them.

Fix: one line, adding \uXXXX / \UXXXXXXXX / \xNN to that leftover-encoding check. Checked before resending: - all 31 saved Warmups sets from Days 2–10 give exactly the same answers as before; - all 53 sets from the failed attempt now come out complete; - tests added (a residue test in Day 2's suite, the full blob 50 in Day 10's, since it needs every later decoder).

09:14:25, CORRECT on a fresh variant (a retry, sent 30 s after another lane's Single Solve to stay clear of the rate limit):

started_at 2026-10-11T13:14:24.095Z  deadline 2026-10-11T13:14:32.095Z  answer_ids ['set1.message', … 'set53.message']
  mode mastery  ranked  unique_attempts_remaining 254
  artifact warmups-day-11-mastery.zip 27581 bytes (checked)
  retry 878  artifact 298  solve 68  submit 701  TOTAL 1945 ms
  vs started_at: retry +128, artifact +426, solve +494, ready +494, submit +1195 ms
result CORRECT  flag a6f1605a…a886

Time to solve

The morning solver started the Single Solve at 13:00:06 UTC and had the Single Solve and Time Trial CORRECT by 13:00:09, each on the first submit. The Mastery's first submit was incorrect (5 of 53 slugs truncated); after the one-line fix, the ranked retry went CORRECT at 13:14:25, 14 min 19 s after the first start.

Takeaways

  • Every new decoder needs its leftovers added to the "not fully decoded" check. Two days after Day 9 added escapes, their absence let a slug-shaped word tail through.
  • The format check alone can't catch a truncated slug that still has three words and a number. A plausible-looking answer isn't proof.
  • Replay every saved set after a shared-decoder change. 31 sets in under a minute is what made the fix safe to send.