Проблема: Скрытые (неявные) зависимости — модули/пакеты, используемые в коде, но не указанные в манифесте проекта (например, package.json, requirements.txt). Они приводят к уязвимостям цепочки поставок и сложностям воспроизведения сборки.

Причины:
- Динамические вызовы (`require(variable)`, `__import__()`, `Reflection.loadClass`).
- Транзитивные зависимости, не фиксированные в lock-файле.
- Прямой вызов системных утилит (`exec`, `subprocess`, `shell_exec`).
- Отсутствие аудита импортов при рефакторинге.
- Устаревшие или неподписанные пакеты, подгружаемые из внешних источников (CDN, локальных путей).

Решение: Статический + динамический анализ графа вызовов с последующей верификацией манифеста.

1. Построение статического графа вызовов

- Node.js/JS:
`npx madge --json src/ | jq '.dependencies | keys'` — список всех разрешённых модулей.
`npx dependency-cruiser --include-only "^src" --output-type dot src/ | dot -Tsvg > graph.svg`
- Python:
`pyan3 src/main.py --uses --dot | dot -Tpng > graph.png`
`snakefood src/ > sfood.out`
`grep -r "import\|from" src/ | grep -oP "(from\s+|import\s+)[\w.]+" | sort -u`
- Java:
`jdeps -dotoutput graph --multi-release 11 target/classes/`
`mvn dependency:tree -Dincludes=::runtime` (показать транзитивные)
- C/C++:
`egypt src/.c | dot -Tpng -o callgraph.png` (на основе RTL dumps)

2. Выявление динамических загрузок

- Поиск шаблонов:
`grep -rn "require\|import\|exec\|system\|subprocess\|load\|dlopen" src/ --include=".py" --include=".js" --include=".java"`
Исключить статические строки — оставить только переменные в аргументах.
- Анализ AST (Python):
python
import ast, sys
with open('src/main.py') as f:
tree = ast.parse(f.read())
for node in ast.walk(tree):
if isinstance(node, ast.Call) and hasattr(node.func, 'id') and node.func.id == 'require':
print(ast.dump(node))

- Для Java: поиск `Class.forName(variable)`, `Method.invoke`, `URLClassLoader`.

3. Сравнение с манифестом

- npm:
`comm -23