Home

A simple place for my collected thoughts and notes.

Welcome! I'm Sam Stelfox, a security engineer and operations leader with a long-standing habit of taking things apart to see how they work. The best of my time belongs to my wife Hannah, our daughter Zelda, and our pup Cookie, with whatever is left going to tinkering with compilers, knowledge graphs, genetic algorithms, and whatever else catches my attention.

I use this site to keep notes on things I'm digging into, write the occasional blog post, and track whatever projects I'm tinkering with. If you want to know more, there's an about page with contact info.

API Security Hardening

Sam Stelfox 2 min read

This security pass wouldn't have been possible without first cleaning up the pedantic lint issues and expanding test coverage. Auth was optional, password hashing was SHA-256, and the GCRA rate limiter had a bug where it never actually rejected requests, this one I stumbled upon by accident while writing end-to-end tests. The nested Result<Result<_, NegativeOutcome>, InsufficientCapacity> return was only being checked at the outer level so every request that should have been limited was getting waved through. Not ideal.

Auth is mandatory now but the first-time user experience isn't great. You get a 503 on everything until you use hive security set-password on the server side to manually create a user. Query parameter tokens were previously being used and have since entirely been removed. Putting credentials in query params is a very easy way to get live credentials in logs, referrer headers, and browser history. Password hashing moved to Argon2id, SHA-256 is not acceptable for user credentials. There's now a real user system backed by the database with per-user API keys (hive_ prefixed so they're easy to spot if they leak). CLI persistent authentication similar to other tools like the AWS CLI, and first class support for remote servers both in the config and via a --host flag.