Skip to content

Raw SQL Grants

For advanced cases the presets don’t cover — specific tables, REVOKE, ALTER DEFAULT PRIVILEGES, materialized views, foreign servers — a database grant can include a sql field with Go templates that are run during role provisioning. TestIntegration_Proxy_RawSQLPermissions internal/proxy/proxy_integration_test.go:553

{
"databases": {
"myapp": {
"permissions": ["readonly"],
"sql": [
"GRANT INSERT ON public.audit_log TO {{.Role}}",
"GRANT USAGE ON SCHEMA analytics TO {{.Role}}",
"GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO {{.Role}}"
]
}
}
}
VariableValue
{{.Role}}The dynamically created backend role name (e.g. wp_alice_laptop_myapp). Always quote-safe.
{{.Database}}The target database name.
{{.User}}The caller’s Tailscale login (loginName).

Raw SQL is disabled by default server-side via the [provisioning] section:

[provisioning]
allow_raw_sql = false # rejects ACL grants that include `sql`

When false, any grant carrying a sql field is treated as an authorization failure for that connection. Per-listener overrides let you enable raw SQL only on listeners that need it:

[listeners.postgres]
allow_raw_sql = true

See Provisioning & Defaults.

Templates are parsed and validated before execution. Common attack shapes — injection attempts, multi-statement batches, structural malformations, disallowed statement types — are rejected at load time. TestValidateSQL_InjectionAttempts internal/provision/sqlvalidate_test.go:137 TestValidateSQL_RejectedStatementTypes internal/provision/sqlvalidate_test.go:98 TestValidateSQL_Malicious internal/provision/sqlvalidate_test.go:200 Only GRANT, REVOKE, and ALTER DEFAULT PRIVILEGES statements are accepted. TestValidateSQL_Grants internal/provision/sqlvalidate_test.go:8 TestValidateSQL_Revokes internal/provision/sqlvalidate_test.go:49 TestValidateSQL_AlterDefaultPrivileges internal/provision/sqlvalidate_test.go:71

  • Keep raw SQL grants short and idempotent — they run on every connect.
  • Use them to add permissions on top of a preset, not to define the whole grant from scratch.
  • Audit any grant containing sql carefully — it has full backend-side capability subject only to the admin_user’s privileges.
  • If you find yourself templating the same SQL in many grants, prefer a stored procedure on the backend.