When someone signs in to your Snowflake account with a stolen credential, the data can leave through ordinary SQL, so the response has to run on Snowflake's own telemetry and controls rather than on endpoint tools. This playbook is the incident path: the ACCOUNT_USAGE queries that show who signed in and what was read or unloaded, the order in which to lock down network policies, users and tokens, how to review stages and integrations, and what to keep as evidence. It is written for security operations, data platform owners and incident responders who run Snowflake as a customer. Preventive configuration such as MFA, key pair authentication and authentication policies is covered in the Snowflake Security Guide; this page assumes something has already gone wrong and stays on response.
This is an independent guide from NHI Mgmt Group, based on Snowflake's public documentation as of November 2026. It is not sponsored or reviewed by Snowflake. Product features change, so confirm settings against Snowflake's current documentation.
Key takeaways
- Query the account, not the laptop. LOGIN_HISTORY, SESSIONS, QUERY_HISTORY and ACCESS_HISTORY in the SNOWFLAKE.ACCOUNT_USAGE schema hold a year of sign-ins, sessions and queries, and they are your primary evidence.
- Allow for latency. LOGIN_HISTORY can lag by up to two hours, QUERY_HISTORY by up to 45 minutes and ACCESS_HISTORY by up to three hours, so a quiet result in the first hour does not mean nothing happened.
- Disabling a user stops running work.
ALTER USER ... SET DISABLED = TRUEaborts the user's running and scheduled statements and blocks new logins, which makes it the fastest single containment step. - Network policies apply to live sessions. An account or user network policy blocks further queries from sessions outside the allowed rules, but activating one from the wrong IP can lock out your own responders.
- Every credential type needs its own reset. Passwords, RSA public keys, programmatic access tokens and OAuth consents are separate authenticators; resetting one leaves the others working.
How the incident shows up
Snowflake compromise is usually noticed through an unusual sign-in, a cost spike on a warehouse, a Trust Center detection or a third party reporting your data for sale. The table maps common signals to where you confirm them.
| Signal | Where to confirm it | What it may mean |
|---|---|---|
Successful logins from an unfamiliar CLIENT_IP | ACCOUNT_USAGE.LOGIN_HISTORY | Credential use from attacker infrastructure |
SECOND_AUTHENTICATION_FACTOR is NULL for a human user | LOGIN_HISTORY | Password only sign-in, a common entry path for stolen credentials |
Bursts of failed logins (IS_SUCCESS = 'NO') across many users | LOGIN_HISTORY, ERROR_CODE | Credential stuffing or password spraying (ATT&CK T1110.004) |
Unusual REPORTED_CLIENT_TYPE or client version for a user | LOGIN_HISTORY, SESSIONS.CLIENT_APPLICATION_ID | A tool the user does not normally run |
| Login protection or dormant user sign-in detections | Trust Center, Threat Intelligence scanner package | Sign-in from an unusual IP or from a user inactive for 90 days |
Large ROWS_UNLOADED or OUTBOUND_DATA_TRANSFER_BYTES | ACCOUNT_USAGE.QUERY_HISTORY | Bulk export with COPY INTO <location> (T1537, T1567.002) |
| New stages, storage integrations or shares | SHOW STAGES, SHOW INTEGRATIONS, SHOW SHARES, QUERY_HISTORY | A staging area or channel for exfiltration |
| New users, roles or grants of ACCOUNTADMIN | QUERY_HISTORY, ACCOUNT_USAGE.GRANTS_TO_USERS | Persistence (T1136, T1098) |
| Extortion message referencing your tables | Email, leak site monitoring | Data already taken (T1657) |
The initial access technique in most account compromises is T1078.004 Cloud Accounts: a valid user signing in with a credential that was phished, reused or harvested by infostealer malware. See the Infostealer Logs Monitoring and Response Guide for the upstream problem.
Triage questions
Run these as a working session with a data platform owner who holds ACCOUNTADMIN or a delegated role that can read the SNOWFLAKE database. Note the latency figures above and rerun the queries after two to three hours.
- Which users signed in from where? Pull successful logins for the last 30 to 90 days grouped by
USER_NAME,CLIENT_IP,FIRST_AUTHENTICATION_FACTORandSECOND_AUTHENTICATION_FACTOR. Flag IPs that do not belong to your corporate egress, VPN, ETL tools or BI services. - How did they authenticate? A password with no second factor, a key pair, a programmatic access token or an OAuth integration each point to a different credential to revoke. The
FIRST_AUTHENTICATION_FACTOR_IDcolumn identifies which specific credential was used, andAUTHORIZING_INTEGRATION_NAMEnames the security integration for OAuth logins. - What did those sessions do? Join LOGIN_HISTORY.
EVENT_IDto SESSIONS.LOGIN_EVENT_ID, then SESSIONS.SESSION_IDto QUERY_HISTORY. List query text,ROLE_NAME, warehouse, start time and bytes. - Was data unloaded or bulk read? Filter QUERY_HISTORY for non-zero
ROWS_UNLOADED, highOUTBOUND_DATA_TRANSFER_BYTES, and values inOUTBOUND_DATA_TRANSFER_CLOUDorOUTBOUND_DATA_TRANSFER_REGIONthat differ from your own. Look forCOPY INTO,GETandCREATE STAGEstatements. - Which objects were touched? On Enterprise Edition or higher, ACCESS_HISTORY lists
direct_objects_accessed,base_objects_accessedandobjects_modifiedper query, down to column level. This is how you scope which tables, and which personal data columns, were in reach. - Did the attacker change the account? Search QUERY_HISTORY for
CREATE USER,ALTER USER,GRANT ROLE,CREATE STAGE,CREATE STORAGE INTEGRATION,CREATE SHARE,ALTER ACCOUNT,ALTER NETWORK POLICYand any change toDATA_RETENTION_TIME_IN_DAYS. - Is the activity still live? If the sessions are recent, move to containment now and finish scoping afterwards.
A note on GET: Snowflake documents that an execution_status of success for PUT and GET only means the transfer was authorised, not that files moved. Treat it as an indicator to corroborate, not as proof of download.
Containment priorities
Work in this order. Each step should be recorded with time, statement and operator, ideally from a dedicated incident role that is not one of the suspect users.
- Secure responder access first. Confirm at least two responders can sign in with MFA from a known IP, and record their egress addresses. Network policy activation fails unless your current IP or private endpoint is in the allowed list, and only Snowflake Support can set
MINS_TO_BYPASS_NETWORK_POLICY. - Disable suspect users.
ALTER USER <name> SET DISABLED = TRUEaborts that user's running and scheduled statements and prevents new logins. For a service user whose pipeline must keep running, useALTER USER <name> ABORT ALL QUERIESonly as a stopgap, because that user can still log in and start new queries. - Tighten the network policy. Apply an account level policy whose
ALLOWED_NETWORK_RULE_LISTholds only responder, corporate and known integration addresses. Existing sessions from outside those rules are stopped from running further queries. User level policies override the account policy and security integration policies override both, so check those too. - Rotate every authenticator on affected users. Set a new password with
SET PASSWORD(aRESET PASSWORDURL alone does not invalidate the current password). UnsetRSA_PUBLIC_KEYandRSA_PUBLIC_KEY_2and issue new key pairs. Revoke tokens withALTER USER <name> REMOVE PROGRAMMATIC ACCESS TOKEN <token>; revoked tokens cannot be recovered. Revoke OAuth consent withALTER USER <name> REMOVE DELEGATED AUTHORIZATIONS FROM SECURITY INTEGRATION <integration>. - Cut exfiltration paths. Suspend unknown external stages, storage integrations, external functions and outbound shares created during the incident window. Do not drop them yet: describe and record them first.
- Lock retention. If the attacker could drop or overwrite data, set
MIN_DATA_RETENTION_TIME_IN_DAYSat account level so a maliciousDATA_RETENTION_TIME_IN_DAYS = 0on an object cannot disable Time Travel. - Contain upstream. The credential came from somewhere. Reset the same user's identity provider account, revoke its sessions and check the device it was used on. If SSO is in use, follow the Identity Provider Tenant Compromise Playbook where the IdP itself is in doubt.
| Credential type | Containment statement | Watch for |
|---|---|---|
| Password | ALTER USER ... SET PASSWORD = '...' | RESET PASSWORD URL does not invalidate the old password |
| Key pair | ALTER USER ... UNSET RSA_PUBLIC_KEY (and RSA_PUBLIC_KEY_2) | Pipelines that fail until the new public key is set |
| Programmatic access token | ALTER USER ... REMOVE PAT <token_name> | Cannot be run in a session that itself used a PAT |
| OAuth consent | REMOVE DELEGATED AUTHORIZATIONS FROM SECURITY INTEGRATION | Revokes every token for that integration and user |
| Whole user | ALTER USER ... SET DISABLED = TRUE | Aborts running and scheduled work for that user |
Service users need particular care because they often hold broad roles and run unattended. See the Service Accounts in Snowflake Guide and, for finding service users still on passwords, How to find Snowflake service users without key-pair auth.
Eradication
Eradication in Snowflake means removing everything the attacker created or changed, then making sure the entry path no longer works.
- Users and roles: drop users created by the attacker after recording their properties with
DESCRIBE USER. Revoke grants they added, especially of ACCOUNTADMIN, SECURITYADMIN and ownership grants on databases. Compare GRANTS_TO_USERS and GRANTS_TO_ROLES with a pre-incident export if you have one. - Stages: run
SHOW STAGES IN ACCOUNTand review each stage's URL, storage integration and owner. UseLIST @stageto see files left in internal stages, record them, thenREMOVEthem once copied for evidence. Unknown external stages pointing at cloud buckets you do not own should be dropped after evidence capture. - Integrations and shares: review storage, API, notification and security integrations with
SHOW INTEGRATIONS, and outbound shares withSHOW SHARES. Remove consumer accounts you do not recognise. - Scheduled code: check tasks, stored procedures, streams and external functions created or altered in the window. A task can rerun an unload every hour long after the user is disabled, unless its owner role is cleaned up.
- Unload guardrails: set
PREVENT_UNLOAD_TO_INLINE_URLsoCOPY INTOcannot write to a cloud URL typed directly into a statement, andREQUIRE_STORAGE_INTEGRATION_FOR_STAGE_CREATIONandREQUIRE_STORAGE_INTEGRATION_FOR_STAGE_OPERATIONso external stages must use an approved integration. Confirm each value afterwards withSHOW PARAMETERS LIKE '...' IN ACCOUNT. - Close the entry path: apply an authentication policy that requires MFA for human users and blocks password sign-in for service users, as set out in the Snowflake Security Guide. Rerun the Trust Center Security Essentials and Threat Intelligence scanners and resolve the violations.
Recovery
- Restore integrity of data. If tables were dropped,
UNDROPrestores them while they are still within Time Travel retention; it fails if an object of the same name exists, so rename that first. If rows were altered, use Time TravelATorBEFOREclauses to clone the table as it was. The default retention is one day; Enterprise Edition allows up to 90 days on permanent objects. After Time Travel, data enters a seven day Fail-safe period that only Snowflake can recover from, so open a support case early if you need it. - Bring users back in stages. Re-enable human users only after their IdP account and device are cleared and MFA is enforced. Bring service users back with new key pairs or tokens and a user level network policy limited to the pipeline's source addresses.
- Relax the emergency network policy deliberately. Move from the incident allow list to the long-term policy in one recorded change, and confirm every integration still connects.
- Watch closely for 30 days. Schedule the triage queries as alerts, for example any successful login from an IP outside the allow list, any non-zero
ROWS_UNLOADEDby a human user, and any new stage or integration.
| Metric | Target after recovery |
|---|---|
| Human users signing in without a second factor | Zero |
| Service users with password authentication | Zero |
| Logins from outside network policy allow lists | Zero, alerted within the view latency |
| Unreviewed external stages and integrations | Zero; every one has a named owner |
| Time from suspect login to user disablement in exercises | Under one hour |
Evidence to preserve
ACCOUNT_USAGE views retain a year of history, but INFORMATION_SCHEMA table functions cover far less (seven days for query history), and your SIEM may hold less again. Copy the evidence into a locked database or export it before clean-up changes the picture.
| Evidence | Why it matters | How to keep it |
|---|---|---|
| LOGIN_HISTORY for all users, incident window plus 90 days before | Who signed in, from where, with which factors | CREATE TABLE ... AS SELECT into an incident database with restricted ownership |
| SESSIONS rows for suspect logins | Links logins to queries and client software | Same incident database |
| QUERY_HISTORY for suspect sessions and roles | Exact statements, bytes and unload targets | Same, plus export to your SIEM or evidence store |
| ACCESS_HISTORY for suspect queries | Which tables and columns were read, for notification scoping | Same; record the edition you are on |
| DESCRIBE output for suspect users, stages, integrations, shares, tasks | State before you remove them | Save output with timestamps before dropping anything |
| Files in internal stages | What was staged for export | GET to a secured evidence location, hash, then REMOVE |
| IdP sign-in logs and device data for affected users | Where the credential came from | Export from the IdP and EDR before retention expires |
| Snowflake support case history | Fail-safe requests and decisions | Save correspondence |
| Playbook phase | NIST CSF 2.0 | NIST SP 800-53 Rev 5 | MITRE ATT&CK v20 addressed |
|---|---|---|---|
| Triage and scoping | RS.AN-03, DE.CM-03 | IR-4, AU-6 | T1078.004 Cloud Accounts, T1110.004 Credential Stuffing |
| Containment | RS.MI-01 | AC-2, IA-5, SC-7 | T1098 Account Manipulation, T1136 Create Account |
| Eradication | RS.MI-02 | IR-4 | T1537 Transfer Data to Cloud Account, T1567.002 Exfiltration to Cloud Storage |
| Evidence | RS.AN-03 | AU-9 | Not applicable |
| Recovery | RC.RP-01 | CP-10 | T1485 Data Destruction (Time Travel restore) |
| Notification | RS.CO-02 | IR-6 | T1657 Financial Theft (extortion) |
Notification triggers
- Personal data under GDPR or UK GDPR: Article 33 requires the controller to notify the supervisory authority without undue delay and, where feasible, within 72 hours of becoming aware of a personal data breach, unless it is unlikely to result in a risk to individuals. Article 34 requires telling the individuals when the risk is high. ACCESS_HISTORY column lists are the evidence that decides which data subjects are in scope. See the Breach Notification Laws by Country Guide.
- Processors: if you run Snowflake on behalf of clients, Article 33(2) requires you to notify the controller without undue delay.
- US listed companies: a material cybersecurity incident triggers Form 8-K Item 1.05, generally within four business days of determining materiality. See the SEC Cybersecurity Disclosure Rules Guide.
- Sector and contract rules: NIS2 essential and important entities, DORA financial entities and HIPAA covered entities have their own clocks. The Cyber Incident Reporting Requirements Map lists them. Customer contracts often require notice of unauthorised access to their data regardless of law.
- Extortion: if a ransom demand arrives, involve legal counsel before any contact, and see the Ransomware Payments and Sanctions Guide.
Practitioner checklist
- Grant the incident team a role that can read SNOWFLAKE.ACCOUNT_USAGE before an incident, and test it.
- Save the triage queries (logins by IP and factor, sessions to queries, unloads, account changes) as worksheets ready to run.
- Keep a pre-approved emergency network policy and the responder IP list current.
- Know which users are service users and what each one's pipeline needs, so disabling is a quick decision.
- Set
MIN_DATA_RETENTION_TIME_IN_DAYSso Time Travel cannot be switched off on critical data. - Set the unload guardrail parameters and require storage integrations for stages.
- Export ACCOUNT_USAGE login and query data to your SIEM, and alert on logins without a second factor.
- Review Trust Center Threat Intelligence detections daily and route them to the SOC.
- Exercise this playbook once a year with the data platform team, including a service user case.
Standards and references
- Snowflake Documentation: LOGIN_HISTORY view
- Snowflake Documentation: QUERY_HISTORY view
- Snowflake Documentation: ACCESS_HISTORY view
- Snowflake Documentation: Controlling network traffic with network policies
- Snowflake Documentation: ALTER USER
- Snowflake Documentation: Understanding and using Time Travel
- Snowflake Documentation: Trust Center overview
- NIST: SP 800-61 Rev. 3 Incident Response Recommendations and Considerations
Related NHI Mgmt Group resources: Snowflake Security Guide · Service Accounts in Snowflake Guide · Data Exfiltration Playbook · Database Breach Response Playbook · Leaked Credential Response Playbook