Problem/Motivation
Steps to reproduce
Prerequis : have the module "Commerce Invoice 8.x-2.2" installed and enabled.
The location of the file generated for invoice is "privated://"
Steps :
- In admin, create an order for a customer.
- Generate the order
==> An email is sent to the customer but does not include the PDF attachment.
In the code :
namespace Drupal\symfony_mailer;
[...]
class Email.php
at line 592.
If I comment the protection if ($attachment->hasAccess()) {, the attachment is well include.
// Attachments.
foreach ($this->attachments as $attachment) {
<strong>if ($attachment->hasAccess()) {</strong>
$this->inner->addPart($attachment);
if (($attachment->getMediaType() == 'image') && ($attachment->getUri() != NULL)) {
$replace_uri = TRUE;
}
<strong>}</strong>
}Proposed resolution
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | 3529246-temporary-remove-hasaccess-3.patch | 656 bytes | netsliver |
Issue fork symfony_mailer-3529246
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
netsliverHi,
Same problem with webform attachments which is private...
Comment #3
netsliverAttached patch remove temporary hasAccess
Comment #4
adamps commentedThanks for the report. The access checking is a new feature designed to improve security. The change record was linked from the release note. By default private files are not allowed.
Please can you take a look at the CR and see if you could write code to call
Attachment::setAccess()?If not, then do you have any suggestions how we could make it work for your site and still keep some security?
Comment #5
adamps commentedWe could remove the access check for legacy emails (sent using Drupal core mailer)?? This makes some sense for compatibility.
Comment #6
christophe8392 commentedHi,
I manage two sites which use the module commerce_invoice for the two site.
how I have tested in Test Environment, I don't update in PRODUCTION my website. So, in theses condition, I don't apply the update on my PRODUCTION sites. But it's a blocking issue to apply update automatically without patches.
I can wait if no high security violation is discovered.
How it's communicate this new contraint for dependencies module. Actualy, this contraint is not reported I think on project commerce_invoice, and I dont know if they are be concient of this new features.
I am not the best to answer if you can remove the access check for legacy emails...
Thanks
Comment #7
sebastixI managed to add something like this snippet to the custom code for adding attachments which are located in
private://Hope this can help anyone for fixing sending attachments which are located / configured in the private files directory.
Comment #8
zillowwI understand this change was introduced for security reasons, but could you clarify specifically what vulnerability or risk this hasAccess() check is addressing?
On my current site, even public files are no longer being sent as attachments, which breaks expected behavior. Before applying a workaround like setAccess(AccessResult::allowed()), I’d like to understand if:
the change is strictly necessary in all cases,
and whether the implementation is fully correct, given that public files are also affected.
For now, solution #7 works fine, but I’m trying to assess whether this change is required and properly implemented. Thanks.
Comment #9
adamps commentedThis change/problem was introduced in #3382624: embed attachments API addition. The vulnerability is where non-trusted users can attach files - they could attach a file that they shouldn't be able to access and email it to themselves (this isn't just theoretical as there has already been a security issue like this in another module). Particularly this applies to #3284140: Email adjuster to attach/embed by scanning the email body, which currently is in 2.x but not yet in 1.x.
The solution is intended to work like this. Public files are allowed; http/https file are allowed if the URL can be opened with
fopen; everything else is not allowed by default. Code that knows the attachment is from a trusted source can use the API to allow access to any file.For legacy emails, AFAIK there has never been any access checking. The code that sets the attachment is responsible for ensuring that it is safe. Therefore we could reasonably do the same, as in #7. This was how it worked in 1.5, and I AFAIK it is safe.
This is not correct, it would be a bug. Can anyone else confirm? There is an automatic test that should be covering this case, however the test could be wrong.
Comment #10
adamps commentedFix in 2.x first then backport
Comment #14
adamps commentedv1.x version ready for testing please
Comment #15
zillowwWe've reviewed the changes and will test the 1.x fix internally to confirm the regression is resolved.
One additional proposal: introduce a configuration option (e.g., checkbox or boolean field) that allows trusted code to opt into attaching files from private:// when needed. We totally agree that default should remain FALSE for security.
Use case: on a platform managing exams, a certificate is generated after completion and emailed to the user. The certificate contains personal data, so it's stored in private://. With the current restriction, sending it by email becomes impossible, despite being a fully controlled, trusted process.
Instead of requiring all developers to manually override access via setAccess(AccessResult::allowed()), exposing a controlled config flag would make the behavior clearer, safer, and easier to manage.
What do you think @adamps?
Comment #16
adamps commentedThanks
Please can you explain how you are adding the attachment?
email->attachFromPath()or similar. So could you add one extra line to callsetAccess()?Comment #17
zillowwI'm using the function
email->attachFromPath()so yeah, I can add thesetAccess()just after.For your patch, I just realized that it changes the legacy mailer that I don't use, so I will not be able to review it.
Comment #18
sebastixAs I was thinking about a same solution so this seems to be a good idea from me. This configuration form could have a field where you can set trusted sources for the attachments being sent with the module.
Comment #19
adamps commentedThis could potentially work.
I don't feel it's safe as a flag that would allow access to any file. The GUI admin might set the flag intending access to specific files, but then the attacker could add something else (such as
settings.php😃).I have another idea. We could allow attaching private files that the recipient would anyway have access to via HTTPS. It's a bit awkward to implement because there isn't an API - the code is tied into FileDownloadController.php. I guess we'd have to invoke
hook_file_download().I have raised #3530021: Allow selective access to attach private files.
Comment #20
ccarnnia commentedHi All,
in prepration for d11 i upgraded from 1.4 to 1.6.
no custom code, i use symfony_mailer with webforms.
/admin/config/system/mailsystem is set to default `Default PHP Mailer`.
/admin/config/system/mailer/transport is set to `sendmail`.
/admin/config/system/mailer/override no overrides enabled.
test webform submission puts a link for the uploaded file in the body, no attachment:
```
File
my.png (528.35 KB)
```
path for my.png is : http://mysite.dev/system/files/webform/casey_test_file_upload/4713/my.png
which is not accessable by anonymous user.
Patch #3 fixes the issue for now.
Comment #21
adamps commented@Thanks ccarnnia. Please could you test MR176 as that is what I would like to commit?
After someone has tested and set it to RTBC then I will commit and make a new release.
Comment #22
renrhafTested & +1 for RTBC here !
Comment #23
adamps commentedComment #25
adamps commentedGreat thanks
Comment #26
adamps commentedNow available in 1.6.2 release.
Comment #27
christophe8392 commentedDears,
I have just tested the new version in 1.6.2, it's OK for me. I have the attachment : PDF for invoice by module commerce_invoice.
Thanks