Building the CTF Arena Into This Portfolio
The CTF Arena on this site is a static Nuxt app with no backend — which raises an obvious problem: if there's no server to check answers against, how do you avoid shipping the flag in the JavaScript bundle where anyone can just read it out of view-source?
The answer is to never store the flag itself — only its SHA-256 digest. When someone submits an answer, it gets hashed client-side with the Web Crypto API and compared against the stored digest. The plaintext flag only ever exists transiently in the browser's memory during that comparison, and only the player who solves it correctly ever sees it in plain text (and only because they typed it in themselves).
The one exception is deliberate: a 'view source' style challenge, where the mechanic *is* finding a flag hidden in an HTML comment. That's not a leak — the whole point of that challenge is literally digging through the rendered page source.
For scalability, every challenge is just an object in an array — id, category, difficulty, points, a brief, a task description, a hint, and a hash. Adding a new challenge later means writing the flag, hashing it, and pushing one object onto the list. No new components, no new routes.
This writeup relates to View Source in the CTF Arena. Try it yourself →
More Writeups
Breaking Down "Signal Intercept": A Base64 Primer
Why Base64 isn't encryption, how to recognize it in the wild, and the reasoning behind one of the CTF Arena challenges.
What It Took to Hold #1 on TryHackMe for 4 Months
A practical breakdown of the routine behind a 4-month monthly leaderboard streak — less about talent, more about consistency.