π Home | πΎ Dump | π Restore | βοΈ How it works | π¬ FAQ
pg_anon masks the table data you select, but a dump also carries schema objects that can leak secrets or personal data by themselves β foreign-server credentials, function bodies, planner statistics. This page explains what pg_anon handles by default, what it only warns about, and how to clean a dump yourself. For the limits of masking itself, see Security & limitations in the README.
Besides table data, a dump carries schema objects. Some can hold credentials or personal data that masking does not change. pg_anon removes what it safely can without breaking the restore, warns about the rest, and leaves the final call to you.
| Object | Risk | pg_anon default | What you can do |
|---|---|---|---|
FDW user mapping (USER MAPPING) |
Remote-server user/password | Dump blocked when credentials are visible; mappings stripped on restore | --allow-fdw-credentials / --keep-fdw-user-mappings |
FDW server (SERVER OPTIONS) |
Internal host/port addresses | Warned at dump time; kept in the dump | Strip manually β see Maximum cleanup |
| Subscriptions | Publisher password in CONNECTION string |
Excluded via pg_dump --no-subscriptions (pg_dump β₯ 10) |
β |
| Planner statistics (PG 18+) | Real (unmasked) column values | Excluded via pg_dump --no-statistics (pg_dump β₯ 18) |
β |
| Function / procedure / trigger bodies | Hard-coded secrets or personal data | Warned at dump time; restored as-is | Review bodies; exclude their schema if needed |
pg_anon does not inspect other objects β security labels, GUC settings (ALTER ROLE/DATABASE ... SET), comments, or extension table data. If any of them may hold
secrets, review them yourself: exclude suspicious schemas with
--exclude-schema-name, and restore the dump
structure onto a throwaway instance to check what it contains before you share it.
β οΈ An excluded schema can still appear on the targetIf an extension lives in that schema,
pg_anoncreates the schema on the target to install the extension. It stays empty, so nothing leaks β see Extensions.
FDW CREATE USER MAPPING statements must carry OPTIONS (for oracle_fdw, a user and
usually a password). What ends up in the dump depends on whether the dumping role can
see those options:
| Dumping role | In the dump | Restore | Side effect |
|---|---|---|---|
| superuser / mapping owner | USER MAPPING ... OPTIONS (user 'β¦', password 'β¦') |
works | remote-server credentials leak into the dump |
| unprivileged | USER MAPPING ... ; (no OPTIONS) |
fails with missing required option "user" |
no credentials, but the restore breaks |
This is pg_dump behavior, not a pg_anon bug β pg_anon inherits it. Its defaults cover both
cases:
At dump time β block credential leaks. If any FDW user mapping exposes OPTIONS visible
to the dumping role, the dump is refused (error CREDENTIALS_LEAK): pg_dump would
otherwise write the remote credentials into the archive. Two ways forward:
- Dump with a less-privileged role that owns the foreign server (so the dump stays
self-contained, keeping
CREATE SERVER) but cannot read the mappingOPTIONS. The minimal grants for such a role:USAGEon the dumped schemas,SELECTon their tables and sequences, andUSAGE+EXECUTEon theanon_funcsschema afterinit. - Or pass
--allow-fdw-credentialsto include them intentionally (an informed decision; the dump logs a warning that credentials are inside).
Independently, whenever a foreign server exists pg_anon warns that its SERVER OPTIONS
(remote host/port of your infrastructure) go into the dump. Those are not stripped
automatically β removing a SERVER would break the FOREIGN TABLEs that depend on it.
Strip them manually if they matter (Maximum cleanup).
At restore time β strip mappings. By default pg_anon removes USER MAPPING entries from
the restore. This fixes the unprivileged-dump failure automatically, and it also means that
even a dump taken with --allow-fdw-credentials does not recreate the credentials in the
target. Pass --keep-fdw-user-mappings to restore them (a mapping without OPTIONS
still fails on wrappers that require them β that is the original pg_dump behavior).
Foreign servers (SERVER) and foreign tables (FOREIGN TABLE) are always kept, so querying
a foreign table in the restored copy needs its mapping recreated by hand (or a restore with
--keep-fdw-user-mappings).
To fully remove infrastructure objects and keep the dump reliable, do it by hand:
pg_anon dumpβ a full dump.pg_anon sync-struct-restoreβ restore only the structure into a throwaway database.- Clean the throwaway database: drop FDW objects, functions, triggers, extensions, GUC settings β anything that must not be shared.
pg_anon sync-struct-dumpβ dump the cleaned structure.- Replace
pre_data.backup/post_data.backupin the original dump with the cleaned ones.
This cannot be automated in general (the objects are not known in advance), but it can be scripted in CI/CD for a specific database.