Daily Log — 2026-06-30: phantom 405s, scary variable names, and automating this post
An experiment: a daily, public log of what I worked on — stripped down to the parts that are actually transferable. No customer names, no internal ticket numbers, just the engineering lessons that survive being taken out of context.
Today had three things worth writing down.
1. The phantom GET / → 405 behind a cloud load balancer
A service was emitting a steady stream of 405 / "Unsupported method GET: url: /" — tens of
errors per second, millions per day. Enough to drown real signal and trip alerting.
The trap here is that the 405 is correct. The port in question only registers / for
POST, so a GET / should return 405. The bug isn't the handler — it's that something
keeps sending GET /.
The usual suspects were innocent:
- Pod liveness/readiness probes pointed at
GET :8080/health, not/. - A
tcpdumpon the app container's port showed no obvious external HTTP.
What ties it together: the service is a LoadBalancer exposing many ports, and the cloud
LB's health probe defaults to GET / against every exposed port. The kubelet probes and
the LB probes are two different things hitting two different places.
Debugging checklist I'd reuse:
- Decide whether the 405 is by design before chasing the caller. If
/isPOST-only, aGET /405 is a symptom, not the disease. - Separate kubelet probes (pod-level, you control the path) from load-balancer health
probes (often default to
/, configured outside your manifests). - Capture on all interfaces at the node/pod namespace, not just the app container. TLS ports will prove the connection but hide method/path — you still need LB/access logs for that.
- Enumerate every exposed port. A
LoadBalancerthat publishes 9 ports is 9 probe targets.
Fixes, cheapest first:
- Point the LB health check at a real health path (
GET /health, HTTPS if the port is TLS). - Stop exposing ports the LB doesn't need.
- Use a TCP health check instead of HTTP for ports that don't speak plain HTTP
GET.
And a logging lesson for whoever owns the service: a WrongMethod/405 log line that doesn't
include source IP, user-agent, host, and path forces everyone downstream into gdb and
eBPF to answer "who sent this?". Log the caller.
2. A scary variable name is not a vulnerability
I hit a variable named EventTypesToSkipAuthorization. That suffix sets off alarms — and it
should make you look — but a name is not an exploit. The methodology I used to clear it:
- Find every use. It was consumed in exactly one place: an allowlist check that skipped a
per-item RBAC check for a single event type (
request-access). - Read the comment + the intent. Requiring an RBAC pass to request access to something you don't have access to is a contradiction — that's the whole point of "request access".
- Walk the full handler chain. Authentication still ran first; only item-level authorization was skipped. Skipping authZ ≠ skipping authN.
- Check the blast radius. Objects were resolved strictly within the caller's own account; creating the event granted nothing (an admin still had to approve); it was feature-gated and rate-limited.
- Name the residual risk honestly. The only real edge was same-account name enumeration — inherent to the feature, low severity — not an auth bypass.
Verdict: safe by design. The fix worth suggesting was cosmetic — rename it to something like
eventTypesExemptFromItemRBAC so the next person doesn't have to repeat this trace.
Takeaway: trace, don't trust the name — in either direction. Alarming names can be fine; boring names can hide real bugs.
3. Automating this very post with the Cursor Agent SDK
The meta part. I spent some time with the Cursor Agent SDK and community ports, then had the agent build the pipeline that produces this log:
- A Cursor skill that knows my data sources (shell history, agent transcripts, browser
history, GitHub activity,
git logacross my dev dirs). - A gather script that collects a day's activity into one place.
- A split into two posts — a private one with the real names and numbers, and this public one with only the transferable bits.
- A cron-friendly wrapper so it runs on a schedule instead of on a whim.
If this keeps working, the entries will keep coming. If it doesn't, this will be a lonely little category in the tag list — which is its own kind of honest signal.