Researchers Detail Privilege-Escalation Chain to RCE in Snowflake-Managed PostgreSQL

Summary
Varonis researchers chained PostgreSQL features to turn a CREATEROLE role into OS-level RCE on Snowflake-managed instances. Snowflake remediated the issue server-side before publication; customers need take no action.
Key points
- The chain began with the non-superuser snowflake_admin role, which had CREATEROLE and could grant itself PostgreSQL data-access roles.
- Researchers used write access to pg_cron jobs to run SQL as postgres, gain superuser privileges, and create a SECURITY DEFINER backdoor.
- They rebound blocked file-access functions using LANGUAGE internal, then used large-object file writes to alter postgresql.auto.conf and trigger commands through archive_command.
- The demonstrated access reached OS-level command execution as the postgres user, enabling potential file tampering, recovery disruption, and concealment from database-level audit trails.
- Varonis reported the chain to Snowflake in May 2026; Snowflake confirmed the security-boundary issue and remediated it server-side before publication.
- Snowflake customers require no further action. The article advises limiting CREATEROLE, monitoring privilege grants and pg_cron jobs, and applying least privilege to PostgreSQL roles.
Article Details
- Attack Vectors
- A role with CREATEROLE self-grants pg_read_all_data and pg_write_all_data, then writes to the pg_cron job table to run SQL as postgres and create a SECURITY DEFINER backdoor.
- As superuser, LANGUAGE internal bindings expose blocked PostgreSQL file-read functions; lo_export provides arbitrary file writes as the postgres OS user.
- Overwriting postgresql.auto.conf sets archive_command to execute a shell payload through /bin/sh -c during WAL archiving, resulting in OS-level code execution.
- An alternative execution path uses a custom C extension written on the host, loaded via LANGUAGE c, to register a SQL-callable shell function.
- Defensive Notes
- Snowflake remediated the issue server-side before publication; Snowflake customers do not need to take further action.
- Avoid granting CREATEROLE to application or service-account roles; use dedicated least-privilege roles and scope access to operational needs.
- Constrain pg_cron so job usernames cannot be changed to high-privilege roles, and periodically review cron jobs and SECURITY DEFINER functions.
- Restrict creation of LANGUAGE internal and LANGUAGE c functions to trusted platform roles; hiding blocked function names does not remove underlying capabilities.
- Protect postgresql.auto.conf and the data directory from writes through lo_export; review archive_command configuration.
- Use short-lived Snowflake-issued tokens, enable network policies, and prefer private connectivity such as AWS PrivateLink or Azure Private Link.
- For self-managed PostgreSQL, confine the postgres process with SELinux, disable unused extensions, and avoid exposing PostgreSQL ports publicly.