DEV Community

Discussion on: One caller, two approvers: the bypass a reader found in my approval code

Collapse
 
_firelinks profile image
Mike Dabydeen •

Two of your open items depend on each other, so I'd ship them together. The requester check compares the deciding actor with requested_by, and on a request created over HTTP that value is whatever the caller put in the header. A requester can file under any name, approve with their own token, and the check passes. create() already stores actor_source on the request, so the check can read it. If the request's source is header or unspecified, comparing names proves nothing, so either gate create the way you gated decide, or refuse decisions on those requests until a verified caller files them again.

On the decisions recorded before the fix: decided_at comes from the server clock inside decide(), not from the caller, so it already separates them. _status() could skip approve decisions dated before the PR #10 merge without a schema change. I'd run that as a report first, listing the approvals whose status would change, because some of them are probably real approvals that just can't be verified now. Then add actor_source to the decision record itself. Today the gate guarantees new decisions were verified, but the record only shows it through the date.

Collapse
 
williamchiu profile image
weiche chiu •

You're right that they depend on each other. On the reference server every request is created over HTTP, so requested_by is whatever the caller sent. A requester check that compares names would only stop someone who files under their own name. Shipped alone, it would look like protection without being any. I'll do both in one change: decide() reads the request's actor_source and refuses when it's header or unspecified, and the requester check sits behind that.

You're also right about the old decisions. decided_at is set inside decide() from the server clock, and was before PR #10 too, so the article's line that filtering them out needs a schema change is wrong. A cutoff at the merge time works. I'll run it as a report first, as you suggest, and then add actor_source to the decision record so a decision shows how it was verified without relying on its date. I'll correct that line in the article.