#!/usr/bin/env bash # CWE-407 scan — Composer (PHP package manager) # Large PHP ecosystem; dep solver uses topological sort and cycle detection # Strategy: PHP membership patterns in graph/dep/solver context set -euo pipefail echo "# scan=composer host=$(hostname) date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" cd /tmp && git clone --depth 1 https://github.com/composer/composer composer 2>&1 | tail -1 # O(n) membership patterns in PHP PHP_MEM='in_array\s*\(|array_search\s*\(|\barray_key_exists\s*\(' # Loop constructs PHP_LOOP='foreach\s*\(|for\s*\(|while\s*\(' for dir in \ src/Composer/DependencyResolver \ src/Composer/Package \ src/Composer/Repository \ src/Composer/Util; do [ -d /tmp/composer/$dir ] || continue echo "# roots: /tmp/composer/$dir" find /tmp/composer/$dir -name "*.php" 2>/dev/null | sort | while IFS= read -r f; do ml=$(grep -nE "$PHP_MEM" "$f" 2>/dev/null | cut -d: -f1 || true) [ -z "$ml" ] && continue while IFS= read -r ln; do s=$(( ln > 20 ? ln - 20 : 1 )); e=$(( ln + 20 )) ctx=$(sed -n "${s},${e}p" "$f" 2>/dev/null || true) graph_hit=$(echo "$ctx" | grep -iE 'graph|depend|topo|visit|cycle|dag|sort|stack|order|reachab|ancestor|transit|package|solver|pool' | head -1 | sed 's/^\s*//' || true) [ -z "$graph_hit" ] && continue loop_hit=$(echo "$ctx" | grep -iE "$PHP_LOOP" | head -1 | sed 's/^\s*//' || true) [ -n "$loop_hit" ] && { mem_line=$(sed -n "${ln}p" "$f" | sed 's/^\s*//') echo "CANDIDATE\t${f}:${ln}\t${mem_line} [loop: ${loop_hit}]" } done <<< "$ml" done done echo "# scan complete"