Created by: Hemant Patidar (@HemantSolo)
Code-Evolution-Tracker is a universal Python-based tool that automatically scans all versions of a package across multiple ecosystems to identify vulnerable or fixed code lines.
It downloads, extracts, and inspects every package version to locate a specific code snippet or line — even if the filename, folder, or structure has changed due to refactor or rename.
This tool is incredibly useful for:
- 🔍 Source code review
- 🧩 Commit analysis
- 🕵️ Vulnerability triage
- 🧠 Patch identification
- 🧾 Historical file tracking
✅ Supports 7 major ecosystems:
- PyPI (
pypi) — Python - npm (
npm) — JavaScript / Node.js - Maven (
maven) — Java / JVM - Go (
go) — Go Modules - Packagist (
php) — PHP - RubyGems (
ruby) — Ruby - NuGet (
nuget) — .NET (auto-decompiles.dllvia ILSpy)
✅ Auto file detection:
If you don’t specify a filename, the tool searches all readable files to find where your target code exists.
✅ Smart caching:
Downloaded archives and decompiled files are cached under ./downloads/, avoiding redundant re-downloads and re-decompilations.
✅ Progress bar support:
Visual feedback using tqdm while scanning hundreds of versions.
✅ NuGet decompilation:
Automatically decompiles .dll files using ilspycmd (if installed) and scans resulting C# code.
✅ Refactor-aware scanning:
Detects code across renamed, relocated, or refactored files — perfect for finding intro commits and fix commits.
python3 -m venv .venv
source .venv/bin/activate
pip install tqdm requestsInstall ILSpy command-line tool:
dotnet tool install --global ilspycmd
export PATH="$PATH:$HOME/.dotnet/tools"git clone https://github.com/HemantSolo/Version-Scanner.git
cd Version-ScannerVersion-Scanner/
│
├── script.py # Main scanning script
├── downloads/ # Cached downloads and decompiled source
│ ├── pypi/
│ ├── npm/
│ ├── maven/
│ ├── go/
│ ├── php/
│ ├── ruby/
│ └── nuget/
│ ├── <package>/
│ │ ├── <version>.nupkg
│ │ └── decompiled/<version>/
│ │ └── *.cs
└── results.csv # (optional) Output CSV if --output-csv used
Example: Check which Maven versions contain a vulnerable line in UIConfigRest.java.
python3 script.py \
--ecosystem maven \
--pkg org.opencastproject:opencast-user-interface-configuration \
--vulnerable-file UIConfigRest.java \
--test-code "final String basePath = new File(uiConfigFolder, orgId).getCanonicalPath() + File.separator;" \
--output-csv results.csvExample Output
[+] Starting scan — ecosystem: maven, package: org.opencastproject:opencast-user-interface-configuration
[+] 12 versions found
...
[+] MATCHES FOUND:
- 9.1.0: src/main/java/UIConfigRest.java (line 57): final String basePath = ...
- 9.2.0: src/main/java/UIConfigRest.java (line 59): final String basePath = ...
Summary: scanned 12 versions — hits: 2 — errors/no-file: 0
If you don’t know which file the code appears in — useful for refactor/rename tracking:
python3 script.py \
--ecosystem maven \
--pkg org.opencastproject:opencast-user-interface-configuration \
--test-code "final String basePath = new File(uiConfigFolder, orgId).getCanonicalPath() + File.separator;"🧭 The tool will recursively search all files in every version, skipping binaries and large files, and report the exact file paths where your code appears.
python3 script.py \
--ecosystem pypi \
--pkg requests \
--vulnerable-file sessions.py \
--test-code "def merge_environment_settings"python3 script.py \
--ecosystem npm \
--pkg express \
--test-code "app.use(function (req, res, next)"python3 script.py \
--ecosystem nuget \
--pkg Newtonsoft.Json \
--test-code "public static string SerializeObject"💡 For NuGet packages,
.nupkgfiles are downloaded,.dlls automatically decompiled withilspycmd, and all resulting.csfiles scanned and cached.
python3 script.py \
--ecosystem pypi \
--pkg flask \
--test-code "def run_simple" \
--max-versions 10python3 script.py ... --output-csv results.csvEach CSV row includes:
| Ecosystem | Package | Version | Found | File | LineNo | Line | Reason | Matches_JSON |
|---|
| Use Case | Description | Benefit |
|---|---|---|
| 🔍 Vulnerability Tracking | Identify which versions contain a vulnerable or fixed code line | Confirms affected/fixed versions |
| 🧩 Source Code Review | Compare historical versions for risky or missing logic | Simplifies audits |
| 🕵️ Commit Analysis | Track file renames or refactors automatically | Detects hidden changes |
| 🧠 Patch Verification | Confirm that a patch or fix exists in release | Ensures secure deployment |
| 🧾 Binary to Source Inspection | Decompile NuGet DLLs to readable C# for scanning | Makes .NET analysis transparent |
- NuGet scanning requires
ilspycmd. - Large archives or many versions can be limited with
--max-versions. - Files larger than 9.5 MB or known binary types are skipped for performance.
- All downloads are cached; re-runs reuse prior data to save bandwidth and time.
| Ecosystem | Keyword | Example Package Syntax |
|---|---|---|
| PyPI | pypi |
requests |
| npm | npm |
@angular/core or angular |
| Maven | maven |
org.apache.logging.log4j:log4j-core |
| Go | go |
github.com/gorilla/mux |
| PHP | php |
symfony/http-foundation |
| RubyGems | ruby |
rails |
| NuGet | nuget |
Newtonsoft.Json |
[+] MATCHES FOUND:
- 10.0.0:
Piranha.decompiled.cs (line 4560): public async Task SaveAsync(Language model)
- 10.0.0-alpha1:
Piranha.decompiled.cs (line 4531): public async Task SaveAsync(Language model)
- 10.0.2:
Summary: scanned 88 versions — hits: 24 — errors/no-file: 0
[+] Results saved to results.csv
Hemant Patidar (@HemantSolo) Senior Security Researcher • Penetration Tester • Bug Bounty Hunter • Ethical Hacker • Open Source Contributor
🔗 LinkedIn 🔗 Twitter / X
This project is released under the MIT License. Free for research, auditing, and educational purposes.
If you find this project useful for:
- Security Research
- Patch Verification
- Source Code Review
- Dependency Auditing
- Vulnerability Tracking
⭐ Star this repository and share it to support further open-source security research.