java-topology/whitepaper/outreach/pylons.md
russell@unturf.com 652608142a feat: close outreach doc gap — 276 docs (batches 11-16)
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.
2026-04-15 13:57:42 -04:00

3 KiB
Raw Blame History

Pyramid (Pylons) — CWE-407 Disclosure Brief (pylons-0001/0002/0003)

2026-04-13 · Patches available — awaiting upstream merge

Finding

Three O(N²) defects in TopologicalSorter (Pyramid's dependency ordering utility) where list membership tests and list removal fire inside loops over names and edges.

The Defects

pylons-0001 (PATCHED — MEDIUM): src/pyramid/util.pyadd() and sorted()

# add() — O(N) list scan per call:
if name in self.names:     # list membership — O(N)
    self.remove(name)
self.names.append(name)

# sorted() — O(N) list scan inside O(N) loop:
for name in sorted_names:
    if name in self.names:  # O(N) per iteration
        result.append(...)

pylons-0002 (PATCHED — MEDIUM): sorted() edge validation

names = [self.first, self.last]   # list
names.extend(self.names)
for a, b in order:                # O(E) edges
    if a in names and b in names: # O(N) list scan × 2 per edge

pylons-0003 (PATCHED — MEDIUM): remove() edge list operations

self.order = []  # list of (a, b) tuples
# remove() — O(E) per edge removal:
self.order.remove((u, name))  # O(E) list scan per call

Complexity Proof

At N=1,000 sorter entries and E=3,000 edges:

pylons-0001: add() sequence: 1,000 × 500 = 500,000 comparisons. sorted(): 1,000 × 500 = 500,000. ~500× op reduction each.

pylons-0002: Edge validation: 3,000 × 1,000 × 2 = 6,000,000 comparisons. ~3,000× op reduction.

pylons-0003: remove() with D edges per name: D × 3,000 per removal. ~3,000× op reduction.

Impact

Pyramid is one of the most widely deployed Python web frameworks. TopologicalSorter orders tweens, middleware, and configuration includes. Applications with complex middleware stacks (enterprise apps, CMS platforms) call add() hundreds of times during startup and sorted() on every configuration commit. Large Pyramid deployments with many tweens and includes compound the quadratic cost during application boot.

The Fix

pylons-0001: Add a names_set shadow set for O(1) membership in add() and sorted().

pylons-0002: Replace names list with a names_set set for edge validation.

pylons-0003: Replace self.order list with a set for O(1) discard() instead of O(E) remove().

Patches

Three patches available:

  • defects/pylons/patch/pylons-0001-toposorter-names-set.patch
  • defects/pylons/patch/pylons-0002-toposorter-sorted-names-set.patch
  • defects/pylons/patch/pylons-0003-toposorter-order-set.patch

All target src/pyramid/util.py.

What We Ask

Patches are ready for review.

  1. Confirm receipt and assign a GitHub issue reference (Pylons/pyramid).
  2. Assess severity — fires during application configuration and startup.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the Pylons team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.