CVE-2026-53769: Avo Direct Attachment Upload Endpoint Lacks Vulnerability

MODERATE
Advisory Identifier: GHSA-pqpw-cvm4-8mv9
CVSS 6.5
CWE-862 CWE-863
Published
Advisory Summary

CVE-2026-53769 is a MODERATE (CVSS 6.5) direct attachment upload endpoint lacks vulnerability (CWE-862: Missing Authorization) affecting Avo libraries in the RubyGems ecosystem. The issue involves direct attachment upload endpoint lacks upload authorization and bypasses field-level upload policy. Remediation is available by upgrading affected packages to version 3.32.0.

CVE-2026-53769 at a Glance

CVE Identifier CVE-2026-53769
GHSA Identifier GHSA-pqpw-cvm4-8mv9
Severity MODERATE
CVSS v3.1 Base Score 6.5
CWE Classification CWE-862: Missing Authorization
Affected Product Avo
Package Ecosystem RubyGems
Published Date
Last Updated

Security Impact

CVSS: 6.5

The security impact metrics below are parsed directly from the CVSS v3.1 vector string (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N).

Attack Vector Network (AV:N)
Attack Complexity Low (AC:L)
Privileges Required Low (PR:L)
User Interaction None (UI:N)
Scope Unchanged (S:U)
Confidentiality None (C:N)
Integrity High (I:H)
Availability None (A:N)

How to Fix CVE-2026-53769

To remediate this vulnerability, upgrade all affected Avo dependencies to a patched release. Both direct and transitive dependencies should be checked, as frameworks or security libraries may pull in vulnerable versions transitively.

avo fixed: 3.32.0
Upgrade avo to 3.32.0
Verify Direct and Transitive Dependencies

Run the following command in your project directory to verify that all resolved dependencies use the patched release:

inspect dependencies for avo

How to Check if You Are Affected

To determine whether your application is affected by CVE-2026-53769, inspect your project dependencies for Avo:

inspect dependencies for avo

Analyze the terminal output to locate any version of Avo in your dependency tree. If any resolved version matches the vulnerable ranges listed in the table below (for example, versions earlier than 3.32.0), your application is affected.

Note: Verify declared build manifests and deployed runtime container environments.

Technical Details

Vulnerability Mechanism & Technical Analysis

This vulnerability is classified under CWE-862: Missing Authorization, where the product does not perform an authorization check when an actor attempts to access a resource or perform an action. In Avo, software state validation or input boundaries are circumvented during processing. Review the official source advisory statement below for specific affected components, classes, and reproduction details.

Source Advisory Statement

### Summary Avo's direct attachment upload endpoint lacks server-side upload authorization and bypasses the documented field-level upload policy methods such as `upload_{FIELD_ID}?`. An authenticated Avo user who can reach the Avo attachment upload endpoint can replace or add attachment content, including binary content, filename, and content-type metadata, on a resolved record even when both `update?` and `upload_<field>?` policies deny the operation. This primarily affects multi-role Avo Pro/Advanced-style deployments where non-administrator or restricted operator users can reach Avo and per-record or per-field operations are expected to be enforced by policies. ### Details Avo exposes a direct attachment upload endpoint: ```text POST /<avo-root>/avo_api/resources/:resource_name/:id/attachments/ ``` The vulnerable code path is `Avo::AttachmentsController#create`: - `app/controllers/avo/attachments_controller.rb:9-24` Current behavior: ```ruby def create blob = ActiveStorage::Blob.create_and_upload! io: params[:file].to_io, filename: params[:filename] association_name = BaseResource.valid_attachment_name(@record, params[:attachment_key]) if association_name @record.send(association_name).attach blob elsif params[:key].blank? raise ActionController::BadRequest.new(...) end render json: { url: main_app.url_for(blob), href: main_app.url_for(blob) } end ``` This endpoint creates an `ActiveStorage::Blob` before validating the requested attachment association and before any upload authorization could be enforced. If `attachment_key` resolves to an association, the blob is attached to the target record. If the request uses the key-based/Trix path, the endpoint can still persist the blob and return `url`/`href` even when no attachment association is resolved on the target record. The controller never calls: - `@resource.authorization.authorize_action("upload_<field>?", record: @record, ...)` - `@resource.authorization.authorize_action("update?", record: @record, ...)` This is inconsistent with the rest of Avo's file authorization implementation. The field-level file authorization concern defines upload authorization as: - `lib/avo/fields/concerns/file_authorization.rb:11-12` - `lib/avo/fields/concerns/file_authorization.rb:25-27` ```ruby def can_upload_file? authorize_file_action(:upload) end def authorize_file_action(action) authorize_action("#{action}_#{id}?", record: record, raise_exception: false) end ``` That upload policy is used by UI components to decide whether to render upload controls, but the server-side upload endpoint does not enforce the same policy. A user can therefore bypass the policy by directly POSTing to the endpoint. By contrast, attachment deletion does call attachment-specific authorization: - `app/controllers/avo/attachments_controller.rb:27-65` ```ruby def destroy if authorized_to :delete ... end end def authorized_to(action) @resource.authorization.authorize_action("#{action}_#{params[:attachment_name]}?", record: @record, raise_exception: false) end ``` The asymmetry is: - `destroy`: calls `delete_<attachment_name>?` - `create`: does not call `upload_<attachment_key>?` or `update?` The field-level upload authorization intent is also documented by Avo: - Issue #1624 requested the "Ability to police each file upload/download/delete". https://github.com/avo-hq/avo/issues/1624 - PR #1625 introduced `upload_cover_photo?` as an example upload policy method. https://github.com/avo-hq/avo/pull/1625 - PR #1667 clarified the policy semantics: "From now on, only field level authorization will be considered. If it is defined and returns true, the action will be granted; otherwise, it will not." https://github.com/avo-hq/avo/pull/1667 - The current Avo authorization documentation lists `upload_{FIELD_ID}?` as the policy method controlling whether a user can upload an attachment, stating: "Controls whether the user can upload the attachment." https://docs.avohq.io/4.0/authorization.html - The same documentation says the same `upload_file?` policy method will be used to "authorize the file upload" in action file fields. https://docs.avohq.io/4.0/authorization.html Affected versions observed: - PoC-confirmed: Avo `3.31.2`, commit `46aa6b3bc9e3283110c39e58cfec8bb95adc1897` - Same vulnerable code path by source inspection: `origin/main` HEAD as of 2026-05-29, `9e23ddc88f2b1e762e4a5ec35a6f86370ac16c73` - Same vulnerable code path by source inspection: Avo `v4.0.0.beta.26`, `6d339595a27f8779cb99b4aa38ddc97cb702b30f` - Same vulnerable code path by source inspection: `origin/4-dev` at version `4.0.0.beta.40`, `7ab9794f8b044b11b9677cdc57547d99cf96c3f3` Suggested affected range for the GitHub Security Advisory form: ```text >= 2.28.0 ``` Rationale: - The direct attachment upload endpoint exists without upload authorization from commit `ab5f5970e2aa76e6ca0a95bf04f510ba7ed5e858` (`feature: trix attachments`, 2021-04-24), first included in tag `v1.4.0`. - The documented field-level upload policy bypass is confirmed from commit `667049ceeda838394214489693d088708d9da77d` (`feature: field level file authorization`, 2023-03-12), first included in tag `v2.28.0`. - PR #1667 later clarified the field-level-only grant/deny semantics in commit `31b6ef94f8cc4c340a2a75eec36c838cda933ce7`, first included in tag `v2.30.1`. From a narrow missing-authorization perspective, the issue exists from `v1.4.0`; the `>= 2.28.0` range is a conservative submission range anchored to the documented field-level upload policy boundary. Fixed version: to be determined by maintainers. ### PoC A local request spec was used to reproduce the issue. The PoC adds `pundit` to the test group and replaces `Avo::Services::AuthorizationService` with a test double. The test double records every `authorize_action` invocation and, when invoked, delegates the decision to a `PostPolicy` resolved via `Pundit.policy!`. The policy setup is: - `PostPolicy#update?` returns `false` - `PostPolicy#upload_attachments?` returns `false` - `PostPolicy#upload_cover_photo?` returns `false` - `PostPolicy#method_missing` returns `true` for all other policy methods ending in `?`, simulating a user with general read access but explicit update/upload denial - the replacement authorization service records all `authorize_action` calls The open-source repository does not include Avo Pro's authorization client. The critical observation is independent of which client is plugged in: the vulnerable endpoint never invokes `authorize_action` at all, so the call list remains empty. The PoC user has `roles: {admin: true}`, which is required only to pass the dummy app's coarse route-level guard: ```ruby authenticate :user, ->(user) { user.is_admin? } ``` The vulnerability under test is one layer below that guard: the fine-grained record/field authorization that Avo Pro/Pundit deployments would normally enforce. The dummy route gate is not part of Avo's upload policy decision. In a deployment where non-admin operators reach Avo through a different authentication rule, `AttachmentsController#create` would still skip `authorize_action` for the upload. Policy scoping is orthogonal to this finding. Even if `apply_policy` filtered the record set during lookup, `AttachmentsController#create` would still not authorize the upload action itself for records that survive the scope. The spec demonstrates: 1. Normal record update is denied by policy and does not persist changes. 2. Direct upload with `attachment_key=cover_photo` succeeds even though `PostPolicy#upload_cover_photo?` returns `false`, replacing the existing `has_one_attached` `cover_photo` blob. 3. Direct upload with `attachment_key=attachments` succeeds even though `PostPolicy#upload_attachments?` returns `false`, adding to a `has_many_attached` association. 4. Direct upload with `params[:key]` and no attachment association succeeds, creates an `ActiveStorage::Blob`, and returns `url`/`href` without attaching the blob to the record. 5. The direct upload requests do not invoke the replacement authorization service at all. The full request-spec patch can be provided in this advisory thread if useful. Verification environment: - Ruby `3.3.1` - Avo `3.31.2` - Commit `46aa6b3bc9e3283110c39e58cfec8bb95adc1897` ### Impact This is a missing server-side authorization vulnerability in Avo's direct attachment upload endpoint. The primary affected deployments are Avo Pro/Advanced-style multi-role deployments where non-administrator or restricted operator users can reach Avo, and per-record/per-field operations are expected to be enforced by policies. In such deployments, an authenticated Avo user can add or replace attachment content on a resolved record even when the host application policy denies both: - record update, for example `update?` - field-level upload, for example `upload_cover_photo?` or `upload_attachments?` For `has_one_attached` fields, the demonstrated impact is replacement of a protected attachment field with attacker-controlled content. The attacker controls the uploaded binary content, filename, and content-type metadata for the reachable field. For key-based/Trix upload flows, the endpoint can persist a blob and return a URL even when no attachment association is resolved. This means the endpoint should not be left as an unauthenticated blob creation and URL return path for authenticated Avo users. In admin-only deployments following the Avo Community pattern, practical exposure is much lower because the only users who can reach the endpoint are already trusted to perform record updates through the normal CRUD path. Suggested fix direction: - validate the requested `attachment_key` before any blob is stored - perform upload authorization before `ActiveStorage::Blob.create_and_upload!` - derive the policy method from the validated association name rather than raw request input - apply an equivalent authorization decision to supported `params[:key]` / Trix upload flows before blob creation or URL return - return a JSON-compatible `403 Forbidden` response when upload authorization is denied The default `Avo::Services::AuthorizationService#authorize_action` returns `true` in `lib/avo/services/authorization_service.rb:34-35`, so applications without a custom authorization client should not see a behavior change from adding an authorization call. Deployments with custom/Pro authorization clients that explicitly deny upload would gain enforcement at this endpoint. No official Avo-level workaround was confirmed in this review. Until a fix is available, applications can reduce exposure by ensuring only fully trusted administrators can access Avo routes. Applications needing an immediate mitigation may override or monkey-patch `Avo::AttachmentsController#create` to authorize uploads before blob creation. Any mitigation should be tested against the application's Avo authorization client and upload UI, because the endpoint is used by Trix/file upload flows. If a mitigation falls back to `update?` for key-based/Trix uploads, that is a conservative behavior change for applications that currently allow read-only operators to use those uploads; those deployments should replace the fallback with an explicit rich-text upload policy.

CVE-2026-53769 Affected Avo Versions

1 component(s)
Fixed Versions:
3.32.0
Product / Package Ecosystem Affected Versions Fixed Version
avo
RubyGems
≥ 2.28.0
< 3.32.0
3.32.0

References

Frequently Asked Questions

What is CVE-2026-53769?
CVE-2026-53769 is a security vulnerability in Avo involving Direct attachment upload endpoint lacks upload authorization and bypasses field-level upload policy under CWE-862: Missing Authorization.
Which Avo versions are affected?
Affected versions include releases prior to 3.32.0 across affected packages: avo.
What version fixes CVE-2026-53769?
Upgrading to 3.32.0 (or the latest patched release for your respective branch) resolves the vulnerability.
Is avo affected?
Yes, avo is affected in releases prior to 3.32.0. Upgrade your dependency to 3.32.0 or later.
What is the CVSS score of CVE-2026-53769?
CVE-2026-53769 has a CVSS v3.1 base score of 6.5 (MODERATE) with vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N.
What CWE is associated with CVE-2026-53769?
CVE-2026-53769 is classified under CWE-862: Missing Authorization (The product does not perform an authorization check when an actor attempts to access a resource or perform an action.).
How can I check RubyGems dependencies for CVE-2026-53769?
Run the dependency tree command: 'inspect dependencies for avo'. This command lists direct and transitive dependencies in your build configuration so you can verify if a vulnerable version is resolved.
Machine-readable OSV JSON OSV v1.5 Schema
Normalized schema output
{
  "schema_version" : "1.4.0",
  "id" : "GHSA-pqpw-cvm4-8mv9",
  "modified" : "2026-07-09T20:54:10Z",
  "published" : "2026-07-09T20:54:10Z",
  "aliases" : [ "CVE-2026-53769" ],
  "summary" : "Avo: Direct attachment upload endpoint lacks upload authorization and bypasses field-level upload policy",
  "details" : "### Summary\n\nAvo's direct attachment upload endpoint lacks server-side upload authorization and bypasses the documented field-level upload policy methods such as `upload_{FIELD_ID}?`.\n\nAn authenticated Avo user who can reach the Avo attachment upload endpoint can replace or add attachment content, including binary content, filename, and content-type metadata, on a resolved record even when both `update?` and `upload_<field>?` policies deny the operation.\n\nThis primarily affects multi-role Avo Pro/Advanced-style deployments where non-administrator or restricted operator users can reach Avo and per-record or per-field operations are expected to be enforced by policies.\n\n### Details\n\nAvo exposes a direct attachment upload endpoint:\n\n```text\nPOST /<avo-root>/avo_api/resources/:resource_name/:id/attachments/\n```\n\nThe vulnerable code path is `Avo::AttachmentsController#create`:\n\n- `app/controllers/avo/attachments_controller.rb:9-24`\n\nCurrent behavior:\n\n```ruby\ndef create\n  blob = ActiveStorage::Blob.create_and_upload! io: params[:file].to_io, filename: params[:filename]\n  association_name = BaseResource.valid_attachment_name(@record, params[:attachment_key])\n\n  if association_name\n    @record.send(association_name).attach blob\n  elsif params[:key].blank?\n    raise ActionController::BadRequest.new(...)\n  end\n\n  render json: {\n    url: main_app.url_for(blob),\n    href: main_app.url_for(blob)\n  }\nend\n```\n\nThis endpoint creates an `ActiveStorage::Blob` before validating the requested attachment association and before any upload authorization could be enforced. If `attachment_key` resolves to an association, the blob is attached to the target record. If the request uses the key-based/Trix path, the endpoint can still persist the blob and return `url`/`href` even when no attachment association is resolved on the target record.\n\nThe controller never calls:\n\n- `@resource.authorization.authorize_action(\"upload_<field>?\", record: @record, ...)`\n- `@resource.authorization.authorize_action(\"update?\", record: @record, ...)`\n\nThis is inconsistent with the rest of Avo's file authorization implementation. The field-level file authorization concern defines upload authorization as:\n\n- `lib/avo/fields/concerns/file_authorization.rb:11-12`\n- `lib/avo/fields/concerns/file_authorization.rb:25-27`\n\n```ruby\ndef can_upload_file?\n  authorize_file_action(:upload)\nend\n\ndef authorize_file_action(action)\n  authorize_action(\"#{action}_#{id}?\", record: record, raise_exception: false)\nend\n```\n\nThat upload policy is used by UI components to decide whether to render upload controls, but the server-side upload endpoint does not enforce the same policy. A user can therefore bypass the policy by directly POSTing to the endpoint.\n\nBy contrast, attachment deletion does call attachment-specific authorization:\n\n- `app/controllers/avo/attachments_controller.rb:27-65`\n\n```ruby\ndef destroy\n  if authorized_to :delete\n    ...\n  end\nend\n\ndef authorized_to(action)\n  @resource.authorization.authorize_action(\"#{action}_#{params[:attachment_name]}?\", record: @record, raise_exception: false)\nend\n```\n\nThe asymmetry is:\n\n- `destroy`: calls `delete_<attachment_name>?`\n- `create`: does not call `upload_<attachment_key>?` or `update?`\n\nThe field-level upload authorization intent is also documented by Avo:\n\n- Issue #1624 requested the \"Ability to police each file upload/download/delete\".\n  https://github.com/avo-hq/avo/issues/1624\n- PR #1625 introduced `upload_cover_photo?` as an example upload policy method.\n  https://github.com/avo-hq/avo/pull/1625\n- PR #1667 clarified the policy semantics: \"From now on, only field level\n  authorization will be considered. If it is defined and returns true, the\n  action will be granted; otherwise, it will not.\"\n  https://github.com/avo-hq/avo/pull/1667\n- The current Avo authorization documentation lists `upload_{FIELD_ID}?` as the\n  policy method controlling whether a user can upload an attachment, stating:\n  \"Controls whether the user can upload the attachment.\"\n  https://docs.avohq.io/4.0/authorization.html\n- The same documentation says the same `upload_file?` policy method will be used\n  to \"authorize the file upload\" in action file fields.\n  https://docs.avohq.io/4.0/authorization.html\n\nAffected versions observed:\n\n- PoC-confirmed: Avo `3.31.2`, commit\n  `46aa6b3bc9e3283110c39e58cfec8bb95adc1897`\n- Same vulnerable code path by source inspection: `origin/main` HEAD as of\n  2026-05-29,\n  `9e23ddc88f2b1e762e4a5ec35a6f86370ac16c73`\n- Same vulnerable code path by source inspection: Avo `v4.0.0.beta.26`,\n  `6d339595a27f8779cb99b4aa38ddc97cb702b30f`\n- Same vulnerable code path by source inspection: `origin/4-dev` at version\n  `4.0.0.beta.40`,\n  `7ab9794f8b044b11b9677cdc57547d99cf96c3f3`\n\nSuggested affected range for the GitHub Security Advisory form:\n\n```text\n>= 2.28.0\n```\n\nRationale:\n\n- The direct attachment upload endpoint exists without upload authorization from\n  commit `ab5f5970e2aa76e6ca0a95bf04f510ba7ed5e858` (`feature: trix\n  attachments`, 2021-04-24), first included in tag `v1.4.0`.\n- The documented field-level upload policy bypass is confirmed from commit\n  `667049ceeda838394214489693d088708d9da77d` (`feature: field level file\n  authorization`, 2023-03-12), first included in tag `v2.28.0`.\n- PR #1667 later clarified the field-level-only grant/deny semantics in commit\n  `31b6ef94f8cc4c340a2a75eec36c838cda933ce7`, first included in tag\n  `v2.30.1`.\n\nFrom a narrow missing-authorization perspective, the issue exists from\n`v1.4.0`; the `>= 2.28.0` range is a conservative submission range anchored to\nthe documented field-level upload policy boundary.\n\nFixed version: to be determined by maintainers.\n\n### PoC\n\nA local request spec was used to reproduce the issue. The PoC adds `pundit` to\nthe test group and replaces\n`Avo::Services::AuthorizationService` with a test double. The test double\nrecords every `authorize_action` invocation and, when invoked, delegates the\ndecision to a `PostPolicy` resolved via `Pundit.policy!`.\n\nThe policy setup is:\n\n- `PostPolicy#update?` returns `false`\n- `PostPolicy#upload_attachments?` returns `false`\n- `PostPolicy#upload_cover_photo?` returns `false`\n- `PostPolicy#method_missing` returns `true` for all other policy methods ending\n  in `?`, simulating a user with general read access but explicit update/upload\n  denial\n- the replacement authorization service records all `authorize_action` calls\n\nThe open-source repository does not include Avo Pro's authorization client. The\ncritical observation is independent of which client is plugged in: the vulnerable\nendpoint never invokes `authorize_action` at all, so the call list remains empty.\n\nThe PoC user has `roles: {admin: true}`, which is required only to pass the\ndummy app's coarse route-level guard:\n\n```ruby\nauthenticate :user, ->(user) { user.is_admin? }\n```\n\nThe vulnerability under test is one layer below that guard: the fine-grained\nrecord/field authorization that Avo Pro/Pundit deployments would normally\nenforce. The dummy route gate is not part of Avo's upload policy decision. In a\ndeployment where non-admin operators reach Avo through a different\nauthentication rule, `AttachmentsController#create` would still skip\n`authorize_action` for the upload.\n\nPolicy scoping is orthogonal to this finding. Even if `apply_policy` filtered\nthe record set during lookup, `AttachmentsController#create` would still not\nauthorize the upload action itself for records that survive the scope.\n\nThe spec demonstrates:\n\n1. Normal record update is denied by policy and does not persist changes.\n2. Direct upload with `attachment_key=cover_photo` succeeds even though\n   `PostPolicy#upload_cover_photo?` returns `false`, replacing the existing\n   `has_one_attached` `cover_photo` blob.\n3. Direct upload with `attachment_key=attachments` succeeds even though\n   `PostPolicy#upload_attachments?` returns `false`, adding to a\n   `has_many_attached` association.\n4. Direct upload with `params[:key]` and no attachment association succeeds,\n   creates an `ActiveStorage::Blob`, and returns `url`/`href` without attaching\n   the blob to the record.\n5. The direct upload requests do not invoke the replacement authorization\n   service at all.\n\nThe full request-spec patch can be provided in this advisory thread if useful.\n\nVerification environment:\n\n- Ruby `3.3.1`\n- Avo `3.31.2`\n- Commit `46aa6b3bc9e3283110c39e58cfec8bb95adc1897`\n\n### Impact\n\nThis is a missing server-side authorization vulnerability in Avo's direct\nattachment upload endpoint.\n\nThe primary affected deployments are Avo Pro/Advanced-style multi-role\ndeployments where non-administrator or restricted operator users can reach Avo,\nand per-record/per-field operations are expected to be enforced by policies.\n\nIn such deployments, an authenticated Avo user can add or replace attachment\ncontent on a resolved record even when the host application policy denies both:\n\n- record update, for example `update?`\n- field-level upload, for example `upload_cover_photo?` or\n  `upload_attachments?`\n\nFor `has_one_attached` fields, the demonstrated impact is replacement of a\nprotected attachment field with attacker-controlled content. The attacker\ncontrols the uploaded binary content, filename, and content-type metadata for\nthe reachable field.\n\nFor key-based/Trix upload flows, the endpoint can persist a blob and return a\nURL even when no attachment association is resolved. This means the endpoint\nshould not be left as an unauthenticated blob creation and URL return path for\nauthenticated Avo users.\n\nIn admin-only deployments following the Avo Community pattern, practical\nexposure is much lower because the only users who can reach the endpoint are\nalready trusted to perform record updates through the normal CRUD path.\n\nSuggested fix direction:\n\n- validate the requested `attachment_key` before any blob is stored\n- perform upload authorization before `ActiveStorage::Blob.create_and_upload!`\n- derive the policy method from the validated association name rather than raw\n  request input\n- apply an equivalent authorization decision to supported `params[:key]` / Trix\n  upload flows before blob creation or URL return\n- return a JSON-compatible `403 Forbidden` response when upload authorization is\n  denied\n\nThe default `Avo::Services::AuthorizationService#authorize_action` returns\n`true` in `lib/avo/services/authorization_service.rb:34-35`, so applications\nwithout a custom authorization client should not see a behavior change from\nadding an authorization call. Deployments with custom/Pro authorization clients\nthat explicitly deny upload would gain enforcement at this endpoint.\n\nNo official Avo-level workaround was confirmed in this review. Until a fix is\navailable, applications can reduce exposure by ensuring only fully trusted\nadministrators can access Avo routes.\n\nApplications needing an immediate mitigation may override or monkey-patch\n`Avo::AttachmentsController#create` to authorize uploads before blob creation.\nAny mitigation should be tested against the application's Avo authorization\nclient and upload UI, because the endpoint is used by Trix/file upload flows.\nIf a mitigation falls back to `update?` for key-based/Trix uploads, that is a\nconservative behavior change for applications that currently allow read-only\noperators to use those uploads; those deployments should replace the fallback\nwith an explicit rich-text upload policy.",
  "severity" : [ {
    "type" : "CVSS_V3",
    "score" : "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N"
  } ],
  "affected" : [ {
    "package" : {
      "ecosystem" : "RubyGems",
      "name" : "avo"
    },
    "ranges" : [ {
      "type" : "ECOSYSTEM",
      "events" : [ {
        "introduced" : "2.28.0"
      }, {
        "fixed" : "3.32.0"
      } ]
    } ]
  } ],
  "references" : [ {
    "type" : "WEB",
    "url" : "https://github.com/avo-hq/avo/security/advisories/GHSA-pqpw-cvm4-8mv9"
  }, {
    "type" : "PACKAGE",
    "url" : "https://github.com/avo-hq/avo"
  }, {
    "type" : "WEB",
    "url" : "https://github.com/avo-hq/avo/releases/tag/v3.32.0"
  } ],
  "database_specific" : {
    "cwe_ids" : [ "CWE-862", "CWE-863" ],
    "severity" : "MODERATE",
    "github_reviewed" : true,
    "github_reviewed_at" : "2026-07-09T20:54:10Z",
    "nvd_published_at" : null
  }
}