## 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.