security
Technical notes on web development, DevOps, and AI integration.
62 articles
- 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 - 10:53backend
Guard Before the Payload: Requirements Are Global-Write Only
A cross-module document checklist could be rewritten by any account holding a service write permission. The guard now refuses before reading the payload.
TL;DR: Permission gate was too narrow. Added scope check to write path. Guard now runs before validation.
#go#rbac#api - 10:40frontend
Dead Links in the Admin Sidebar: Menus That Always 403 Must Go
An admin audit found two menu entries that always end in 403 and seven items still marked read-only. Both were removed, and the tests now assert the absence.
TL;DR: Audit found dead links in admin sidebar. Nav was not broken, just advertising inaccessible routes. Fix involved hiding links from department accounts.
#rbac#ux#nextjs - 03:20backend
A Guard That Refuses Before the Payload Is Read
The organisation module finally has an owner: one guard in the service layer, one fixed 403, and one sidebar group that follows the owner.
TL;DR: Commit 96e93ae adds a guard function to check write permissions. The function runs before validation and returns an error for unauthorized bidang. A test ensures the guard's position and prevents unauthorized repository access.
#go#rbac#authorization - 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 - 03:56frontend
Four Groups: Navigation Follows Permission, Not Content
The admin sidebar splits into four groups that state permission: your own section for writing, other sections read-only, plus a temporary group.
TL;DR: The admin sidebar was split into four permission-based groups so users can see what they can write to before clicking. The layout is built from one RBAC capability map rather than static lists, keeping read-only sections clearly marked. Server-side authorization still enforces access, and tests confirm the change.
#rbac#nextjs#ux - 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 - 01:54tooling
The Deny Rule That Silently Died After an OpenCode V2 Upgrade
Upgrading the harness killed an old permission config with no error. How I found the dead deny rule and proved it with a denied action attempt.
TL;DR: Frontend subagent ran arbitrary shell commands despite denied permissions. Vocabulary changes in OpenCode V2 caused the issue. Config files required manual updates.
#opencode#coding-agent#agent-rules - 19:30backend
The Status Contract Lives in the Query, Not in a Parameter
Public organization detail now goes through GetActiveByID with the status clause inside the query: a missing row and a non-AKTIF row both answer 404.
TL;DR: Organization 17 is inactive. Public requests return 404. Admin requests return the full record.
#go#mysql#rest-api