![[New Feature] Snowflake's Multi-party Approval is now generally available, so we tried making approval flows mandatory for critical operations](https://images.ctfassets.net/ct0aopd36mqt/wp-refcat-img-3610e3c1ff5961bdb7b464e17f8bf06d/90b168b240005ead852ec1d474bb74fb/snowflake-logo-1200x630-1.png?w=3840&fm=webp)
[New Feature] Snowflake's Multi-party Approval is now generally available, so we tried making approval flows mandatory for critical operations
This page has been translated by machine translation. View original
This is Kawabata.
With Multi-party Approval (MPA), which became GA on August 4, 2026, you can now require "review and approval by a second approver" for critical operations.
In this article, using network policy changes as the protected target, I will verify the entire flow from MPA policy creation to the approval workflow, abnormal scenarios such as rejection and cancellation, and auditing through the Account Usage view.
Overview of Multi-party Approval
MPA is a feature that prevents specified critical operations (protected operations) from being executed by a single administrator alone. When someone attempts to execute a protected operation, it is temporarily blocked and an approval request is issued. Only after another approver reviews and approves the request can the original operation be executed.
The main motivation is that even if an administrator account is compromised in a ransomware attack or similar incident, the attacker cannot unilaterally execute fatal operations such as disabling MFA or revoking Tri-Secret Secure keys.
Protected Operations
Operations that can be protected are divided into the following 3 groups. For each rule in the policy, you select which operations to protect.
| Group | Operation | Description |
|---|---|---|
| Administrative Operations | MODIFY_MULTI_PARTY_APPROVAL | Changes to MPA policies, rules, and application/removal to accounts (required for all policies). Also covers creation, modification, and deletion of SAML2 security integrations |
| Administrative Operations | DISABLE_MULTI_FACTOR_AUTHENTICATION | Disabling MFA and resetting user passwords |
| Administrative Operations | MODIFY_TRI_SECRET_SECURE | Enabling/disabling Tri-Secret Secure keys |
| Administrative Operations | MODIFY_PRIVILEGED_ROLE_GRANTS | Granting/revoking administrator roles |
| Administrative Operations | MODIFY_CORTEX_GUARDRAILS | Modifying Cortex AI guardrails |
| Administrative Operations | MODIFY_DATA_RETENTION_TIME | Changing Time Travel retention period |
| Policy Operations | MODIFY_NETWORK_POLICY | Modifying active network policies and network rules, changing assignments to accounts/users |
| Policy Operations | MODIFY_SESSION_POLICY | Changing session policy settings and assignments |
| Policy Operations | MODIFY_AUTHENTICATION_POLICY | Changing authentication policy settings and assignments |
| Policy Operations | MODIFY_PASSWORD_POLICY | Changing password policy settings and assignments |
| Security Integration Operations | MODIFY_OAUTH_INTEGRATION | Modifying OAuth integrations |
| Security Integration Operations | MODIFY_EXTERNAL_OAUTH_INTEGRATION | Modifying External OAuth integrations |
| Security Integration Operations | MODIFY_SCIM_INTEGRATION | Modifying SCIM integrations |
The reason MODIFY_MULTI_PARTY_APPROVAL also protects SAML2 security integrations is that if SSO settings are modified, the attacker could manipulate who can be authenticated as an approver.
Note: Protection for MODIFY_TRI_SECRET_SECURE requires Business Critical Edition or higher. The edition requirements for the MPA feature itself are not explicitly stated in the documentation as of August 2026.
Approval Flow
When you attempt to execute a protected operation, the flow proceeds in the following 4 steps.
- When the requester executes the SQL for a protected operation, it is blocked with an
MPA_APPROVAL_REQUIREDerror and arequest_idis returned - When the requester submits a business justification using
SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION(), the request becomes PENDING and the approver is notified - The approver reviews the request in Snowsight and votes to approve or reject. Once the required number of approvals is reached, the status becomes APPROVED
- When the requester re-executes the exact same SQL statement that was originally blocked, it matches the approved request and is executed (within 3 days of approval)
The request status transitions through PENDING / APPROVED / EXECUTED / REJECTED / CANCELLED / EXPIRED. If even one approver rejects the request, it immediately becomes REJECTED.
Note that there are 2 patterns for becoming EXPIRED.
- When the required number of approvals is not reached within the expiration period (request_duration_days) while still in PENDING status
- When the request becomes APPROVED but the re-execution is not performed within the 3-day replay window
It does not mean that "once approved, re-execution can be performed at any time."
Policy Components
An MPA policy is a schema-level object with a YAML-format definition that can contain multiple rules. The configuration items for each rule are as follows.
| Item | Required/Optional | Default | Range |
|---|---|---|---|
| name (rule name) | Required | - | - |
| operations (protected operations) | Required | - | 1 or more (cannot be empty) |
| approvers.users (approvers) | Required | - | - |
| required_approvals (required number of approvals) | Optional | 2 | 1–20. Must be less than or equal to the number of approvers in the list |
| request_duration_days (request expiration) | Optional | 3 days | Maximum 14 days |
| self_approval_allowed (allow self-approval) | Optional | true | true / false |
Note: All policies must have at least one rule that includes MODIFY_MULTI_PARTY_APPROVAL in operations. This is a self-protecting rule designed to prevent a compromised administrator from unilaterally disabling or modifying MPA itself. Also, a single operation can only be included in one rule within the same policy.
Note: self_approval_allowed defaults to true. If the requester is included in the approver list, they can approve their own request and have it counted toward the required number of approvals. Specifying self_approval_allowed: false prevents the requester's own vote from being counted toward the approval count. On the other hand, setting required_approvals to 2 or more while leaving it true still prevents solo execution, but the requester's own vote is included in the approval count. If you require the four-eyes principle, which clearly separates requesters from approvers, it is appropriate to explicitly set self_approval_allowed: false and configure approvers to be different users from the requester.
Approver Requirements
There are conditions for users who can be designated as approvers.
- Must be a local Snowflake user or a SCIM-managed user (service users are not allowed)
- Must be enrolled in MFA
- Must have a verified email address
No additional privileges are required for the approval operation itself, and granting ACCOUNTADMIN to approvers is not a mandatory requirement for MPA. From a least-privilege perspective, it is desirable not to grant approvers unnecessarily strong privileges.
Additionally, users designated as approvers are protected, and login name changes or deprovisioning (deletion) via SCIM is blocked.
Prerequisites
- ACCOUNTADMIN role must be used to configure and manage MPA policies
- Approvers must be users with MFA enrollment and verified email addresses (granting ACCOUNTADMIN is not required)
- In this verification, we use 2 users: KAWABATA_ADMIN (using ACCOUNTADMIN) who executes protected operations, and APPROVER_ADMIN as the approver, plus a dedicated verification user as the network policy assignment target
- Verification is performed in an environment after the GA on August 4, 2026
Verification Environment
- Verification period: August 5, 2026 – August 11, 2026
- Snowflake trial account, Enterprise edition
- Verification user configuration:
- KAWABATA_ADMIN: Requester who executes protected operations (using ACCOUNTADMIN)
- APPROVER_ADMIN: Approver (MFA enrolled, email verified)
- MPA_TEST_USER: Dedicated verification user as the network policy assignment target (not used for login)
Preparation
Creating and Activating a Verification Network Policy
We will use MODIFY_NETWORK_POLICY for verifying protected operations. What is important here is that the protection scope of MODIFY_NETWORK_POLICY is defined as "modifying active network policies and network rules, and changing assignments to accounts or users." A network policy does not become effective just by being created; it only becomes active when assigned to an account or user, so changes to a policy not assigned anywhere may not be blocked by MPA.
Therefore, we create a dedicated verification user who is not used for login, assign the policy to that user to create an active state. We avoid assigning at the account level due to the risk of lockout.
USE ROLE ACCOUNTADMIN;
-- Dedicated verification user for assignment target (not used for login)
CREATE USER mpa_test_user
COMMENT = 'MPA verification: network policy assignment target';
-- Verification network policy (no practical restrictions are added since all IPs are allowed)
CREATE NETWORK POLICY mpa_test_network_policy
ALLOWED_IP_LIST = ('0.0.0.0/0')
COMMENT = 'MPA verification test policy';
-- Assign to the dedicated verification user to make it active
ALTER USER mpa_test_user SET NETWORK_POLICY = mpa_test_network_policy;

Note: Assigning a network policy to a user itself is also within the protection scope of MODIFY_NETWORK_POLICY. If you attempt the assignment after enabling MPA, approval will be required, so complete the assignment before enabling MPA.
Note: Even for a dedicated verification user, creating it with
DISABLED = TRUEas shown below eliminates the possibility of unintended login at the configuration level, making it safer (this verification was conducted without DISABLED).
CREATE USER mpa_test_user
DISABLED = TRUE
COMMENT = 'MPA verification: network policy assignment target; login disabled';
Creating the MPA Policy
Prepare a database and schema for storing the policy, then create the MPA policy. We define 2 rules.
- self_protection_rule: A required rule that protects changes to the MPA configuration itself
- network_policy_rule: A verification rule that protects network policy changes
Only a user different from the requester (APPROVER_ADMIN) is set as the approver, and self_approval_allowed: false is explicitly specified. This means KAWABATA_ADMIN cannot approve their own request, and APPROVER_ADMIN's review is always required.
CREATE DATABASE IF NOT EXISTS security_db;
CREATE SCHEMA IF NOT EXISTS security_db.policies;
CREATE MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy
AS $$
description: 'MPA verification policy'
rules:
- name: self_protection_rule
description: 'Protect MPA configuration changes'
operations: [MODIFY_MULTI_PARTY_APPROVAL]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
- name: network_policy_rule
description: 'Protect network policy changes'
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
$$;

Note: To keep the verification simple, we are using 1 approver + required_approvals: 1, but the official best practice recommends 2 or more for all rules. In production, it is desirable to list multiple approvers, with a combination of required_approvals: 2 or more + self_approval_allowed: false (required_approvals must be less than or equal to the number of approvers in the list).
Let's also check the behavior when attempting to create a policy without defining a rule that includes MODIFY_MULTI_PARTY_APPROVAL.
CREATE MULTI PARTY APPROVAL POLICY security_db.policies.mpa_invalid_policy
AS $$
rules:
- name: network_policy_only_rule
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['APPROVER_ADMIN']
$$;

Applying the Policy to the Account (Activation)
Apply the created policy to the account using ALTER ACCOUNT. Since this is the initial application before MPA is enabled, this operation itself is not expected to be blocked (replacement or removal after activation becomes a protected operation under MODIFY_MULTI_PARTY_APPROVAL).
ALTER ACCOUNT SET MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy;

When operating from Snowsight, you can create and activate (Activate) a policy from Governance & Security » Requests & approvals » Multi-party configuration.

Trying Out the Basic Flow
Confirming That Protected Operations Are Blocked
As the requester (KAWABATA_ADMIN), let's try to execute a change to the active network policy.
ALTER NETWORK POLICY mpa_test_network_policy SET ALLOWED_IP_LIST = ('0.0.0.0/0', '10.0.0.0/8');

According to the documentation, an error in the following format is returned, and the SQL for registering the justification and for cancellation is provided directly.
Blocked by Multi-party Approval. A request has been created. To proceed, add a justification: "select SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION('94ceb31d-4ee0-4a14-b470-f5036eac52cb', '<reason>');". To cancel: "select SYSTEM$CAST_MULTI_PARTY_APPROVAL_VOTE('94ceb31d-4ee0-4a14-b470-f5036eac52cb', 'REJECT');". Expires: August 14, 2026 at 12:42:56 PM UTC. Request-ID: '94ceb31d-4ee0-4a14-b470-f5036eac52cb'
Submitting the Justification
Using the request_id included in the error message, submit the business reason for the operation. This transitions the request to PENDING and notifies the approver.
SELECT SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION(
'<request_id>',
'MPA verification: adding 10.0.0.0/8 to the allowed IP list of the test network policy.'
);

While the request is in PENDING status, the justification can be updated any number of times. The requester can check their own request status from Snowsight under Governance & Security » Requests & approvals » Pending » Created by me.

Approval by the Approver
Log in to Snowsight as the approver (APPROVER_ADMIN) and open Governance & Security » Requests & approvals » Pending » Sent to me to see the pending approval request.

Opening the request allows you to review the target operation, requester, and justification, then choose Approve or Reject. Here we choose Approve.

Since required_approvals is set to 1, 1 vote of approval transitions the request to APPROVED.
Re-executing the Original SQL
Return to the requester (KAWABATA_ADMIN) and re-execute the SQL that was originally blocked. It matches the approved request and this time executes successfully.
ALTER NETWORK POLICY mpa_test_network_policy SET ALLOWED_IP_LIST = ('0.0.0.0/0', '10.0.0.0/8');

After approval, only the exact same statement as the SQL that was blocked when the approval request was created can be executed. SQL with changed target objects or settings will not match the approved request and will be treated as a new operation. Let's actually verify this by executing an ALTER with a partial change.
ALTER NETWORK POLICY mpa_test_network_policy SET ALLOWED_IP_LIST = ('0.0.0.0/0', '10.0.0.0/9');

Note: Re-execution must be performed within 3 days of approval. If the deadline passes, the request becomes EXPIRED and you must start over from a new request. Once execution is complete, the request becomes EXECUTED (a terminal state).
Checking Abnormal Scenarios
Rejection by the Approver (REJECTED)
Create another request for a network policy change, submit a justification, and this time have the approver Reject it. A comment is required for rejection.

If even one approver rejects the request, it immediately becomes REJECTED and is terminated.
Cancellation by the Requester (CANCELLED)
The requester can cancel their own request in PENDING status by voting REJECT using SYSTEM$CAST_MULTI_PARTY_APPROVAL_VOTE. In this case only, the comment can be omitted. Approved, rejected, or expired requests cannot be cancelled.
SELECT SYSTEM$CAST_MULTI_PARTY_APPROVAL_VOTE(
'<request_id>',
'REJECT'
);

Self-approval Behavior (Optional Additional Verification)
Since self_approval_allowed defaults to true, if the requester is included in the approver list, they can approve their own request. To verify this behavior, let's replace the policy with one where the requester is added to the approvers for the network_policy_rule only and self_approval_allowed is reverted to the default (true).
Note: This configuration is exclusively for verifying self-approval behavior. Since the requester can complete the entire process through approval on their own, the four-eyes principle cannot be achieved.
The key point is that replacing the policy itself is a protected operation under MODIFY_MULTI_PARTY_APPROVAL, so this change also requires APPROVER_ADMIN's approval. This also serves as a confirmation that the self-protecting rule is functioning.
ALTER MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy
AS $$
description: 'MPA verification policy (self approval test)'
rules:
- name: self_protection_rule
description: 'Protect MPA configuration changes'
operations: [MODIFY_MULTI_PARTY_APPROVAL]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
- name: network_policy_rule
description: 'Protect network policy changes (self approval test)'
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['KAWABATA_ADMIN', 'APPROVER_ADMIN']
required_approvals: 1
$$;

After the replacement, KAWABATA_ADMIN created a request for a network policy change and registered a justification using SYSTEM$UPDATE_MULTI_PARTY_APPROVAL_JUSTIFICATION. In this verification environment, re-execution of the original SQL succeeded without voting Approve in the Snowsight approval screen.

Note: According to the flow in the official documentation, registering the justification only transitions the request to PENDING, and even when self-approval is allowed, the requester themselves must vote Approve in Snowsight and the request must become APPROVED before re-executing the original SQL. Since the behavior observed in this verification — "re-execution succeeds without voting" — differs from this description, it cannot be concluded as the general specification for when self-approval is permitted. The same behavior can also occur if an approved request for the same SQL remains within the 3-day replay window, so please verify in your own account when trying this.
Note: In actual operations, a combination of self_approval_allowed: false and required_approvals: 2 or more is recommended. A configuration that allows self-approval does not provide protection against the compromise of a single administrator account.
After confirming the self-approval behavior, revert to the safe policy definition (both rules with self_approval_allowed: false). This ALTER itself is also a protected operation under MODIFY_MULTI_PARTY_APPROVAL, so APPROVER_ADMIN's approval is required.
-- After the self-approval test, revert to the safe policy definition
-- This ALTER itself is also subject to MODIFY_MULTI_PARTY_APPROVAL approval
ALTER MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy
AS $$
description: 'MPA verification policy'
rules:
- name: self_protection_rule
description: 'Protect MPA configuration changes'
operations: [MODIFY_MULTI_PARTY_APPROVAL]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
- name: network_policy_rule
description: 'Protect network policy changes'
operations: [MODIFY_NETWORK_POLICY]
approvers:
users: ['APPROVER_ADMIN']
required_approvals: 1
self_approval_allowed: false
$$;
How to Check Policies and Requests
SHOW / DESCRIBE Commands
Policy lists and definitions can be confirmed using SQL.
-- List of policies
SHOW MULTI PARTY APPROVAL POLICIES;
-- Policy currently applied to the account
SHOW MULTI PARTY APPROVAL POLICIES ON ACCOUNT;
-- Checking the policy definition (full YAML)
DESC MULTI PARTY APPROVAL POLICY security_db.policies.mpa_verification_policy;



Auditing with Account Usage Views
The history of approval requests can be confirmed using Account Usage views. Since you can trace who requested which operation at what time and who voted, this can also be used for audit purposes.
SELECT
request_id,
requester_user_name,
operation,
status,
request_justification,
required_approvals_count,
approvers,
created_time,
resolved_time
FROM snowflake.account_usage.multi_party_approval_requests
ORDER BY created_time DESC;

The change history of the policy itself can be confirmed using the MULTI_PARTY_APPROVAL_POLICIES view.
SELECT name, database, schema, policy_definition, created, last_altered, deleted
FROM snowflake.account_usage.multi_party_approval_policies;

Note: Both views have a latency of up to 120 minutes. They may not be reflected immediately after verification.
Limitations and Notes
Here is a summary of the limitations and notes confirmed through verification and official documentation.
Limitations and Notes
- Approvers must be local Snowflake users or SCIM-managed users, with MFA enrollment and email address verification required (service users are not allowed). Granting ACCOUNTADMIN is not required
- Approver voting is performed from an active session in Snowsight
- Re-execution after approval must be performed within 3 days, using the exact same SQL statement as when it was blocked
- Cancellation by the requester is only possible for requests in PENDING status
- A single operation can only be included in one rule within the same policy. Also, required_approvals must be less than or equal to the number of approvers in the list
- self_approval_allowed defaults to true. Explicitly setting it to false prevents the requester's own vote from being counted toward the approval count. Setting required_approvals to 2 or more while leaving it true still prevents solo execution, but the requester's own vote is included in the approval count
- Account Usage view latency is up to 120 minutes
- If the policy is changed, PENDING requests are automatically re-evaluated (reconciled) against the new rule configuration
- In cases of deadlock, such as all approvers becoming unavailable, the response involves filing a formal ticket with Snowflake Support (break-glass). It is recommended to have multiple ACCOUNTADMIN users assigned and to periodically review the approver list
Closing Thoughts
With Multi-party Approval, the control of "important operations must always be reviewed by 2 people" — which until now could only be enforced through operational rules — can now be enforced as a Snowflake feature. However, it is important to note that self_approval_allowed defaults to true, and the recommended configuration to keep in mind is self_approval_allowed: false + required_approvals: 2 or more + approvers separated from the requester. As a countermeasure against a single ACCOUNTADMIN acting alone or being compromised, it seems best to start by protecting the self-protection rule + MFA disabling + network policy changes.
I hope this article is helpful in some way!
