---
title: Hunt: the 'Frozen Privilege' Postgres chain on databases you run (CREATEROLE self-grants, cron.job edits, LANGUAGE internal, archive_command) | ctxsec
url: https://ctxsec.com/items/hunt-postgres-createrole-pgcron-chain
description: ""
status: "hunt idea"
published: 2026-10-17
---

> 

[← Threat Hunting](/hunting) · [markdown](/items/hunt-postgres-createrole-pgcron-chain.md)

hunt idea

2026-10-17

### Hunt: the 'Frozen Privilege' Postgres chain on databases you run (CREATEROLE self-grants, cron.job edits, LANGUAGE internal, archive_command)

Snowflake fixed its service, but every link in the Varonis chain is standard PostgreSQL behavior, so check self-managed and other managed Postgres you administer. (1) Roles: list non-superusers with CREATEROLE (`SELECT rolname FROM pg_roles WHERE rolcreaterole AND NOT rolsuper;`) and anyone who is a member of pg_write_all_data, pg_read_all_data or pg_read_server_files via `pg_auth_members`. Unexpected grants of those roles are the first link. (2) pg_cron: if installed, review `cron.job` for jobs whose `username` is a superuser but that were created or changed by someone else, and alert on writes to that table from non-admin roles. (3) Backdoors: look for new SECURITY DEFINER functions owned by superusers (`pg_proc.prosecdef`) and any function created with LANGUAGE internal outside an extension. (4) Config: diff `postgresql.auto.conf` and watch `archive_command` (and `archive_library`) for changes. A shell command you didn't set there is code execution. (5) Turn on pgaudit or statement logging for GRANT, CREATE FUNCTION and lo_export, since parts of this chain leave nothing in default logs.

Sources: [Varonis Threat Labs: Frozen Privilege](https://www.varonis.com/blog/remote-code-execution-in-snowflake-managed-postgresql) · [PostgreSQL docs: predefined roles](https://www.postgresql.org/docs/current/predefined-roles.html)
