java-topology/defects/trytond/SCAN.md

2.6 KiB

Tryton (trytond) 5-MOAD Scan — 2026-03-31

Target: https://github.com/tryton/trytond (depth=1) Focus: trytond/model/, trytond/ir/, trytond/res/, trytond/protocols/

MOAD-0001 (CWE-407) — 1 PRE-EXISTING DEFECT (tryton-0001)

Tryton uses sets and dicts throughout hot paths. Specific checks:

  • ir/model.py fill_models(): uses a list for visited-set dedup but the list is bounded by the number of models in a single access check (typically 1-10) and is only called at access-check time, not in a per-record inner loop. Low severity.
  • model/tree.py check_recursion(): visited = set() throughout. O(1) lookup.
  • model/modelsql.py: field membership checks use dicts/sets. O(1) throughout.
  • ir/translation.py: trans_reports and strings are dicts. O(1) lookups.
  • ir/rule.py: domain building uses defaultdict(list), no membership scans.
  • model/modelstorage.py _save_values(): pre-existing defect — previous list O(T*P) in one2many/many2many save. Fixed in tryton-0001.

MOAD-0002 (Intertangle) — CLEAN

Pool is our class registry (model, wizard, report types per database). It is intentionally a registry/locator pattern, not a god object coupling subsystems. Modules load independently via load_modules. Transaction, Pool, Cache and Model layers are cleanly separated. No shared mutable state coupling unrelated subsystems.

MOAD-0003 (Leaked Context) — CLEAN

Transaction._local = threading.local() is an intentional per-thread transaction stack for the WSGI worker thread model. The _request context key is explicitly stripped from cache keys (cache.py _key() strips _request). The transaction carries user ID, database name, and context, which are properly scoped to each thread's request lifetime and cleared on stop(). This is a standard WSGI thread-per-request pattern, not a leaked identity defect.

MOAD-0004 (CWE-312) — CLEAN

protocols/dispatcher.py routes common.db.login to its own login() function that does NOT call _safe_repr or any logger with the parameters dict containing the password. security.login() logs only username and remote address on success or failure, never the password or session token. No SMTP or LDAP password logged in any logger call found in trytond core.

MOAD-0005 (Thundering Herd) — CLEAN

MemoryCache uses a per-transaction _database_cache (defaultdict of LRUDict). The transaction isolation model means each transaction sees a consistent snapshot. Cache invalidation uses PostgreSQL NOTIFY channels or a polling timeout, not concurrent get+compute+set without synchronization. No unsynchronized cache stampede pattern found.