ROYALFIRE

security · 2026

Black-box security assessment

An authorised penetration test of my own hosting dashboard, written up honestly — including the finding that mattered most.

Role
Tester and author of the report
Status
active
Stack
Burp-style manual probingOAuth2HMAC session analysisNode.jsExpress

You cannot claim a system is secure without having tried to break it yourself. So I tested my own dashboard the way an attacker would, under strict read-only rules: no destructive actions, no writes against production data, no load generation.

What was tested

Endpoint discovery across the full API surface, route-bypass probing including trailing-slash and encoded-slash variants, header injection including X-Original-URL and X-Rewrite-URL, session tampering, offline brute force of the session signing secret against roughly a hundred common secrets, CORS policy probing, XSS reflection checks, and source review of the shipped JavaScript bundle.

What held

More than I expected. Every session-tampering variant returned 401. The session secret survived offline guessing. Thirty-plus API endpoints refused unauthenticated access. CORS honoured an exact-origin whitelist rather than reflecting subdomains or suffixes. No .env, .git, source map, or stack trace leaked. Route normalisation tricks were all blocked. The security headers were already correct.

What did not

Eight findings, VJ-01 through VJ-08. The critical one was a placeholder test account left in the production root-access list: a Discord snowflake that is obviously not a real account, sitting in a list that grants full root privileges. Had that ID ever matched a real user, they would have had complete control simply by logging in. The high-severity finding was a missing OAuth2 state parameter — login CSRF, which lets an attacker silently sign a victim into the attacker’s account and then harvest whatever credentials the victim types next.

The rest were medium and low: no CSRF tokens across 37 state-changing endpoints, an in-memory session store that invalidates every session on restart, a CORS handler returning 500 instead of a clean refusal, and an error page leaking on an invalid OAuth code.

The report includes remediation for each finding with the effort estimated, in the order I would actually fix them. The first one took five minutes.

What I would change

I would test authorisation with a real non-admin session from the start. The one finding I could not close is role enforcement on admin APIs, precisely because I had no second account to probe with. Self-assessments have a structural blind spot at exactly the point where a second pair of eyes matters, and the honest fix is to have someone else run that pass.