Only if everyone who can publish messages to your broker is fully trusted. The Celery security guide says pickle should be avoided whenever clients are untrusted or unauthenticated. JSON has been the default since version 4.0. Set accept_content to a short allow list, and guard the broker as carefully as you would a login server.
What the Celery guide says
Celery's security page covers serializers first. JSON has been the default since 4.0, and supports a limited set of types. Pickle can handle almost any Python object, but it should be avoided whenever clients are untrusted or unauthenticated.
For pipelines this matters because Celery is often the engine behind scheduled and queued data jobs. A worker that deserializes pickle from a queue will run whatever a message contains. So anyone who can write to the queue can reach the worker.
Broker access is the real perimeter
The guide says it is imperative that the broker is guarded from unwanted access, especially if it is public. It advises a firewall in front of the broker that allows only approved machines, but warns not to rely on the firewall alone, since misconfiguration and temporary disabling are common. Where the broker supports fine grained access control, as RabbitMQ does, enable it. Where supported, use broker_use_ssl for end to end encryption and authentication.
Settings that limit what workers accept
| Setting | Effect |
|---|---|
accept_content | An allow list of content types workers will take. For example, only json |
task_serializer | The format used for new task messages |
auth serializer | Public key signing so workers can verify the sender |
app.setup_security() | Configures signing, and per the docs also disables all insecure serializers |
The guide notes that signing does not encrypt. The auth serializer does not hide message contents, so encryption has to be enabled separately.
A simple configuration to aim for
app.conf.task_serializer = "json"
app.conf.accept_content = ["json"]
app.conf.result_serializer = "json"
If you need richer types, convert them yourself at the edge: pass identifiers or file locations in the message, and let the worker fetch the data from storage with its own credentials.
Migration steps
- Find every producer that sends tasks, including old scripts and notebooks.
- Check which serializer each uses today.
- Switch producers to JSON and fix tasks that relied on pickled objects.
- Narrow accept_content on workers once producers are updated.
- Restrict broker network access and turn on its authentication.
- Consider signed messages if several teams share a broker.
Common mistakes
| Mistake | Better practice |
|---|---|
| Leaving the default accept list wide because "it works" | Name only the content types you use |
| Putting the broker on a shared network with no authentication | Require credentials and restrict by address |
| Sharing one broker across teams with different trust levels | Separate brokers, or signed messages and per team access |
| Sending whole dataframes in task arguments | Send a storage location and let the worker fetch it |
A task message is an instruction to run code in your environment. Treat who may send one the way you treat who may log in.
Where Safeguard fits
Safeguard's dependency scanning can show which projects use Celery and which versions, and policies and gates can stop a vulnerable dependency from merging. A free scan gives you the inventory.
Quick check
Is a firewall enough to protect the broker?
The guide says not to rely on it alone, since misconfiguration is common. Add broker authentication and access control.
Does message signing encrypt the task?
No. The auth serializer signs but does not hide contents.
Sources
Last reviewed: 19 October 2026.