Most vulnerability management programs spend their energy on getting findings in and getting findings fixed. The decisions that quietly carry the most risk are the ones that take a finding off the board without a fix. Marking something as accepted risk, declaring it a false positive, or closing it outright are all judgment calls. When a single analyst can make those calls alone, the program inherits a structural weakness that auditors notice and attackers exploit.
Four-eyes approval is the control that closes that gap. It requires a second, independent reviewer to sign off before a sensitive finding change takes effect. In PMAP, this is not a policy you write in a runbook and hope people follow. It is enforced behavior built into the finding workflow, wired so that the requester can never be the approver, and recorded as a timestamped, two-party trail that stands up to review.
This article explains why second-person review matters for vulnerability decisions, exactly which status changes PMAP gates, how the request-to-decision flow works, and how the resulting approval timeline becomes audit evidence. If you are looking for the click-by-click procedure, the practitioner guide on how to approve sensitive finding changes covers the steps. This piece is about the why and the design decisions behind it.
Why a Single Analyst Should Not Accept Risk Alone
Accepting risk is a statement that the organization will live with an open vulnerability. It is a business decision dressed up as a technical one. The analyst who triages a finding may understand the technical severity perfectly well and still lack the context to decide that the residual risk is acceptable for the company. Compensating controls, asset criticality, regulatory exposure, and contractual obligations all sit outside the finding record. A single person rarely holds all of it.
This is precisely why unilateral risk acceptance is a recurring audit finding in regulated environments. When an assessor asks who decided that a critical vulnerability could stay open, and the answer is one analyst with no review and no record of the reasoning, the program has a control deficiency. The same pattern applies to false positives. A finding dismissed as a false positive disappears from every dashboard and SLA clock. If that judgment was wrong and nobody checked it, a real exposure has been hidden by a single keystroke.
PMAP treats these decisions as governance events rather than ordinary edits. Every accepted-risk and false-positive decision becomes a two-party, timestamped, comment-bearing record. The second reviewer is not a rubber stamp. They are a structural safeguard against the one person who is too close to the finding, too rushed, or simply wrong. The point is not to slow analysts down on routine work. The point is to make the small set of irreversible decisions deliberate and accountable.
There is a quality benefit too. Knowing that a peer will read the justification changes how analysts write it. Requests carry better evidence and clearer reasoning when someone is going to evaluate them. Over time, the review gate raises the standard of every decision it touches, not just the ones that get rejected.
Which Status Changes Are Gated
Four-eyes approval in PMAP is targeted, not blanket. Applying a review gate to every status change would bury reviewers in noise and train them to approve without reading. PMAP gates exactly the transitions that remove a finding from active management or hide it from view. Three statuses require approval before the change takes effect when the approval workflow is enabled.
The first is accepted_risk. This is the explicit decision to leave a vulnerability open and own the consequences. It is the highest-stakes call in triage and the one most likely to surface in an audit.
The second is false_positive. Declaring a finding invalid is a claim that there is nothing to fix. If accepted blindly, it permanently removes a finding from the queue, the dashboards, and the SLA timers. A wrong false-positive call is an exposure that the program no longer tracks.
The third is closed. Closing a finding asserts that the issue is resolved. Gating closure ensures that a finding is not quietly marked done without a second person confirming the resolution holds.
These three are all terminal states in the finding status state machine. Once a finding reaches closed, false_positive, or accepted_risk, the state machine treats it as final. Because the consequences are durable and removing a finding from active tracking is exactly the kind of decision an organization wants reviewed, these are the transitions PMAP puts behind the gate. Every other transition in the triage cycle, such as moving from open to in_progress or sending a finding to retest, proceeds without an approval round trip. The gate sits only where it earns its place.
The Request to Decision Flow
The mechanics of the gate are designed to be unobtrusive for routine work and unmistakable for the decisions that matter. The flow runs from request to inbox to review to a recorded outcome.
When an analyst changes a finding’s status to one of the three gated values and the approval workflow is enabled, the status change does not apply immediately. The PUT /findings/{id}/status endpoint responds with a 202 ApprovalRequest instead of executing the transition. The finding stays exactly where it was. Nothing about the live state of the program changes on the strength of one person’s intent.
From the finding’s Approvals tab, the analyst opens the request modal. They select the target status, add an optional justification note up to 1,000 characters, and set an optional expiry date. Submitting calls POST /findings/{id}/approvals and creates the request in a pending state. The note is where the reasoning lives. A good request explains why the analyst believes the risk is acceptable, why the finding is a false positive, or why closure is justified, so the reviewer has something concrete to evaluate.
The request then surfaces to eligible reviewers. The sidebar pending-count badge increments within 60 seconds, and the reviewer navigates to the approvals inbox to act on it. In the inbox, the reviewer opens the review modal, sees the request details, and can add an optional reviewer note before confirming. Approving calls POST /approvals/{id}/approve; rejecting calls POST /approvals/{id}/reject.
The outcome is decisive. An approved request lets the finding status change proceed to the target status. A rejected request leaves the finding exactly where it was, in its current status, with the reviewer’s note explaining what was missing. Both paths produce a permanent record. There is no state in which a sensitive change happens without a decision attached to it.
Self-Review Prevention as a Hard Rule
The integrity of any four-eyes control rests on one principle. The person who requests a change cannot be the person who approves it. If that rule can be bent, the gate is decorative. PMAP enforces it in two layers so that it cannot be bypassed by accident or intent.
At the API level, the platform returns ErrSelfReviewBlocked if the user attempting to approve or reject a request is the same user who created it. This is the authoritative check. It does not matter how the request to approve arrives; the backend rejects a self-review outright.
At the UI level, the action buttons are simply not rendered when the request’s requester matches the current user. When req.requester_id === currentUserId, the approve and reject controls disappear. This is a first line of defense that keeps analysts from even attempting a self-review, with the API enforcement standing behind it as the guarantee.
The two layers serve different purposes. The UI keeps the interface honest and prevents wasted clicks. The API makes the separation of duties non-negotiable regardless of what the client does. Together they implement genuine dual control rather than a convention that depends on people behaving.
The Approvals Inbox and Its Four Queue Modes
Reviewers should not have to hunt through individual findings to discover what needs their attention. The approvals inbox is the dedicated workspace where review happens, and it organizes work into four queue modes so that different roles see what is relevant to them.
The my_pending mode is the default. It shows requests awaiting the current user’s review. Critically, it shows only requests the user is eligible to review, which means it excludes anything they submitted themselves. This is the queue an approver drains. It is their to-do list.
The requested_by_me mode shows the requests the current user submitted. This is where an analyst tracks the fate of their own pending decisions and sees whether a reviewer has acted yet. Because of the self-review rule, requests an analyst submitted never appear in their my_pending queue. They live here instead.
The all_pending mode surfaces every pending request within the user’s tenant scope. This is the manager and administrator view. It exists so that no approval request stalls unreviewed anywhere in the organization. A team lead can scan the whole pending surface and chase down requests that are aging.
The closed mode is the historical record. It holds the requests that have already reached a decision, approved or rejected, and serves as the browsable archive of past governance decisions. An optional target-status dropdown narrows any of these queues further, so a reviewer can focus on, for example, only the accepted-risk requests awaiting them.
Every inbox query applies tenant scope filtering. The all_pending view, despite its name, surfaces only the pending requests inside the authenticated user’s tenant. There is no path through which a reviewer in one company sees approval requests from another.
One Pending Request Per Finding
A finding can have only one pending approval request at a time. This rule prevents a class of confusion that would otherwise undermine the whole control. If two analysts could each open a request to take the same finding in different directions, reviewers would face contradictory pending decisions on a single record, and the audit trail would become ambiguous.
When a pending request already exists for a finding, a new request is blocked with approval_err_pending_exists. The interface reinforces this by hiding the New Request button while a pending request is open. There is one decision in flight per finding, and it resolves before another can be opened.
A second guard sits alongside this one. The New Request button is also hidden when the finding is already in a terminal status. If a finding is already closed, accepted_risk, or false_positive, there is nothing to gate. The gate exists to govern the transition into those states, not to re-litigate a finding that is already there. Together these two guards keep the approval surface clean. Every pending request maps to exactly one live decision on a finding that is still in play.
Expiry, Cancellation and Request Hygiene
Approval requests are not allowed to pile up as stale clutter. Two mechanisms keep the pending surface honest over time.
Requests carry an optional expiry date through the expires_at field. When that date passes without a decision, the request is surfaced with an expiry-lapsed badge, and the approval lifecycle records it as expired. An expired request is a signal in its own right. It tells the program that a decision sat unreviewed long enough to lapse, which is useful feedback about reviewer responsiveness. The decision was never silently applied; it simply aged out and is recorded as such.
Cancellation handles the case where the analyst changes their mind. Only the requester can cancel their own pending request, and doing so moves it to the cancelled state. This is the retraction path for a premature or incorrect submission. Maybe the analyst found new evidence, maybe they realized the finding deserves a fix after all. Cancelling cleanly withdraws the request, and the New Request button becomes available again so a corrected request can follow.
The lifecycle is small and complete. A request begins as pending and ends as one of approved, rejected, expired, or cancelled. Every request reaches one of those outcomes. None of them is the silent application of a sensitive change. The state model itself guarantees that a gated transition only happens through an explicit approval.
The Per-Finding Approval Timeline as Audit Evidence
The most valuable byproduct of the approval gate is the evidence it produces. Every finding carries its own approval timeline, visible from the finding detail Approvals tab, and that timeline is exactly what an auditor wants to see.
The timeline is a chronological, newest-first sequence of approval cards. Each card carries the full context of one request. The requester block shows who asked for the change and the justification note they wrote. The reviewer block shows who decided and the reviewer note they left. Color coding makes the state legible at a glance, with distinct treatments for pending, approved, rejected, and expired or cancelled requests, and an expiry-lapsed badge where a request aged out.
This is what separates a governed decision from an undocumented one. When an assessor asks why a critical vulnerability was accepted as risk, the answer is on the timeline. The requester’s reasoning, the reviewer’s independent confirmation, both identities, and the timestamps are all there in one place, attached to the finding rather than scattered across email threads and chat messages. The reviewer notes are particularly valuable on rejected requests, because they record what evidence was missing, which both improves the next submission and demonstrates that review was substantive rather than reflexive.
Because approvals sit alongside the full finding activity feed, the approval trail is part of the same continuous history as status changes, assignments, and notes. There is no separate system to reconcile. The story of the finding, including who governed its sensitive transitions, lives in one record. This connects directly to the broader compliance and audit posture that regulated programs have to demonstrate.
Keeping Reviewers Responsive
A review gate only works if reviewers actually review. A control that introduces a bottleneck without making the queue visible will frustrate analysts and tempt the organization to disable it. PMAP keeps reviewers aware of their queue with a live signal and gives the program a way to measure responsiveness.
The sidebar pending-count badge is the live signal. It shows the count of requests awaiting the current user’s review and polls every 60 seconds, so a reviewer sees pending work appear without refreshing the page. The badge is scoped to the user’s own review queue, which means it reflects genuine personal workload rather than organization-wide noise. An approver knows at a glance whether there is anything waiting on them.
For program-level visibility, the platform tracks mean time to review, measured from the moment a request is created to the moment a decision is made. This is the metric that tells a manager whether the gate is healthy or whether it has become a bottleneck. A rising mean time to review, or a climbing rate of expired requests, is an early warning that reviewers are overloaded or disengaged. The expired-request rate doubles as a direct measure of approver responsiveness, since a request only expires when nobody acts on it in time.
Together these give the program both the operational nudge and the management dashboard it needs to run the gate without it becoming a source of friction.
Approvals as a Compliance Control
Everything above adds up to a control that maps cleanly onto compliance requirements. Segregation of duties is a foundational concept in security governance, and four-eyes approval is one of its most concrete implementations.
The principle that a single individual should not control a sensitive action end to end appears across the major frameworks. ISO/IEC 27001:2022 treats segregation of duties as a core organizational control. NIST SP 800-53 defines separation of duties explicitly in its AC-5 control. The AICPA SOC 2 Trust Services Criteria likewise expect that significant decisions are subject to appropriate review. In each case, the assessor is looking for evidence that a second, independent party reviewed the decision and that the review is recorded.
PMAP produces exactly that evidence as a natural consequence of how findings are managed. The two-party, timestamped, comment-bearing approval record is not generated for an audit. It is the byproduct of the normal workflow, which is the strongest kind of evidence because it cannot be reconstructed after the fact. The requester and reviewer are always different people, enforced at the API. The decision is always timestamped. The reasoning is always captured. For a regulated environment, the gap between policy and demonstrable practice is where audits fail. The approval gate closes that gap by making the policy the only way the system behaves.
How PMAP Enforces Four-Eyes End to End
The reason this control holds up is that it is enforced consistently at every layer rather than relying on any single point. A gate that lives only in the interface can be bypassed by anyone who reaches the API directly. A gate that lives only in the API still benefits from a clear interface, but neither is sufficient alone. PMAP implements both.
At the UI layer, the platform hides what should not be available. Self-review buttons disappear when the current user is the requester. The New Request button vanishes when a pending request already exists or when the finding is already terminal. The interface never presents an action that the rules would reject, which keeps analysts on a clean path.
At the API layer, the platform enforces the same rules authoritatively. Self-review returns ErrSelfReviewBlocked. A duplicate request returns approval_err_pending_exists. A sensitive status change returns 202 ApprovalRequest rather than applying the transition. Tenant scope filtering applies to every inbox query. These are not client-side conveniences. They are the guarantees, and they hold regardless of what the client does.
This dual enforcement is what turns four-eyes from an aspiration into a property of the system. The requester is never the approver, not by convention but by design. Sensitive transitions never take effect without a recorded decision, not because people remember to follow the process but because the platform admits no other path. That is the difference between a control that looks good in a policy document and one that an auditor can verify by inspecting how the software actually behaves.
If your program still allows a single analyst to accept risk, dismiss a finding as a false positive, or close it without a second set of eyes, four-eyes approval is the gap worth closing first. See how PMAP gates risk acceptance behind a second reviewer and builds an audit-ready approval trail.
Frequently Asked Questions
What is a four-eyes approval in vulnerability management?
A four-eyes approval requires that two different people are involved in a sensitive decision. One person requests the change and a second, independent person approves it before it takes effect. In PMAP, this applies to the finding status changes that remove a finding from active management, namely accepting risk, declaring a false positive, and closing a finding. The requester and the approver can never be the same user.
Which finding status changes require approval in PMAP?
Three status changes are gated when the approval workflow is enabled: accepted_risk, false_positive, and closed. These are the terminal states that take a finding off the active board. All other transitions in the triage cycle, such as moving a finding to in-progress or sending it to retest, proceed without an approval step.
Can an analyst approve their own approval request?
No. Self-review is blocked as a hard rule. The interface hides the approve and reject buttons whenever the current user is the one who submitted the request, and the API independently returns ErrSelfReviewBlocked if a self-review is attempted. The separation of requester and approver is enforced at both layers, so it cannot be bypassed.
What happens to a finding while an approval request is pending?
Nothing changes. When a gated status change is submitted, the platform returns a pending approval request instead of applying the transition, and the finding stays in its current status. If the request is approved, the status change proceeds. If it is rejected, the finding remains exactly where it was, with the reviewer’s note explaining why.
What if an approval request is never reviewed?
A request can carry an optional expiry date. If that date passes without a decision, the request is recorded as expired and surfaced with an expiry-lapsed badge. The sensitive change is never applied silently. A requester can also cancel their own pending request before any decision is made. The program can track mean time to review and the expired-request rate to monitor reviewer responsiveness.
How does four-eyes approval support a compliance audit?
Every gated decision produces a two-party, timestamped record with both the requester’s justification and the reviewer’s note, all visible on a chronological per-finding approval timeline. This is direct evidence of segregation of duties, which frameworks such as ISO/IEC 27001, NIST SP 800-53 AC-5, and SOC 2 expect. Because the trail is a byproduct of the normal workflow, it cannot be reconstructed after the fact, which makes it strong audit evidence.
Can two people open competing approval requests on the same finding?
No. PMAP allows only one pending approval request per finding. A second request is blocked while one is already pending, and the New Request button is hidden until the open request is resolved or cancelled. The New Request button is also hidden when a finding is already in a terminal status, since there is no transition left to gate.