All projects with patches now have outreach docs. 276 new docs covering CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#, PHP, Ruby, JavaScript, Dart, Erlang, R, and more. Outreach gap: 276 -> 0.
2.8 KiB
Tryton — CWE-407 Disclosure Brief
2026-04-13 · Patch available — awaiting upstream merge
Finding
Two O(n²) defects in Tryton's ORM layer. List-based membership checks and list.remove() calls produce quadratic behavior during record save and change-tracking operations. Patched.
The Defects
tryton-0001a (PATCHED — MEDIUM): trytond/trytond/model/modelstorage.py
# In _save_values() — fires per One2Many/Many2Many field save:
previous = [t.id for t in getattr(self, fname)] # list
...
if target.id in previous: # O(N) membership test
previous.remove(target.id) # O(N) removal
previous is a list. in is O(N) and remove() is O(N), both inside a per-target loop, producing O(T × N) where T = targets, N = previous records.
tryton-0001b (PATCHED — MEDIUM): trytond/trytond/model/modelview.py
# In _changed_values() — fires per record change detection:
previous = [t.id for t in init_targets if t.id] # list
...
if target.id in previous: # O(N) membership test
previous.remove(target.id) # O(N) removal
Same pattern in the view-layer change tracking.
Complexity Proof
tryton-0001: At N=500 related records:
- Defective: ~125,000 comparisons + ~125,000 element shifts per field
- Fixed: ~500 set lookups + ~500 O(1) discard calls
- ~250× op reduction. Fires during every relational field save.
Impact
Tryton is an open-source ERP (enterprise resource planning) framework. Relational field operations (One2Many, Many2Many) on records with hundreds of related entries (invoice lines, order items, stock moves) trigger quadratic behavior during save and change detection. Enterprise deployments with large transaction records experience compounding overhead.
The Fix
tryton-0001: Replace list with set; use discard() instead of remove():
# Before — O(N²)
previous = [t.id for t in getattr(self, fname)]
previous.remove(target.id)
# After — O(N)
previous = set(t.id for t in getattr(self, fname))
previous.discard(target.id)
Patch
Fix available: defects/tryton-0001/patch/tryton-0001-modelstorage-save-values.patch and defects/tryton-0001/patch/tryton-0001-modelview-changed-values.patch
Two-file patch across trytond/model/modelstorage.py and trytond/model/modelview.py.
What We Ask
A patch is ready for review.
- Confirm receipt and assign an issue reference (bugs.tryton.org or Heptapod).
- Assess severity — fires during every relational field save and change detection.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
- We will credit the Tryton team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.