A dbt macro or hook can run any SQL that your dbt connection's role is allowed to run. That includes grants, drops and alters if the role permits them. So the real control is the role you give dbt, plus code review on every macro, including those inside installed packages.
Definitions
Macro. A reusable piece of Jinja that generates SQL.
Hook. SQL that dbt runs at set points. The dbt docs list pre-hook and post-hook for models, seeds and snapshots, and on-run-start and on-run-end for whole invocations.
Operation. A macro called directly with the run-operation command. The docs call it a convenient way to invoke a macro without running a model. The macro must explicitly execute its query, for example with run_query, or dbt only returns the SQL as a string.
Why this is a privilege question
The dbt page on hooks does not have a security section. What follows is our reading of how the feature works, not dbt guidance. Hooks and operations go through the same warehouse connection as your models, so their power equals the power of that role.
The docs even show an operation that grants privileges to a role, passed in as an argument. That is a normal use. It also shows that a macro can change access, not only build tables.
Where the risk shows up
| Situation | Risk |
|---|---|
| A package ships an on-run-start hook | Runs on every invocation, with your role |
| A macro builds SQL from an argument | Unvalidated input ends up in SQL text |
| Production uses an admin role | A bad macro can drop or regrant widely |
| Anyone can invoke run-operation | Arbitrary SQL on demand |
Controls that help
- Use a narrow role for dbt in production. It needs to create objects in its own schemas, not own the warehouse. Our post on warehouse role design for analysts covers the shape.
- Review hooks in every package. Search installed packages for hook entries and for grant, drop and alter statements.
- Prefer built in configuration. The docs recommend hooks only when the grants configuration cannot do the job.
- Validate arguments. Allow list the values a macro accepts instead of pasting raw text into SQL.
- Restrict who can run operations in production, and log who did.
- Send changes through code review like any other code.
A quick review recipe for a package
Clone it, search for hook keys in its project file, search the macros folder for execute calls such as run_query, and list anything that touches schemas outside the package's purpose. It takes minutes and answers most of the question.
Quick check
Do hooks run with special privileges?
Not documented as such. They run through your dbt connection, so they have that role's privileges.
Does a model need to exist for a macro to run?
No. The run-operation command invokes a macro directly, as long as the macro executes its SQL.
Safeguard policies and gates can check dependency changes in pull requests, so a new package with an unexpected hook gets a human look. A free scan is at gold.safeguard.sh/scan.
Sources
Last reviewed: 19 October 2026.