Security implementation / Go
AuthRace
Authorization and concurrent-write abuse testing
I built a loopback-only Go HTTP regression harness that demonstrates broken object-level authorization and concurrent replay, then proves the corresponding enforcement paths reject cross-tenant writes and apply a logical mutation once.
What I was trying to prove
In an API review, successful authentication is not evidence of object authorization. Concurrent retries also expose bugs that one-at-a-time tests never trigger. I wanted a reproducible attack-and-fix comparison, not a screenshot of a scanner report.
Synthetic verified principal → tenant authorization → atomic operation ledger → local mutation.
- 01 · Untrusted request
Caller + HTTP request
Fixture principal + tenant and operation
- 02 · Authorization
Tenant scope gate
Request tenant must equal principal
- 03 · Concurrency boundary
Atomic idempotency
Principal-bound operation + fingerprint
- 04 · Commit
Local side effect
Once per logical operation
Failure path: Cross-tenant request → 403. Replayed operation → no second mutation. Same operation ID, different payload → 409.
Enforcement: The reference uses an in-process mutex. A distributed payment system would need transactional storage and reconciliation.
Architecture of the implemented reference system, not a production deployment diagram.
Implementation decisions
- Built an in-process HTTP service with deliberately vulnerable and hardened implementations sharing a typed request contract.
- Reproduced a tenant-scope violation caused by trusting request-body ownership rather than a verified principal.
- Applied a tenant-bound operation key and payload fingerprint under an atomic mutex-protected decision and mutation.
- Drove 24 concurrent identical HTTP mutations against both implementations to show duplicate side effects versus single-application behavior.
- Covered malformed requests, authorization rejection, cross-tenant paths, concurrent replay, idempotency key reuse and conflicting payloads with Go tests.
Adversarial paths and trust boundaries
- An authenticated caller supplies a target tenant they do not own. The vulnerable fixture accepts it; the protected handler rejects before mutation.
- Simultaneous identical operations arrive after a timeout or request duplication. The vulnerable fixture commits repeatedly, while the repaired handler records a single logical operation.
- An attacker changes the payload while reusing a valid operation ID. The protected handler raises a fingerprint conflict rather than reinterpreting the ID.
Test evidence
- go test -race ./... and go vet ./...: passed on Apple Silicon.
- go run ./cmd/auth-race: 24 concurrent requests produced 120 units of side effects in the vulnerable fixture and 5 in the hardened fixture.
- All requests target a temporary local httptest server. No external scanning or live payment operations.
Same 24 concurrent requests. Different outcome.
The local fixture sends 24 copies of one logical 5-unit operation. The intentionally vulnerable version applies all 24; the patched version applies it once.
Synthetic local test values, not financial transactions or production service measurements.
Implementation and test method →
Reproduce locally
cd examples/auth-race-lab go test -race ./... go vet ./... go run ./cmd/auth-race
Run against fixtures or binaries you own or are authorized to inspect. The complete working project remains in my private site repository; the published downloads provide reviewable source and tests, not a public GitHub repository.
What I am not claiming
- Identity is a synthetic verified-principal fixture, not a real OAuth/JWT verifier.
- Atomicity is process-local; production requires durable transactional storage, unique constraints and outbox reconciliation.
- It tests modeled API behavior, not authorization for arbitrary third-party systems.
