CI-Guard: Static Analysis for Detecting Supply Chain Attacks in Package Managers
Abstract
Static analysis tool for detecting supply chain attacks in NPM and PyPI packages. CI-Guard analyzes 12 distinct attack patterns including lifecycle hook abuse, token exfiltration, and obfuscated payloads. Achieves 89.6% detection rate on NPM and 82.2% on PyPI with 0% false positives on 826 popular packages. Open-source: https://github.com/Otsmane-Ahmed/ci-supplychain-guard
Full text
CI-Guard: Static Analysis for Detecting Supply Chain Attacks in Package Managers Ahmed Otsmane University of Computer Science, Sidi Bel Abbes [email protected] [email protected] December 2025 Abstract Supply chain attacks targeting package managers (NPM, PyPI) have increased dramatically, exploiting lifecycle hooks, typosquatting, and environment variable theft to compromise developer systems and CI/CD pipelines. Existing tools rely on behavioral analysis or manual review, which are insufficient for preventing attacks at submission time. I present CIGuard, a static analysis tool that detects malicious packages before installation by analyzing 12 distinct attack patterns across multiple programming languages. Evaluated on 15,059 malicious NPM packages and 2,257 PyPI packages from the Datadog Malaria dataset, CI-Guard achieves an 89.6% detection rate for NPM and 82.2% for PyPI, with a 0% false positive rate on 826 popular packages. The rule-based approach blocks 11,743 real-world attacks while maintaining zero false positives, demonstrating practical viability for integration into CI/CD workflows. The tool is open-source and designed for immediate deployment in automated security pipelines. 1 Introduction Modern software development relies heavily on package managers such as NPM (Node.js) and PyPI (Python) to manage dependencies. However, this dependency on third-party code has created a critical attack vector: supply chain attacks [1, 2, 3]. In 2024 alone, over 150,000 malicious packages were published to NPM and PyPI [4], targeting developers with credential theft, backdoors, and cryptocurrency miners. The full implementation, evaluation scripts, and sanitized datasets for CI-Guard are available at https://github.com/Otsmane-Ahmed/ ci-supplychain-guard. Traditional defenses such as manual code review, behavioral sandboxing, and signaturebased detection suffer from significant limitations. Manual review does not scale to the millions of packages published daily. Behavioral analysis requires execution in a sandboxed environment, introducing latency and bypasses via environment-aware malware [5]. Signaturebased tools fail against novel attack variants. I propose CI-Guard, a real-time static analysis framework designed to detect supply chain attacks at package submission time, before code execution. CI-Guard analyzes source code and package metadata for 12 distinct attack patterns, including lifecycle hook abuse, token exfiltration, obfuscated payloads, and suspicious network activity. Key contributions include: Comprehensive rule set: 12 detection rules targeting lifecycle hooks, environment variable theft, obfuscation, process spawning, binary blobs, typosquatting, and CI/CD workflow manipulation. Multi-language support: Unified detection for NPM (JavaScript) and PyPI 1
(Python) ecosystems. Zero false positives: Validated on 826 popular packages (React, Lodash, Express) with no false alarms, ensuring production viability. High detection rate: 89.6% for NPM (13,488/15,059 samples) and 82.2% for PyPI (1,856/2,257 samples) on real-world malware. Open-source implementation: Available for immediate integration into CI/CD pipelines. The remainder of this paper is organized as follows: Section 2 reviews related work. Section 3 describes my detection rules and system architecture. Section 4 presents a detailed case study of SSH credential exfiltration. Section 5 reports experimental results. Section 6 discusses limitations and future work. Section 7 concludes. 2 Related Work 2.1 Package Repository Security Several commercial and research tools address package security. Socket.dev [6] and Snyk [7] provide runtime behavioral analysis but require sandboxed execution, introducing latency. npm audit and pip-audit [8, 9] rely on vulnerability databases and cannot detect zero-day attacks. Backstabber’s Knife Collection [10] demonstrated static detection of malicious PyPI packages but focused only on obfuscation patterns. My work extends static analysis to cover lifecycle hooks, environment theft, and CI/CD manipulation, attack vectors that are absent from prior tools. 2.2 Supply Chain Attack Taxonomies Datadog’s 2024 report [1] categorizes attacks into installation hooks, dependency confusion, and typosquatting. Ohm et al. [10] identified obfuscation as a primary indicator. I synthesize these taxonomies into a unified detection framework covering 12 distinct patterns. 2.3 Limitations of Existing Approaches Behavioral tools [6, 5] are bypassed by environment-aware malware that detects sandboxes. Signature-based tools fail against polymorphic payloads. Static analysis tools [10] lack coverage of lifecycle hooks and token theft. CIGuard addresses these gaps with comprehensive static rules and validation on 826 benign packages to ensure zero false positives. 3 Methodology 3.1 Threat Model I assume attackers can: Publish packages to public repositories (NPM, PyPI). Compromise maintainer accounts or submit malicious pull requests. Obfuscate payloads using base64, hex encoding, or dynamic imports. Exploit lifecycle hooks (postinstall, preinstall,setup.py). I assume defenders: Run CI-Guard in isolated containers without network egress. Have access to package source code and metadata. Cannot execute untrusted code during analysis. Out of scope: State-actor attacks, alreadyleaked secrets, and attacks requiring postinstallation privilege escalation. 3.2 System Architecture Figure 1 shows CI-Guard’s pipeline. Packages are extracted, scanned for entry points (package.json,setup.py), and analyzed using 12 detection rules. Each rule assigns a risk score; the aggregate score determines the verdict: BLOCKED (≥10), WARNING (4 −9), or SAFE (≤3). 2
Figure 1: CI-Guard system architecture showing the static analysis pipeline from package extraction to verdict decision. 3.3 Detection Rules Table 1 summarizes the 12 detection rules. Full patterns and scoring logic are detailed in Appendix A. 3.4 Attack Taxonomy Figure 2 categorizes attacks into three primary vectors: Code Injection (lifecycle hooks, dependency confusion), Data Exfiltration (token theft, SSH harvesting), and CI/CD Manipulation (workflow backdoors). This taxonomy guided rule development. 3.5 Detection Pipeline Figure 3 details the analysis workflow. Packages are first checked for lifecycle hooks (SA-008), which immediately flag high risk. All files are then scanned in parallel, and rules are applied. The aggregate score determines the final verdict. Figure 2: Supply chain attack taxonomy showing primary attack vectors and sub-categories. Figure 3: Detailed detection pipeline with decision points. Lifecycle hooks are prioritized due to high exploit frequency. 3
Table 1: Detection rules and risk scores. Full regex patterns in Appendix A. ID Name Description Score SA-001 Shell Download Detects curl | bash,wget | sh 10 SA-002 Secret Exfiltration Token theft via process.env + network 10 SA-003 Obfuscated Code Base64, hex, or eval() 7 SA-004 Process Spawning exec(),spawn(), os.system() 5 SA-005 Binary Blob .exe, .dll, .so files 8 SA-006 Typosquatting Levenshtein distance ≤2 from popular packages 6 SA-007 Dynamic Import require(variable), import () 4 SA-008 Lifecycle Hook postinstall,preinstall, setup.py 10 SA-009 Suspicious IP Hardcoded IP addresses 5 SA-010 Sensitive Write Writes to /etc/hosts, ~/.ssh 8 SA-011 Network Call HTTP requests, DNS queries 3 SA-012 CI Workflow Manipulation Modifies .github/workflows/ 10 4 Case Study: SSH Credential Exfiltration I analyze a real-world attack (Datadog sample ID: 2025-11-24-num2words) that exfiltrates SSH credentials via lifecycle hooks. 4.1 Attack Mechanism Figure 4 illustrates the four-stage attack: 1. Upload: Attacker publishes package with malicious postinstall hook. 2. Installation: Developer runs npm install, triggering automatic hook execution. 3. Execution: Malicious script reads ~/.ssh/id rsa. 4. Exfiltration: SSH keys are sent to attacker.com via DNS/HTTP. 4.2 Code Example The malicious package.json contains: Listing 1: Sanitized lifecycle hook example { "scripts": { "postinstall":" node␣ install . js" } } The install.js payload: Listing 2: Simplified SSH stealer (sanitized) const fs = require("fs"); const dns = require ("dns"); const key = fs.readFileSync("~/. ssh/ id_rsa"); dns . resolve (‘ $ { key }. attacker .tld ‘); 4.3 CI-Guard Detection CI-Guard triggers three rules: SA-008: Lifecycle hook detected (10 points). 4
Figure 4: Four-stage SSH credential exfiltration attack via lifecycle hook. CI-Guard detects via rule aggregation: SA-008 (hook) + SA-002 (file read) + SA-011 (network) = BLOCKED. 5
SA-002: File read + network call (10 points). SA-011: DNS query (3 points). Total Score: 23 BLOCKED. Traditional tools fail because: npm audit: No CVE entry for zero-day attacks. Sandboxes: Bypassed if sandbox environment is detected. Manual review: Obfuscated payloads evade human inspection. 5 Evaluation 5.1 Dataset I evaluate on: NPM Malware: 15,059 samples from Datadog Malaria dataset [1]. PyPI Malware: 2,257 samples (Datadog + Maloss). Benign Baseline: 826 top NPM packages (React, Lodash, Express, Webpack, etc.). 5.2 Experimental Setup All experiments ran on Kali Linux with Python 3.13.7 and Node.js v22.20.0. Scans executed in isolated Docker containers without network access. Average scan time: 2.04 seconds per NPM package, 1.87 seconds per PyPI package. 5.3 NPM Results Table 2 shows NPM detection performance. Figure 5 shows the confusion matrix including 826 benign packages. True Positives: 11,743. False Positives: 0. False Negatives: 3,316. Figure 6 shows verdict distribution, and Figure 7 shows the risk score histogram with clear separation at threshold boundaries. Figure 5: NPM confusion matrix with benign baseline. 0 false positives on 826 popular packages. Figure 6: NPM verdict distribution showing 78% blocking rate. Figure 7: NPM risk score histogram. Clear bimodal distribution with separation at BLOCK threshold (10). 6
Table 2: NPM detection results on 15,059 malicious samples. Verdict Count (%) BLOCKED 11,743 (78.0%) WARNING 1,745 (11.6%) SAFE 1,552 (10.3%) ERROR 19 (0.1%) Total 15,059 (100%) 5.4 PyPI Results PyPI detection achieved an 82.2% detection rate (Table 3). This improvement is attributed to Python-specific rules for setup.py hooks and os.system() calls. Table 3: PyPI detection results on 2,257 malicious samples. Verdict Count (%) BLOCKED 1,526 (67.6%) WARNING 330 (14.6%) SAFE 401 (17.8%) Total 2,257 (100%) Figure 8: PyPI confusion matrix. Higher false positives explained by spam packages flagged as suspicious. 5.5 False Positive Analysis Critical Finding: 0% false positive rate on 826 popular NPM packages. Tested packages included: Web frameworks: React, Vue, Express, Next.js Build tools: Webpack, Babel, TypeScript, ESLint Utilities: Lodash, Axios, Moment, UUID Security tools: Passport, Bcrypt, JWT All packages returned SAFE verdict (score ≤3). This validates production viability: CIGuard will not break legitimate dependencies. 5.6 Performance Average scan times: NPM: 2.04s per package PyPI: 1.87s per package Benign packages: 0.5s per package (fewer files) Parallelization (15 workers): Scanned 826 packages in 33 seconds (25 packages/second). 6 Discussion 6.1 Significance of 0% False Positive Rate The most critical metric for CI/CD integration is the false positive rate. Even a 1% FPR would block legitimate packages daily in large organizations, rendering the tool unusable. My 0% FPR on 826 real-world packages demonstrates that CI-Guard’s rules are conservative enough for production deployment while maintaining 89.6% detection on NPM and 82.2% on PyPI. 6.2 Limitations and Evasion Techniques CI-Guard is evadable by: Delayed activation: Malware that triggers only after N days or specific dates bypass static analysis. External fetch: Code downloaded postinstallation from remote servers. 7
Polymorphic payloads: Novel obfuscation techniques not covered by current regex patterns. Mitigation strategies: Behavioral sandboxing: For packages flagged as WARNING, run in isolated environment. Machine learning: Train classifiers on obfuscation patterns to detect novel variants. Community rules: Allow users to contribute new patterns. 6.3 Comparison to Existing Tools Table 4 compares CI-Guard to commercial tools. Table 4: Comparison with existing security tools. Tool Static Zero-day FPR npm audit No No 0% Socket.dev No Yes Unknown Snyk Partial Partial ¡1% CI-Guard Yes Yes 0% CI-Guard is the only fully static tool with zero-day detection and validated 0% FPR. 6.4 Future Work Expand language support: Add Rust (crates.io), Ruby (RubyGems), Go (pkg.go.dev). ML-based obfuscation detection: Train deep learning models on obfuscation patterns. Whitelist generation: Automatically whitelist known-safe lifecycle patterns (e.g., TypeScript compilation). Real-time registry integration: Deploy as pre-commit hook in NPM/PyPI infrastructure. 7 Conclusion Supply chain attacks are a critical threat to modern software development. CI-Guard addresses this threat with a comprehensive static analysis framework that detects 12 distinct attack patterns across NPM and PyPI ecosystems. Validated on 17,316 malicious samples, CI-Guard achieves 89.6% detection on NPM and 82.2% on PyPI, with zero false positives on 826 popular packages, demonstrating immediate production viability. My open-source implementation, available at https://github.com/Otsmane-Ahmed/ ci-supplychain-guard, enables seamless integration into CI/CD pipelines, blocking attacks before code execution. The 0% false positive rate ensures developers can confidently deploy CI-Guard without workflow disruptions. Future work will expand language support, integrate machine learning for novel attack detection, and explore real-time deployment at package registry infrastructure. Acknowledgments I thank Datadog Security Labs for publicly releasing the Malaria dataset, which was instrumental in validating CI-Guard’s detection capabilities. References [1] Datadog Security Labs. “Malicious Software Packages Dataset,” https://github.com/DataDog/ malicious-software-packages-dataset, 2024. [2] FireEye. “Highly Evasive Attacker Leverages SolarWinds Supply Chain to Compromise Multiple Global Victims,” Technical Report, 2020. [3] Codecov. “Bash Uploader Security Update,” https://about.codecov.io/ security-update/, 2021. 8
[4] Sonatype. “State of the Software Supply Chain Report,” 2024. [5] Capsule8. “Detecting Sandbox-Aware Malware,” https://capsule8.com/blog/ detecting-sandbox-aware-malware/, 2023. [6] Socket Security. “Socket for GitHub,” https://socket.dev/, 2023. [7] Snyk. “Developer Security Platform,” https://snyk.io/, 2023. [8] npm. “npm-audit,” https://docs.npmjs. com/cli/audit, 2024. [9] PyPA. “pip-audit,” https://github.com/ pypa/pip-audit, 2024. [10] Ohm, M., Plate, H., Sykosch, A., and Meier, M. “Backstabber’s Knife Collection: A Review of Open Source Software Supply Chain Attacks,” DIMVA 2020, 2020. A Full Detection Rules This appendix provides complete regex patterns and scoring logic for all 12 detection rules. A.1 SA-001: Shell Download Pattern: curl.*\|.*bash|wget.*\|.*sh Score: 10 Rationale: Direct shell execution from remote sources is a hallmark of supply chain attacks. A.2 SA-002: Secret Exfiltration Pattern: process\.env|os\.environ.* (http|dns|fetch) Score: 10 Rationale: Reading environment variables combined with network calls indicates credential theft. A.3 SA-003: Obfuscated Code Pattern: eval\(|exec\(|Function\(| atob\(|Buffer\.from\(.*base64 Score: 7 Rationale: Obfuscation hides malicious intent. Legitimate uses (e.g., polyfills) rarely trigger this rule alone. A.4 SA-004: Process Spawning Pattern: os\.system\(|exec\(|spawn\(| subprocess\. Score: 5 Rationale: Arbitrary command execution. Common in build tools, hence moderate score. 9