Skip to content

[15.0][FIX] attachment_mimetype_restriction: skip binary field storage - #1896

Draft
AungKoKoLin1997 wants to merge 4 commits into
OCA:15.0from
qrtl:15.0-fix-attachment_mimetype_restriction
Draft

[15.0][FIX] attachment_mimetype_restriction: skip binary field storage#1896
AungKoKoLin1997 wants to merge 4 commits into
OCA:15.0from
qrtl:15.0-fix-attachment_mimetype_restriction

Conversation

@AungKoKoLin1997

@AungKoKoLin1997 AungKoKoLin1997 commented Aug 4, 2026

Copy link
Copy Markdown

Binary/image fields default to attachment=True, so the ORM stores their values as ir.attachment records with res_field set — image_1920 and its resized variants on partners/products, the company logo, the company favicon. Nothing in _validate_mimetype_from_vals exempted those, so they were validated against the allowlist even though they are field storage rather than user-facing uploads, and their content type is chosen by Odoo rather than by the uploader.

The effect is that a configured allowlist which does not happen to cover those content types breaks ordinary record saves. Creating a company fails unconditionally, because res.company.create() injects a default favicon (res_company.py) whose mimetype no allowlist would reasonably include:

if not vals.get('favicon'):
    vals['favicon'] = self._get_default_favicon()

This PR returns early when res_field is set, and adds res_field to the vals dict rebuilt in write() so the update path is covered too — replacing an existing image goes through atts.write({'datas': value}) in fields.Binary.write(), not through create().

Added a regression test that sets res.partner.image_1920 under a text/plain-only allowlist. It fails on 15.0 today with ValidationError: File type 'image/png' is not allowed. and passes with this change.

Restriction of user-uploaded attachments (chatter uploads, incoming mail attachments) is unchanged.

@qrtl QT5832

Binary/image fields default to attachment=True, so the ORM stores their
values as ir.attachment records with res_field set (partner/product
image_1920 and its resized variants, company logo and favicon). These are
field storage rather than user-facing uploads, and their content type is
chosen by Odoo, not by the uploader.

Validating them means that any configured allowlist that does not cover
those content types makes ordinary record saves fail. Creating a company
always fails, since res.company.create() injects a default favicon that no
allowlist would reasonably include.
@OCA-git-bot

Copy link
Copy Markdown
Contributor

Hi @AungKoKoLin1997, @yostashiro,
some modules you are maintaining are being modified, check this out!

@OCA-git-bot OCA-git-bot added series:15.0 mod:attachment_mimetype_restriction Module attachment_mimetype_restriction labels Aug 4, 2026
@AungKoKoLin1997
AungKoKoLin1997 marked this pull request as ready for review August 4, 2026 01:57
]
)
self.assertEqual(attachment.mimetype, "image/png")
self.partner.image_1920 = PNG_DATA

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use different data to confirm the write path works. Using the same data ends up testing nothing as it won't reach ir.attachment.write().

- Use content-based detection (guess_mimetype) instead of relying on
  _compute_mimetype, which trusts a caller-supplied mimetype or filename
  extension. Falls back to filename only when the content sniffer returns
  application/octet-stream (unrecognizable content).
- Fix write() validating the stale record mimetype instead of sniffing
  the incoming content. Drop mimetype from check_vals when new datas/raw
  is present so guess_mimetype runs on the actual bytes.
- Fix upload_attachment controller crash: core returns a str, not a
  Response, so response.get_data() raised AttributeError on every
  blocked upload.
- Look up the allowlist before evaluating attachments in
  _message_post_process_attachments, so errors in _get_allowed_mimetypes
  cannot block attachments when the feature is disabled (empty allowlist).
- Pass unrecognised attachment tuples through to super() instead of
  silently discarding them.
- Reword the blocked-attachment notice (remove "from the email above"
  since the notice is posted before the email) and wrap in _() for i18n.
- Add tests for content/extension mismatch, caller-supplied mimetype
  bypass, and content-based detection on write.
@AungKoKoLin1997
AungKoKoLin1997 marked this pull request as draft August 4, 2026 07:29
@AungKoKoLin1997
AungKoKoLin1997 force-pushed the 15.0-fix-attachment_mimetype_restriction branch from a4b4c4a to 410b2ae Compare August 4, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mod:attachment_mimetype_restriction Module attachment_mimetype_restriction series:15.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants