pg_snakeoil

The PostgreSQL Antivirus

Overview

PackageVersionCategoryLicenseLanguage
pg_snakeoil1.4SECPostgreSQLC
IDExtensionBinLibLoadCreateTrustRelocSchema
7380pg_snakeoilNoYesYesYesNoYes-
Relatedpg_crash pg_cheat_funcs pg_dirtyread pg_savior pg_surgery pageinspect pg_catcheck amcheck

require clamV libs

Version

TypeRepoVersionPG VerPackageDeps
EXTMIXED1.41817161514pg_snakeoil-
RPMPIGSTY1.41817161514pg_snakeoil_$v-
DEBPGDG1.41817161514postgresql-$v-snakeoil-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64
d12.aarch64
d13.x86_64
d13.aarch64
u22.x86_64
u22.aarch64
u24.x86_64
u24.aarch64
u26.x86_64
u26.aarch64

Build

You can build the RPM packages for pg_snakeoil using pig build:

pig build pkg pg_snakeoil         # build RPM packages

Install

You can install pg_snakeoil directly. First, make sure the PGDG and PIGSTY repositories are added and enabled:

pig repo add pgsql -u          # Add repo and update cache

Install the extension using pig or apt/yum/dnf:

pig install pg_snakeoil;          # Install for current active PG version
pig ext install -y pg_snakeoil -v 18  # PG 18
pig ext install -y pg_snakeoil -v 17  # PG 17
pig ext install -y pg_snakeoil -v 16  # PG 16
pig ext install -y pg_snakeoil -v 15  # PG 15
pig ext install -y pg_snakeoil -v 14  # PG 14
dnf install -y pg_snakeoil_18       # PG 18
dnf install -y pg_snakeoil_17       # PG 17
dnf install -y pg_snakeoil_16       # PG 16
dnf install -y pg_snakeoil_15       # PG 15
dnf install -y pg_snakeoil_14       # PG 14
apt install -y postgresql-18-snakeoil   # PG 18
apt install -y postgresql-17-snakeoil   # PG 17
apt install -y postgresql-16-snakeoil   # PG 16
apt install -y postgresql-15-snakeoil   # PG 15
apt install -y postgresql-14-snakeoil   # PG 14

Preload:

shared_preload_libraries = 'pg_snakeoil';

Create Extension:

CREATE EXTENSION pg_snakeoil;

Usage

pg_snakeoil: ClamAV antivirus scanning for PostgreSQL data

pg_snakeoil provides ClamAV virus scanning of data stored in PostgreSQL without interfering with normal database operations.

CREATE EXTENSION pg_snakeoil;

Functions

FunctionReturnsDescription
so_is_infected(text)boolCheck if text data matches a virus signature
so_is_infected(bytea)boolCheck if bytea data matches a virus signature
so_virus_name(text)textReturn virus name if infected, empty string otherwise
so_virus_name(bytea)textReturn virus name if infected, NULL otherwise
so_update_signatures()boolReload virus signatures, true if changed

Ad-hoc Scanning

SELECT so_is_infected('Not a virus!');
-- f

SELECT so_is_infected('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
-- t

SELECT so_virus_name('X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*');
-- Eicar-Test-Signature

On-Access Protection with Domains

CREATE DOMAIN safe_text AS text CHECK (NOT so_is_infected(value));
CREATE TABLE t1 (safe safe_text);

INSERT INTO t1 VALUES ('This text is safe!');
-- INSERT

INSERT INTO t1 VALUES('X5O!P%@AP...');
-- NOTICE: Virus found: Eicar-Test-Signature
-- ERROR: value for domain safe_text violates check constraint "safe_text_check"

On-Access Protection with Triggers

CREATE OR REPLACE FUNCTION check_virus() RETURNS trigger AS $$
BEGIN
    IF so_is_infected(NEW.content) THEN
        RAISE EXCEPTION 'Virus detected: %', so_virus_name(NEW.content);
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER virus_check BEFORE INSERT OR UPDATE ON uploads
    FOR EACH ROW EXECUTE FUNCTION check_virus();

Last Modified 2026-07-23: update extension list to 555 (d81fc56)