Hardening pass

Reading the money path first

A small commerce platform was days from taking real payments. I reviewed the trust boundaries before the features and found an order that could mark itself paid.

Payment, webhook and administrative boundaries reviewed before anything else
Money path firstPayment, webhook and administrative boundaries reviewed before anything else
What was knowingly not fixed, with reasons and cost
Deferred listWhat was knowingly not fixed, with reasons and cost
Mis-committed asset removed from repository history
164 MBMis-committed asset removed from repository history

The client

A small direct-to-consumer commerce platform in the EU — payments, an administrative area, file uploads and a messaging bot — built quickly by a small team and approaching launch without a security review.

The engagement

A short review-and-harden pass ordered by trust boundary, closing with a written deferral list.

The problem

A commerce platform with payments, an administrative area, file uploads and a messaging bot was approaching launch without anyone having looked at it as an attacker would. The failure mode here is not a dramatic breach — it is a quiet one: orders marked as paid that were not, a webhook anyone can call, an administrative page that is hidden rather than protected.

What I did

I read the money path before anything else, because that is where a small platform loses real value rather than reputation. The order-completion route trusted its caller instead of verifying the payment provider's event; the incoming webhook had no shared secret; the administrative area relied on the interface not linking to it; and rate limiting was held in process memory on a runtime that discards process memory. Those were fixed first, followed by idempotency on payment events so a retried notification cannot double-apply, then the ordinary hygiene. Everything I chose not to fix was written down with the reason and the cost of doing it later — an undocumented deferral is indistinguishable from an oversight when someone reviews the system in six months.

What was built

A hardening pass ordered by trust boundary rather than by feature: provider-verified payment completion, a shared secret on the incoming webhook, a real server-side guard on the administrative area, durable rate limiting, idempotent payment events, then the ordinary hygiene of indexes, caching, error reporting and continuous integration.

On the table at the end

  • Fixes across the payment, webhook and administrative boundaries
  • Documented deferral list with reasons and effort estimates

What it changed

Closed a payment-verification hole before the platform took live money, made repeated payment notifications safe, and left an explicit record of what was deliberately deferred and what it would cost to close later.

How it ran

  1. 01

    Follow the money

    Trace the path from checkout to an order being marked as paid, and check what the system trusts at each hop.

  2. 02

    Close the trust boundaries

    Verify the provider's event rather than the caller's word, add a shared secret to the webhook, put a real server-side guard on the admin area.

  3. 03

    Make retries safe

    Idempotency on payment notifications and durable rate limiting, since a serverless runtime forgets what it held in memory.

  4. 04

    Ordinary hygiene

    Indexes, caching, error reporting wired into the build, continuous integration, and a large mis-committed asset removed from history.

  5. 05

    Write down what you did not do

    Row-level security, content security policy and migration baselining documented as deliberate deferrals with reasons and effort.

Something similar on your plate?

Thirty minutes, no deck. I will tell you whether it is worth doing at all.