GitHub Advisoryadvisory · RubyGems

GHSA-8fq9-273g-6mrg Avo: Missing Authorization in Avo Association Attach Endpoint Allows Unauthorized Relationship Manipulation and Privilege Escalation

CRITICAL Published 2026-06-17 Modified 2026-07-18 Official page ↗
Aliases
CVE-2026-55518
Ecosystem
RubyGems
Packages
avo
Severity
Critical
CVSS vector
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N
Weaknesses
CWE-639, CWE-862, CWE-863
Reviewed
2026-06-17

Affected packages

• RubyGems avo: < 3.32.1 → fixed in 3.32.1 • RubyGems avo: >= 4.0.0.beta.1, < 4.0.0.beta.51 → fixed in 4.0.0.beta.51

Description

Summary A critical missing authorization flaw exists in Avo's association attach workflow. The UI and `GET /resources/:resource/:id/:related/new` path can check `attach_?`, but the actual write endpoint, `POST /resources/:resource/:id/:related`, does not run the same authorization check before mutating the association. As a result, an authenticated low-privileged Avo user can bypass hidden/disabled attach controls and directly attach related records to a parent record by sending a crafted POST request. In applications where associations represent teams, tenants, roles, projects, users, memberships, ownership, or other authorization-bearing relationships, this can lead to privilege escalation and cross-tenant data exposure. Details The association attach route writes relationships through `Avo::AssociationsController#create`: ```ruby config/routes.rb post "/:resource_name/:id/:related_name", to: "associations#create", as: "associations_create" ``` The controller registers an attach authorization callback only for `new`, not for `create`: ```ruby app/controllers/avo/associations_controller.rb before_action :set_attachment_record, only: [:create, :destroy] before_action :authorize_index_action, only: :index before_action :authorize_attach_action, only: :new before_action :authorize_detach_action, only: :destroy ``` The `new` action is only the form-rendering step. The actual mutation happens in `create`: ```ruby def create if create_association create_success_action else create_fail_action end end ``` `create_association` then attaches the attacker-supplied related record to the parent: ```ruby def create_association association_name = BaseResource.valid_association_name(@record, association_from_params) perform_action_and_record_errors do if through_reflection? && additional_params.present? new_join_record.save elsif has_many_reflection? || through_reflection? @record.send(association_name) &fields[related_id]=42 ``` Run the attached PoC: ```bash python poc_avo_association_attach_bypass.py \ --base-url http://localhost:3000 \ --avo-root /admin \ --cookie "_app_session=" \ --parent-resource projects \ --parent-id 1 \ --related-name users \ --related-id 42 \ --check-new ``` If `GET /new` is forbidden or redirected but the direct POST succeeds, the authorization bypass is confirmed. To perform the actual attach: ```bash python poc_avo_association_attach_bypass.py \ --base-url http://localhost:3000 \ --avo-root /admin \ --cookie "_app_session=" \ --parent-resource projects \ --parent-id 1 \ --related-name users \ --related-id 42 \ --confirm-attach ``` Expected vulnerable result: • The low-privileged user can attach the related record despite `attach_?` being denied. • The parent record now includes the related record. Impact This vulnerability allows unauthorized relationship manipulation through Avo. Depending on the affected association, the impact can include: • Privilege escalation by attaching a user to an admin group, privileged project, tenant, organization, role, or membership record. • Cross-tenant data exposure when tenant/user/project membership determines record visibility. • Integrity loss by changing ownership, assignment, access-control relationships, or business workflow state. • Policy bypass even when Avo UI controls correctly hide the attach button or deny the attach form. Recommended Fix Enforce attach authorization on the mutating endpoint. At minimum: ```ruby before_action :authorize_attach_action, only: [:new, :create] ``` Additionally: 1. Authorize against the parent record and the selected related record before writing the relationship. 2. Ensure `create` fails closed when `attach_?` is missing and `explicit_authorization` is enabled. 3. Add regression tests that directly POST to `/resources/:resource_name/:id/:related_name` while `attach_?` returns `false`. 4. Verify `has_many`, `has_one`, `has_many :through`, and `has_and_belongs_to_many` association paths all enforce the same server-side authorization.

Related

Alias · CVE (1)

  • CVE-2026-55518 Avo is a framework to create admin panels for Ruby on Rails apps. vulnerability

Weakness · CWE (3)

  • CWE-639 Authorization Bypass Through User-Controlled Key weakness
  • CWE-862 Missing Authorization weakness
  • CWE-863 Incorrect Authorization weakness

References