Threats tagged 'ghsa-pqpw-cvm4-8mv9'
1 threat
Most recently published first
| Severity | CVSS | Signals | Threat | Source | Published | Score and star |
|---|---|---|---|---|---|---|
| Medium | 6.5 | EPSS 0.4% | CVE-2026-53769Avo: Direct attachment upload endpoint lacks upload authorization and bypasses field-level upload policy Medium6.5EPSS 0.4%GCVE DatabaseCVE-2026-53769 ### 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 atta | GCVE Database |
Page 1 of 1