Dev.to Security 🔐 Cybersecurity 👁 0 📖 4 min read

Entitlement Is Not Balance: Don't Authorize Google Flow Spend with Arithmetic

Originally published on hexisteme notes. A Google Flow account page said a plan included monthly credits and added daily credits. It was tempting to infer the remaining monthly balance by subtracting the daily amount fr

Originally published on hexisteme notes.

A Google Flow account page said a plan included monthly credits and added daily credits. It was tempting to infer the remaining monthly balance by subtracting the daily amount from a displayed total. That arithmetic looked tidy, but it did not establish a balance, a billing cycle, or which credit pool would be spent next.

The authorization code now treats those as separate facts. An entitlement says what a plan may include. A balance says what remains in a particular pool at a particular time. A priority rule says which pool a provider will debit. None follows from the others. Spend authorization requires evidence for the one it intends to consume.

The observation had a narrow scope

On September 13, a browser UI capture for one account showed text describing 1,000 monthly included credits and 50 daily credits, with daily credits used first. It also showed 50 daily credits remaining. It did not show a current monthly balance or a billing-cycle boundary. The historical observation is useful as an input format and a test fixture; it is not a statement about today's provider policy, this account's current balance, or any other account.

A content hash bound the local receipt to the captured bytes. That confirms the file later used by the code did not change. It does not authenticate the capture's origin or prove a forged capture could not have been created with a matching hash. Provenance and byte integrity are separate properties.

Why subtraction is not authorization

Suppose a UI names a monthly entitlement, shows a daily remainder, and displays an unrelated total. Subtracting one number from another silently assumes the total is a monthly balance, that no past debits were assigned differently, that the cycle is current, and that the provider will consume pools in the assumed order. Each assumption can be false while the arithmetic remains correct.

The code consequently permits daily-only use from a fresh daily balance without inventing a reset instant or a monthly remainder. Monthly use requires a source-specific current remaining balance, a current cycle, and an explicit priority statement from the same capture. Unknown historical debits are reported as unclassified rather than reassigned to make the numbers add up.

Freshness also belongs in the authorization contract. The captured balance was accepted for 15 minutes, then had to be rechecked. That rule does not predict a provider reset schedule. It limits how long the system is willing to act on an observation while external spending can change the account.

Count a reservation exactly once

The other subtle failure is double subtraction. A pending request reserves credits before a provider response arrives. If the same request is then recognized as completed, its reservation must be removed exactly once. If it is uncertain or has a remote job identifier, ordinary retry is blocked and recovery is required.

This is why authorization is more than remaining >= planned. It is a state transition with evidence: fresh observation, durable intent, lock held across the pre-submit recheck, and a unique binding from reservation to spend. Duplicate identifiers, conflicting balances, malformed evidence, stale observations, and insufficient verified funds all stop rather than falling back to a guessed pool.

The scoped test suite recorded 268 passing cases for parsing, freshness, malformed captures, reservation accounting, and legacy behavior. Tests establish that the implementation enforces these rules for the fixtures. They do not refresh the account, create a provider guarantee, or authorize real spending.

Design for a missing balance

The safest useful outcome is often partial knowledge. A verified daily pool can authorize a daily-sized request even if monthly data is absent. A monthly entitlement alone cannot authorize a larger request. A UI total whose allocation is unknown should remain unknown, not be converted into a plausible answer for convenience.

This pattern applies to prepaid APIs, cloud promotional credits, per-day quotas, and corporate allowances. Preserve the evidence source and capture time with every decision. Keep plan terms, available balance, pool order, and local reservations in different fields. When one of them is missing, reduce the authorization scope or stop.

The falsifier is direct: reopen this design if a fresh, source-bound observation can pass while its declared pool balance or priority is wrong; if normal intent reobservation double-counts or drops a reservation; or if unknown historical rows are asserted as actual pool usage. The success condition is not a familiar-looking number. It is a traceable right to spend from a named balance.

Email list for these notes: hexisteme.beehiiv.com — no issue has gone out yet, so you would be on it before the first one. No welcome sequence, no course, no upsell.

More notes at hexisteme.github.io/notes.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.