GTR Algorithm
GTR (Graph Threat Recognition) analyzes dependency relationships to identify suspicious patterns, hidden risks, and supply chain anomalies that single-package analysis would miss.
Overview
Modern applications have complex dependency trees — often hundreds of transitive dependencies. GTR builds a complete graph of these relationships and applies pattern detection to find:
- Dependency Confusion — Internal vs external package conflicts
- Circular Dependencies — Packages that depend on each other
- Shadow Dependencies — Hidden transitive risks
- Depth Anomalies — Unusually deep dependency chains
- Abandoned Subtrees — Unmaintained branches in the graph
💡 Why Graph Analysis?
The event-stream attack in 2018 was hidden 3 levels deep in the dependency tree. Single-package scanners missed it. GTR would have flagged the suspicious new maintainer and unusual dependency addition.
Threat Patterns Detected
1. Dependency Confusion
When internal package names conflict with public registry packages:
⚠️ DEPENDENCY CONFUSION DETECTED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Package: @mycompany/utils
Issue: Public npm package exists with same name
Risk: Attacker could publish malicious version
Your package.json:
"@mycompany/utils": "^1.0.0"
Public npm registry:
"@mycompany/utils": "1.0.1" (published 2 days ago)
Recommendation: Use scoped registry or explicit registry URL
⚠️ Real-World Impact
Dependency confusion attacks have hit Apple, Microsoft, PayPal, and dozens of Fortune 500 companies. Always scope internal packages.
2. Circular Dependencies
Packages that create loops in the dependency graph:
⚠️ CIRCULAR DEPENDENCY DETECTED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Cycle found:
package-a@1.0.0
→ package-b@2.0.0
→ package-c@1.5.0
→ package-a@1.0.0 ← CYCLE
Risk Level: MEDIUM
Issues:
• Unpredictable initialization order
• Potential infinite loops during install
• May indicate compromised package insertion
Recommendation: Review why cycle exists
3. Shadow Dependencies
Dangerous packages hidden deep in the dependency tree:
⚠️ SHADOW DEPENDENCY RISK
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Risky package found at depth 4:
your-app
→ express@4.18.2
→ body-parser@1.20.0
→ raw-body@2.5.1
→ sketchy-lib@0.1.0 ← FLAGGED
Package: sketchy-lib@0.1.0
Risk: HIGH (DIRT score: 0.78)
Reason: New package, single maintainer, no docs
You didn't directly depend on this package, but it's
in your node_modules and runs during installation.
Recommendation: Find alternative to raw-body or pin version
4. Depth Anomalies
Unusually deep dependency chains that may indicate injection:
⚠️ ABNORMAL DEPENDENCY DEPTH
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Package: simple-util@1.0.0
Stated purpose: "Simple string utilities"
Actual depth: 12 levels
Expected depth: 1-2 levels for utility library
Dependency chain (truncated):
simple-util → helper-a → helper-b → helper-c
→ wrapper-x → wrapper-y → ... (12 levels)
Risk: HIGH
This is abnormal for a "simple utility" package.
Deep chains are often used to hide malicious code.
Recommendation: Do not use - find alternative
5. Abandoned Subtrees
Branches of your dependency tree that are no longer maintained:
⚠️ ABANDONED DEPENDENCY SUBTREE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Package: old-framework@2.3.1
Last update: 847 days ago
Depends on: 23 packages (also unmaintained)
Affected packages in subtree:
• old-framework@2.3.1 (2+ years stale)
• old-helper@1.0.0 (3+ years stale)
• deprecated-util@0.9.0 (archived)
Known vulnerabilities in subtree: 7
• 2 CRITICAL
• 3 HIGH
• 2 MEDIUM
Risk: CRITICAL
Recommendation: Replace old-framework with maintained alternative
Understanding the Graph
GTR builds a directed graph where:
- Nodes = Packages (with metadata)
- Edges = Dependency relationships
- Weights = Risk scores from RUNT/DIRT
Example Dependency Graph
your-app (root)
├── express@4.18.2 ✅
│ ├── body-parser@1.20.0 ✅
│ │ └── raw-body@2.5.1 ✅
│ ├── cookie@0.5.0 ✅
│ └── debug@4.3.4 ✅
├── lodash@4.17.21 ✅
├── cros-env@1.0.0 ❌ ← RUNT: Typosquat
│ └── malicious-dep@0.0.1 ❌ ← DIRT: Critical
└── @internal/utils@1.0.0 ⚠️ ← GTR: Confusion risk
Legend: ✅ Safe ⚠️ Warning ❌ Threat
Configuration
# config.yaml
detection:
gtr:
enabled: true
# Maximum depth to analyze (performance vs coverage)
max_depth: 10
# Thresholds
thresholds:
# Flag if dependency depth exceeds this for "simple" packages
depth_anomaly: 5
# Flag circular dependencies
circular_deps: true
# Minimum DIRT score to flag shadow dependencies
shadow_risk_threshold: 0.6
# Days without update to consider "abandoned"
abandoned_days: 365
# Dependency confusion settings
confusion:
enabled: true
# Your internal package scopes
internal_scopes:
- "@mycompany"
- "@internal"
# Check if internal names exist on public registry
check_public_registry: true
# Packages to exclude from analysis
ignore:
- "typescript" # Known to have many deps
- "@types/*" # Type definitions
CLI Options
# Run GTR analysis only
falcn scan . --algorithms gtr
# Set maximum depth
falcn scan . --max-depth 15
# Check for dependency confusion
falcn scan . --check-confusion
# Output dependency tree
falcn scan . --output tree
# Export graph as DOT format (for visualization)
falcn scan . --output dot > deps.dot
dot -Tpng deps.dot -o deps.png
# Show full dependency paths for threats
falcn scan . --show-paths
# Ignore specific packages
falcn scan . --ignore typescript --ignore "@types/*"
Full Example Output
🦅 FALCN v2.0.0 - GTR Analysis
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
[✓] Building dependency graph...
[✓] Analyzing 847 packages across 12 levels
[✓] Running pattern detection...
📊 Graph Statistics:
Total packages: 847
Direct deps: 23
Max depth: 8
Circular deps: 0
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠️ GTR FINDINGS (2 issues)
1. SHADOW DEPENDENCY [HIGH]
Path: express → body-parser → raw-body → iconv-lite
Issue: iconv-lite@0.4.24 has known CVE-2022-24434
2. ABANDONED SUBTREE [MEDIUM]
Package: legacy-auth@1.2.0
Last update: 456 days ago
Affected deps: 7 packages
Known CVEs: 2
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ No dependency confusion detected
✅ No circular dependencies
✅ No depth anomalies
Scan completed in 2.3s
Remediation Strategies
Dependency Confusion
// .npmrc - Force internal packages to private registry
@mycompany:registry=https://npm.mycompany.com/
// package.json - Use explicit registry
"dependencies": {
"@mycompany/utils": "npm:@mycompany/utils@^1.0.0"
}
Shadow Dependencies
# Option 1: Override the transitive dependency
npm pkg set overrides.sketchy-lib="npm:safe-alternative@^1.0.0"
# Option 2: Use package-lock.json overrides
"overrides": {
"raw-body": {
"sketchy-lib": "npm:safe-lib@^2.0.0"
}
}
Abandoned Subtrees
# Find direct dependency that pulls in abandoned package
falcn scan . --show-paths --filter abandoned
# Then update or replace the direct dependency
npm update direct-dep
# or
npm uninstall old-package && npm install new-alternative
Performance Considerations
| Project Size | Packages | GTR Time | Memory |
|---|---|---|---|
| Small | <100 | ~200ms | ~20MB |
| Medium | 100-500 | ~800ms | ~50MB |
| Large | 500-1500 | ~2s | ~100MB |
| Monorepo | 1500+ | ~5s | ~200MB |
💡 Performance Tip
For CI/CD, use --max-depth 5 for faster scans. Most attacks are within 5 levels. Use full depth for security audits.
Combining with RUNT & DIRT
GTR is most powerful when combined with RUNT and DIRT:
| Attack Type | RUNT | DIRT | GTR |
|---|---|---|---|
| Typosquatting | ✅ Primary | ✅ Confirms (new pkg) | — N/A |
| Dependency Confusion | — N/A | — N/A | ✅ Primary |
| Compromised Maintainer | — N/A | ✅ Primary | ✅ Finds hidden deps |
| Deep Injection | — N/A | ✅ Scores risk | ✅ Finds path |
| Abandoned Package | — N/A | ✅ Primary | ✅ Maps impact |
# Run all algorithms together (default)
falcn scan .
# Run specific combination
falcn scan . --algorithms runt,dirt,gtr
Related Documentation
🔍RUNT Algorithm Typosquatting detection using string similarity.
📊 DIRT Algorithm Business risk assessment based on package metadata.
🏗️ Architecture How GTR fits into the overall system.
🛡️ Complete Protection
For maximum security, run all three algorithms: RUNT for naming attacks, DIRT for package health, and GTR for graph-level threats.