java-topology/whitepaper/outreach/substanced.md

2.7 KiB
Raw Blame History

SubstanceD — CWE-407 Disclosure Brief

2026-03-27 · Patch available — awaiting upstream merge

Security contact: github.com/Pylons/substanced/security/advisories/new

Finding

One defect in SubstanceD's Folder.reorder() — quadratic scaling on folder item reordering. Patched. Patch ready for upstream review.

The Defect

substanced-0001 (PATCHED — MEDIUM): substanced/folder/__init__.py:169-173

# In Folder.reorder() — called to reorder M items in an N-item folder:
for name in names:
    if not name in order_names:          # O(N) scan
        raise FolderKeyError(name)
    idx = order_names.index(name)        # O(N) scan
    oid = order_oids[idx]

order_names is a plain Python list built from self._order. Per iteration: two O(N) linear scans — one membership check, one index lookup. With M items being reordered in a folder of N total items: O(M×N) total. When M is proportional to N (bulk reorder): O(N²).

Complexity Proof

substanced-0001: M reorder ops × two O(N) list ops: O(M×N). At N=1,000 items: 2,000× op reduction over the loop-based pair.

Impact

SubstanceD is a CMS application framework built on Pyramid/ZODB. Folder.reorder() is called on UI drag-and-drop operations that reorder folder contents — a common CMS interaction. For large folders (content-heavy sites, media libraries, document repositories), worst-case complexity fires on every user reorder gesture.

The Fix

substanced-0001: Pre-build name→index dict before the loop:

# Before
for name in names:
    if not name in order_names:
        raise FolderKeyError(name)
    idx = order_names.index(name)

# After
# CWE-407 fix: pre-built dict for O(1) lookup instead of two O(N) list scans per item.
order_name_idx = {n: i for i, n in enumerate(order_names)}
for name in names:
    if name not in order_name_idx:
        raise FolderKeyError(name)
    idx = order_name_idx[name]

Patch

Fix available: defects/substanced/patch/substanced-0001-reorder-dict.patch

Single-location patch in substanced/folder/__init__.py. Unit test: 1/1 pass. substanced-0001: 2,000× op reduction at N=1,000.

What We Ask

Patches are ready for review. Please open a GitHub Security Advisory at github.com/Pylons/substanced/security/advisories/new.

  1. Confirm receipt and assign a tracker reference.
  2. Assess severity — reorder() fires on every folder drag-and-drop in production.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the SubstanceD team in the public disclosure. Preferred acknowledgment format welcome.

This brief is confidential until coordinated disclosure. Full report: https://undefect.com