Hunting with Vulnhuntr: Getting Your First CVE
Your Path to Your First CVE Begins Here
Ready to bag your first CVE with Vulnhuntr? This step-by-step guide will walk you through the entire process—from installing the tool to reporting your findings and securing that coveted CVE number. Whether you're a seasoned bug hunter or just starting out, Vulnhuntr's ability to pinpoint vulnerabilities in open-source projects makes it a powerful ally in your security toolkit. Let’s dive in and get you one step closer to joining the ranks of CVE hunters.
Step 1: Installation
Ubuntu
Add deadsnakes PPA and install Python 3.10:
sudo add-apt-repository ppa:deadsnakes/ppa
sudo apt update
sudo apt install python3.10 python3.10-venv python3.10-dev
Install pip specifically for 3.10:
curl -sS https://bootstrap.pypa.io/get-pip.py | python3.10
Now you can install pipx using Python 3.10
python3.10 -m pip install --user pipx
python3.10 -m pipx ensurepath
Install Vulnhuntr:
pipx install git+https://github.com/protectai/vulnhuntr.git --python python3.10
Windows
A windows installation is similar, simply get the Python 3.10 installer from here https://www.python.org/downloads/release/python-3109/ then skip down to the pipx installation followed by the Vulnhuntr installation through pipx.
Step 2: Finding Target Projects
Bug Bounties
The platform huntr.com offers bounties and CVEs for reported vulnerabilities in open source projects. However, because Vulnhuntr has been out for a while now, many of the best potential targets may already be scanned by the tool. Successfully finding zero day vulnerabilities using Vulnhuntr alone on huntr.com will likely require you to set an alert for when huntr.com adds new target repositories and try to be the first to scan them. That being said, Vulnhuntr is still an excellent tool for scanning projects due to its ability to alert you to potential trouble spots in code even if it doesn’t directly find a vulnerability which gives you a great starting point for manual bug hunting. Claiming your first CVE in the wider open source ecosystem will likely be faster.
Searching Open Source Projects
Focus on open source pure Python projects that handle user input through a common Python web framework like Flask, Django, or FastAPI. Projects that mix languages heavily, like 60% Python and 40% JavaScript, may lead to incomplete analysis due to the limitations of static code tracing across multiple languages.
One easy way to find projects which may benefit from a Vulnhuntr security scan is to visit this list of FastAPI projects: https://kludex.github.io/awesome-fastapi-projects/. Sort by stars and find a good target that stands up a web server. Another option is to search GitHub directly. This GitHub dork can help narrow in on popular projects that stand up a web server:
in:readme flask OR django OR fastapi language:Python stars:>1000
Sort by most stars then scroll down til we find a project that appears to stand up a web server. A project named gpt_academic is on the first page and isn’t just a repository of tutorials. After clicking that link, we check what percentage of the project is made up of Python.
This looks good because Python is the large majority of the code and we know it’s using Flask, Django, or FastAPI.
You could stop here, clone the target repo, and simply run, `vulnhuntr -r /local/path/to/repo` however less tokens and higher quality results will occur if you do a quick search of the repo for the file or files that directly handle user input and specifically letting Vulnhuntr start there. To do that, we’ll do a quick project search depending on which framework the library uses. In this case, we know it’s using FastAPI so a quick search finds a couple files that look like good entry points: fastapi_server.py and toolbox.py.
“.route(“ is often another good search term for FastAPI or Flask applications to narrow down good starting target files.
Step 3: Running Vulnhuntr
With your target project and target files identified, clone the repository and run Vulnhuntr:
git clone https://github.com/binary-husky/gpt_academic
export ANTHROPIC_API_KEY="your-key-here"
vulnhuntr -r /path/to/cloned/folder/gpt_academic -a shared_utils/fastapi_server.py
Step 4: Interpreting Results
Vulnhuntr’s initial output will just be the multi-vulnerability assessment of the file alone, not the full assessment on the full call chain per vulnerability so this information is simply to inform you of where it’s about to start hunting. Running Vulnhuntr against the older, vulnerable version of gpt_academic will return a final analysis similar to this:
scratchpad:
1.Analyzing the file_code, focusing on network-related components and HTTP handlers. 2.Found previous SSRF through /vits endpoint in TTS functionality. 3.Examining additional HTTP routes and handlers. 4.Found
file handler endpoint that processes path_or_url parameter. 5.Analyzing validate_path_safety() and _authorize_user() functions that handle path validation. 6.Found that path_or_url is processed by
os.path.relpath() before validation. 7.Found that validate_path_safety() first converts path to relative path, then checks if it starts with sensitive paths. 8.Found that both validation functions allow accessing
'tests' and 'build' directories without restriction. 9.Crafting PoC to bypass path restrictions by using ../ sequences that get normalized by relpath(). 10.Confirmed that sensitive path checks are applied AFTER
path normalization, allowing directory traversal via ../ sequences.
----------------------------------------
analysis:
The code contains a directory traversal vulnerability in the file download endpoint that could lead to Local File Inclusion. The vulnerability exists because path validation in validate_path_safety() and
_authorize_user() is performed AFTER the path is normalized using os.path.relpath(). This allows an attacker to use ../ sequences to break out of the intended directory structure and access sensitive files. While
there are checks for sensitive paths like PATH_LOGGING and PATH_PRIVATE_UPLOAD, these are applied after path normalization, making them ineffective against path traversal. Additionally, the code explicitly allows
access to 'tests' and 'build' directories without any validation, which could be used as part of the attack path.
----------------------------------------
poc:
- Request to /file=tests/../path/to/sensitive/file - The path gets normalized by os.path.relpath() before validation 2. Since it starts with 'tests/', it passes the validation check 3. After normalization, the
actual file path accessed would be 'path/to/sensitive/file' 4. Example exploit URL: http://localhost:PORT/file=tests/../../../../etc/passwd
----------------------------------------
confidence_score:
9
----------------------------------------
vulnerability_types:
- LFI
----------------------------------------
The scratchpad is the model’s chain of thought. It’s useful for debugging the model’s thought process in cases of false positives or false negatives. The analysis section is best used for when the model thinks there’s a vulnerability but the proof of concept isn’t working out of the box. That section should help you with reading the target project’s source code and adjusting the proof-of-concept for accuracy. The proof of concept is the requests or commands necessary to exploit the vulnerability, and finally, Vulnhuntr generates confidence scores for each identified vulnerability:
- Score 8+: High confidence and likely a true positive.
- Score 7: Worth investigating but may require proof of concept tweaks.
- Score < 6: Unlikely to be a vulnerability.
We see from the output above that the tool is extremely confident in the LFI it found so let’s try making that request. Note the –path-as-is argument to stop curl from removing the path traversal:
Success!
Since LLMs can vary in output, it’s a good idea to run Vulnhuntr a few times to achieve comprehensive coverage.
Step 5: Contacting The Maintainer
Ideally, the target project has a Security.md file which you can read from here:
From which you can report the issue privately. Barring a security policy or report link there are several other methods of contacting the maintainer:
- Checking the owner’s GitHub page itself will sometimes lead to an email address
- Checking for a Discord channel to join
- Checking for the most active recent maintainer by commits and looking up their screen name
- Checking the project’s website if it exists
The key is to not contact anyone you’re not absolutely sure is an owner or high privilege developer of the project. Include in your contact that you’ll publish the vulnerability in 90 days after contact which is a reasonable amount of time to have the issue be fixed.
Step 6: Applying for a CVE
Several potential routes to use. If reported on huntr.com, a CVE will be automatically applied if it’s determined to be valid. If you’re able to report it via the project’s Security tab in GitHub then after it’s accepted by the maintainer you use the options in the security report on GitHub to request a CVE.
If neither of these routes exist, search to see if the project is listed under the CVE Numbering Authority (CNA) of a specific organization. For example, open source Apache projects are under the authority of the Apache Security Team which can issue CVEs themselves without going through MITRE. Reach out to the appropriate CNA if the project has one. If the project does not fall under the authority of a specific CNA, then you may continue on to the MITRE request form.
Start by visiting MITRE’s official CVE Request form (https://cveform.mitre.org/). You’ll need to fill in detailed information about the vulnerability to ensure it meets MITRE’s criteria including things like the CVSS score. LLMs such as Claude or ChatGPT can help you figure out an appropriate CVSS score. After submitting, MITRE will review your request. This process can take some time, especially if MITRE needs to verify additional details. If approved, then congratulations on using Vulnhuntr to get your first CVE!
Final Note
It will be enticing to see Vulnhuntr’s output saying it has 8 or 9 confidence in a finding, and simply pasting the analysis report to the maintainer of the project. DO NOT DO THIS! You MUST manually confirm and validate the finding by running the project, proving the vulnerability exists using tools like BurpSuite or curl, then and only then move on to contacting the maintainer. Maintainers do not want or appreciate security reports which are not manually verified because it often wastes their time. You are far more likely to have your future security reports to the project automatically rejected if you do not include the manual verification evidence in your report. Happy hunting!