GitHub Advisoryadvisory · RubyGems
GHSA-8fq9-273g-6mrg Avo: Missing Authorization in Avo Association Attach Endpoint Allows Unauthorized Relationship Manipulation and Privilege Escalation
CRITICAL
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
References
- https://github.com/avo-hq/avo/security/advisories/GHSA-8fq9-273g-6mrg web
- https://nvd.nist.gov/vuln/detail/CVE-2026-55518 advisory
- https://github.com/avo-hq/avo/pull/4568 web
- https://github.com/avo-hq/avo/commit/995928e586fd1788dd496bd51c4dbe4a79cb2b9c web
- https://github.com/avo-hq/avo package
- https://github.com/avo-hq/avo/releases/tag/v3.32.1 web
- https://github.com/rubysec/ruby-advisory-db/blob/master/gems/avo/CVE-2026-55518.yml web
- https://www.cve.org/CVERecord?id=CVE-2026-55518 web