You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
PR #384 fixed the two except Exception blocks on the create/write request path in spp_attachment_av_scan/models/ir_attachment.py: they swallowed database errors, which
left execution continuing on an aborted transaction, so the next SQL statement failed in
unrelated code (InFailedSqlTransaction) and the real cause was invisible. It also
defeated odoo.service.model.retrying, which would have transparently retried the
serialization failure that triggered the incident.
The same file has seven more bare except Exception blocks with the same latent
hazard, deliberately left out of #384 because their blast radius differs: they run inside
queue jobs or explicit button actions, where a poisoned transaction is confined to that
job/request rather than corrupting an unrelated user request mid-flight.
A swallowed DB error in a queue job makes the job report success on a dead
transaction — the scan result/quarantine write is silently lost, and the job is not
retried even though the failure was transient and retryable.
In the button actions, a swallowed DB error turns into a misleading follow-on error
(or a silent no-op behind a success toast).
Reuse the _MUST_NOT_SWALLOW = (psycopg2.Error, ConcurrencyError) guard from #384:
add an except _MUST_NOT_SWALLOW: raise clause ahead of each broad catch. Per-site
review needed — e.g. _quarantine's encryption fallback (line 342) intentionally falls
back to plain storage on encryption errors and must keep doing so for non-DB errors.
Tests should mirror #384's two-sided pattern: a DB error propagates; a non-DB error is
still swallowed/logged and the best-effort behavior (fallback, notification skip) is
preserved.
Context
PR #384 fixed the two
except Exceptionblocks on thecreate/writerequest path inspp_attachment_av_scan/models/ir_attachment.py: they swallowed database errors, whichleft execution continuing on an aborted transaction, so the next SQL statement failed in
unrelated code (
InFailedSqlTransaction) and the real cause was invisible. It alsodefeated
odoo.service.model.retrying, which would have transparently retried theserialization failure that triggered the incident.
The same file has seven more bare
except Exceptionblocks with the same latenthazard, deliberately left out of #384 because their blast radius differs: they run inside
queue jobs or explicit button actions, where a poisoned transaction is confined to that
job/request rather than corrupting an unrelated user request mid-flight.
Sites (line numbers at ba1f3ef)
_scan_for_malware_quarantine(inner, encryption fallback)_quarantine(outer)_notify_security_adminsaction_restore_quarantinedaction_download_quarantined_for_analysisaction_rescanWhy it still matters
transaction — the scan result/quarantine write is silently lost, and the job is not
retried even though the failure was transient and retryable.
(or a silent no-op behind a success toast).
cursor can propagate once code continues past a DB error.
Proposed direction
Reuse the
_MUST_NOT_SWALLOW = (psycopg2.Error, ConcurrencyError)guard from #384:add an
except _MUST_NOT_SWALLOW: raiseclause ahead of each broad catch. Per-sitereview needed — e.g.
_quarantine's encryption fallback (line 342) intentionally fallsback to plain storage on encryption errors and must keep doing so for non-DB errors.
Tests should mirror #384's two-sided pattern: a DB error propagates; a non-DB error is
still swallowed/logged and the best-effort behavior (fallback, notification skip) is
preserved.