On Plone 5, I would need to run through an antivirus the attachment which will become the user's avatar/portrait if they wish to add one from @@personal-information
I can't identify the said file in the server logs. How to identify it? Thank you in advance for your help and explanations which would put me on the right track...
Plone typically stores (most) files you upload in its BLOB storage (which is on the filesystem, where depends on your configuration). Unfortunately, portraits are (in all versions through 6.1 including 5.x) are stored as binary data directly inside the ZODB, not on the filesystem.
What you want to achieve can be done — but only programmatically either at the time of upload of with some post-hoc extraction from the database:
Plone has a method called validate_portrait in plone.app.users.browser.account.AccountPanelForm.
There are two approaches to customizing this method's behavior in an integration/policy product/package of your own customization of Plone:
Monkey patch AccountPanelForm.validate_portrait method with injected additional validation you have coded.
Subclass plone.app.users.browser..personalpreferences.PersonalPreferencesPanel (which is a subclass of AccountPanelForm and the registered view for personal preferences where portraits are uploaded). In this subclass, write your own wrapper around the built-in validate_portrait method that performs stock validation plus your custom validation. Register this in ZCML as a view named personal-preferences and specify a layer value in ZCML which will override what comes out of the box).
the second approach is likely more graceful
General considerations:
You would likely want to use temporary file to save said data;
For safety, if you validate during upload you should implement a maximum file-size check in Python, to avoid potential for denial of service (resource exhaustion of publisher threads).
there will be IO and computational costs to doing this, but if the file-size of portraits is both typically small and enforced as such, it should be reasonable to do this within the scope of your transaction.
If validation fails, you can choose to raise an error or handle presentation of the errors (personally, I would just raise an unhandled exception as an expedient check against storing)
if you do not want to handle this at time of upload, and are comfortable handling this after the fact, you could write a run-script running on a cron-job to pull these out of the database (you can see where these live as a Manager role user visiting /portal_memberdata/portraits/manage_main in a browser).