activerecord-safer-query

activerecord-safer-query is a small static checker for Rails applications. It looks for class-level ActiveRecord lookups that may bypass tenant, organization, or user scopes.

This is an audit tool, not a proof engine. Findings should be reviewed by a human before treating them as vulnerabilities.

Usage

Run it from the target Rails repository:

exe/activerecord-safer-query
exe/activerecord-safer-query app/graphql app/controllers
exe/activerecord-safer-query --root /path/to/rails-app app/graphql
exe/activerecord-safer-query --fail-level HIGH app/graphql
exe/activerecord-safer-query --format json app/controllers/organizations

When installed as a gem, run:

gem install activerecord-safer-query
activerecord-safer-query app/graphql app/controllers

Rules

  • GLOBAL_FIND_EXTERNAL_INPUT: class-level find / find_by with params, GraphQL input, args, session, cookies, headers, or request data.
  • GLOBAL_FIND_ID_VARIABLE: class-level find with a local id, *_id, *_ids, *_uuid, *_slug, or *_code variable.
  • GLOBAL_WHERE_EXTERNAL_IDS: class-level where(id: ...) with external input.
  • GLOBAL_NATURAL_KEY_LOOKUP: class-level lookup by email, uid, issuer, code, subdomain, slug, token, or similar natural keys.
  • UNSCOPED_DESTRUCTIVE_IDS: destructive operations driven by external/global IDs.
  • WITHOUT_TENANT_BOUNDARY: boundary code that calls ActsAsTenant.without_tenant.
  • DRAFT_COURSE_EXPOSURE: draft/closed course scopes in public-ish Rails boundaries.

Suppress a known-safe finding with:

Course.find(params[:id]) # active_record_safer_query: ignore

Development

bundle install
bundle exec rake

License

MIT.