← The Blog

What TryHackMe's Top 6% actually taught me as a developer

29 June 2026 3 min readSecurity

Why a developer bothers with security labs

I started TryHackMe out of curiosity and kept going because it kept changing how I write ordinary code. Working through the analyst, engineering, and penetration testing paths put me in the global top 6%, but the ranking is not the useful part. Spending hours attacking deliberately broken applications rewires how you build working ones.

Three habits came directly out of the labs.

1. I stopped trusting anything the client sends

Every developer knows client-side validation is not security. Knowing it and internalising it are different things, and the gap closes the first time you bypass a form yourself.

Once you have edited a disabled field in devtools, replayed a request with a modified value, and watched a server accept it without complaint, “the frontend already checks that” stops feeling like a reason.

What changed in practice: validation in the browser is for the user’s benefit, giving fast, friendly feedback. Validation on the server is for the application’s safety. They are two separate jobs and I write both.

2. Error messages are an information leak

In labs, a surprising amount of early progress comes from reading what the application volunteers. A stack trace naming a framework version. A login that says “user not found” for one address and “incorrect password” for another, quietly confirming which accounts exist. A verbose database error revealing column names.

None of these are vulnerabilities on their own. All of them are a map.

Now I write errors for two audiences: the user gets a clear, actionable message, and the log gets the detail. The user does not need my stack trace, and neither does anyone else reading over their shoulder.

Recon is mostly reading. The less your application says about itself, the less there is to read.

3. Defaults are a security decision

A large share of lab wins come from things nobody chose: a default credential, an admin panel left reachable, directory listing enabled, a permissive header nobody set deliberately.

The pattern is that no one decided to be insecure. They just did not decide anything, and the default decided for them.

So when I set something up now I try to ask what this does out of the box, and whether that is what I actually want. It is a small question that catches a category of problem you cannot find by reading your own code, because the problem is not in your code.

The ethics part, which is not optional

Everything above was learned inside authorised lab environments built for exactly that purpose. Scope first, permission always. The same curiosity that makes someone good at this is the thing that gets them in trouble if they aim it at systems they were not invited into.

Where this leaves me

I am not a security engineer, and I am careful not to claim otherwise. I am a developer who has spent enough time on the other side to build with a little more suspicion, which mostly shows up as: validate on the server, say less in errors, and read the defaults.

You can verify my progress on my TryHackMe profile.

Comments

Comments run on GitHub Discussions through giscus, so there is no database here and no account details for me to hold.

To switch it on: make the repo public, enable Discussions, install the giscus app, then set giscus.repo in src/lib/site.ts. Until then this page makes no third-party request.