security
Technical notes on web development, DevOps, and AI integration.
54 articles
- 21:12frontend
YouTube Dead in Production: The Referer the Player Needed
The YouTube iframe worked locally and died on deploy: a same-origin Referrer-Policy stripped the referer the player needs, fixed per element.
TL;DR: YouTube iframes were broken. The issue was caused by a Referrer-Policy header. Adding a referrerPolicy attribute to each iframe fixed it.
#youtube#iframe#http - 09:14backend
Three Layers of Validation for One Query Parameter
An enum filter guarded at the handler, the repository, and the SQL layer. Each layer protects a different class of caller.
TL;DR: Editor logic was embedded in a SQL query. The query was simplified to use a column directly. A three-layer validation system was added for security.
#golang#api#sql - 13:02backend
The edit form one bidang should never have opened
Role checks answer who may manage staff, never which row they may touch. A row-ownership guard closes the gap.
TL;DR: Someone edited a staff record from a different bidang. The issue was caused by a lack of object-level authorization. A guard function was added to prevent this.
#security#authorization#owasp - 11:47backend
The Only Admin Module Without a Write Guard
An authorization audit found seven of eight admin modules guarded. The last one closed by reusing the pattern already in the codebase.
TL;DR: The KotaPortal service portal project had an admin module without a scope check. The fix reused a guard pattern from neighboring modules. The handler now passes middleware into the service with a two-function guard.
#go#security#rbac - 02:39testing
One Admin Account per Scope, Then RBAC Checks Prove Something
Manual permission checks stalled because no admin account matched the scope. A closed CLI creates one per scope and proves it with a real login.
TL;DR: Authorization testing needs the right privilege. Admin accounts are created per bidang. The create-bidang-users command has three guards.
#testing#security#go - 19:14backend
Open Routes, Guarded Routes: Where the Permission Seed Goes
Admin routes return 403 for every role except superadmin because the permission rows were never seeded. The guard is only the enforcer.
TL;DR: Admin accounts got 403 errors due to missing permission rows. The permission middleware checked and denied access. Adding permission rows fixed the issue.
#go#security#mysql - 22:12backend
Throttling a Public Feedback Endpoint: Two Buckets and One Cap
A public feedback endpoint needs defenses on two axes: a body size cap before JSON decoding and two per-account rate limit buckets mounted after authentication.
TL;DR: A security review flagged a feedback endpoint accepting unlimited payload sizes and submission frequency. Fixes: cap the body at 32 KiB before JSON decoding, mount two per-user rate limit buckets (one per 10 minutes, five per day) after auth middleware, and return 429 with Retry-After. Also normalize nil query results to empty arrays so clients get the promised JSON contract.
#go#security#rate-limit - 19:06security
The Masked Public Roster: Ship Names, Not Phone Numbers
Hiding sensitive columns in the UI is not protection. The real mask lives in the API layer, proven by negative E2E assertions.
TL;DR: The article describes a common flaw where the UI hides sensitive fields but the API still sends full records to the client, violating OWASP API3:2023 and Indonesia's data minimization rules. The fix strips fields server-side via a projection DTO containing only public data. A Playwright test enforces negative assertions, ensuring PII never reaches the DOM.
#privacy#security#playwright - 23:02devops
Closing the Door Does Not Hide the Drawers
The deploy port was closed, yet /.git/ stayed readable through the staging hostname. Next: an nginx edge regex guard and an api/db network split.
TL;DR: Closing the inbound port didn't protect a staging server still serving .git and .env files over its tunnel. The fix needs three layers: nginx edge rules denying dot-paths, server_tokens off, and explicit Docker networks isolating services. Each layer covers what the others miss; any one alone leaves the same exposed drawers.
#nginx#docker#devops