Safeguard
Security Guides•

What should you pass as Active Job arguments in Rails?

Pass ids or GlobalID records to Active Job, not secrets or raw user data. Learn supported argument types, why payloads persist, and a review checklist.

Safeguard Security Team
3 min read

Pass small, stable values to Active Job: ids, or Active Record objects that Rails turns into GlobalID references. Keep passwords, tokens and large personal data out of arguments, because job payloads are stored in your queue backend and in failure records, often for longer than you expect.

What Active Job accepts

The Active Job guide lists the argument types supported by default: basic types such as nil, strings, integers, floats, big decimals and booleans, plus symbols, dates, times, durations, hashes with string or symbol keys, arrays, ranges, modules and classes. It also supports GlobalID, which lets you pass a live Active Record object. Rails stores a class and id pair and fetches the record when the job runs.

You can add custom types by defining serializers with serialize, deserialize and klass methods.

Why arguments deserve care

Arguments are written into the queue backend. Depending on the adapter, that might be Redis, a database table or a hosted service. They show up in dashboards, retry lists and backups. If the job fails, adapters typically keep the arguments so it can retry.

Passing a record through GlobalID keeps the payload small and means the job sees current data when it runs. Passing a copy of the data means the job may act on stale values and the queue holds a duplicate of whatever was in them.

ArgumentGood practice
Record the job works onPass the record, let GlobalID handle it
Secret or tokenDo not pass it; look it up inside the job
Email body or personal dataPass the id, load at run time
Choice of class or moduleNever from user input
Large blobStore it, pass a reference

The row about classes matters. Active Job allows modules and classes as arguments, so a job that accepts a class name from a request and calls methods on it is dangerous. Map user choices to a fixed list on your side.

A review checklist

  1. Read each job's perform signature.
  2. Ask what a stranger with read access to the queue could learn.
  3. Replace secrets with lookups inside the job.
  4. Replace copied data with ids.
  5. Check how failures are stored and who can open them.
  6. Think about deleted records: a job holding a GlobalID for a record that no longer exists will fail when it tries to load it, so decide how to handle that.
  7. Make sure jobs check authorization when they run, since the user who enqueued them may have lost access by then.

Retries and idempotence

A job that can run twice should be safe to run twice. Charging a card or sending a message needs a guard. That is a reliability point with a security edge, because duplicated actions can be abused.

Quick check

Can I pass an Active Record object to perform_later?

Yes. Active Job supports GlobalID, so Rails serializes a class and id pair and reloads the record when the job runs.

Is the queue private by default?

Treat it as sensitive. Anyone with access to the backend or its dashboard can read stored arguments.

Safeguard's SBOM and dependency scanning cover the gems your job backends rely on, with policy gates on pull requests. A free scan is at gold.safeguard.sh/scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.