Concept demo

Sample / fictional data throughout. This is a concept demo of a heli-ski / heli-charter operations platform — not a certified or currently-in-use operational safety system, and not affiliated with or representing any specific real operator. Every aircraft, person, and guest shown is invented for demonstration.

CLEARSPAR
← Blog
2026-07-07

The Permission Bug That Let Anyone Clear a Helicopter Back Into Service

Clearspar Heli is a concept prototype of a day-of-operations system for a heli-ski/heli-charter operation — not a real operator, not real flights, not real guests. Every aircraft and person in the demo is invented sample data. But the engineering problems that come up when you build something safety-adjacent are real, and this is the first in a series of posts about bugs that actually shipped and got fixed during the build.

The MEL/squawk board is where aircraft discrepancies get logged, deferred under MEL (minimum equipment list), and resolved. “Resolving a squawk” is the action that marks a helicopter airworthy again after a maintenance issue has been fixed, returning it to dispatchable status. That's a consequential action by design — it's the difference between an aircraft every other part of the app treats as grounded and one it treats as clear to fly.

It shipped with no role check on it at all. Any authenticated staff account — including a field guide's — could call the resolve-squawk endpoint and clear an aircraft back into service. The adjacent action, deferring a discrepancy under MEL, was correctly gated to the ops_manager role. Resolving one wasn't gated to anything.

This wasn't caught by a feature checklist. It came out of a systematic pass through an already-live app looking specifically for actively-misleading behavior — cases where the app tells you something is true when it isn't — rather than just missing functionality. “Any staff account can silently clear a grounded aircraft” fits that category exactly: it doesn't throw an error, doesn't look broken, it just quietly lets the wrong person do something they shouldn't be able to.

The fix was to gate the resolve action to ops_manager, matching the permission level already used for defer-under-MEL. That wasn't an arbitrary choice. The two actions are comparable in consequence — one takes an aircraft out of service, the other puts it back — and the app's RBAC doesn't have a separate “mechanic” role to reach for. Reusing the existing manager gate was the minimal fix that matched the authority structure already encoded in the app, rather than inventing a new role for a permission question the app already had a correct answer to sitting right next to it.

Verification didn't stop at “looks right in a local dev environment.” After deploying, I re-ran the exact same exploit against the live production API: called the resolve-squawk endpoint with a field-guide credential and got a real 403 Forbidden. Called it again with a manager credential and got a real 200, with the resolution correctly attributed to that manager's name. Same request, same environment the bug had actually lived in, opposite outcomes for the two roles that mattered.

The underlying lesson isn't really about squawks specifically. The app also ships a documented role x capability permission matrix as a reference for exactly this kind of thing — and that matrix is only as good as the enforcement behind every single mutating action, including the ones that don't get much attention because they're one click on a board full of other clicks. A “resolve” button sitting next to a correctly-gated “defer” button looks equally trustworthy from the UI. Finding that one of them was never checking who was asking took deliberately going looking for the gap, not just moving on to the next feature.

That's story one. A later post covers the multi-tenant data isolation story — a recurring “fails closed, but also fails invisible” bug class tied to Postgres row-level security.