Description
LinkedInProfileValidator (src/ghdcbot/core/social_validators.py) me hostname validation missing hai. Validator sirf check karta hai ke URL me /in/ maujood hai ya nahi, lekin yeh verify nahi karta ke domain linkedin.com hai.
Impact
- Severity: High (CWE-20: Improper Input Validation, CWE-601: URL Redirection to Untrusted Site)
- Attack Scenario: An attacker links a malicious credential-harvesting site (e.g.
https://evil-phishing.com/in/target) via /connect-social platform:LinkedIn profile:https://evil-phishing.com/in/target.
- Public Visibility: The URL is displayed in Discord
/profile embeds, where community members may trust and click it as a verified LinkedIn profile.
Technical Details & Root Cause
In src/ghdcbot/core/social_validators.py:
@staticmethod
def _normalize_url(url: str) -> str:
url = url.strip()
# Ensure https
if url.startswith("http://"):
url = "https://" + url[7:]
elif not url.startswith("https://"):
url = "https://" + url
# Remove www if present (normalize to linkedin.com)
url = url.replace("www.linkedin.com", "linkedin.com")
# Remove trailing slashes and query params
url = url.split("?")[0].rstrip("/")
# Reject company pages
if "/company/" in url or "/companies/" in url or "/school/" in url:
raise ValueError("Company and school pages are not supported, only personal profiles")
# Must be in /in/ path for personal profiles
if "/in/" not in url:
raise ValueError("Only LinkedIn profile URLs (linkedin.com/in/...) are supported")
return url
Key Flaws:
No Hostname Check: The validator relies purely on string manipulation (.replace("www.linkedin.com", "linkedin.com")) and a substring check (if "/in/" not in url:).
Inconsistency with other validators: In contrast, XProfileValidator uses urllib.parse.urlparse to strictly assert:
python
if host in {"x.com", "twitter.com"}:
Spoofing Vulnerability: URLs such as https://linkedin.com.attacker.com/in/victim or https://evil-phishing.com/in/victim pass _normalize_url and _extract_profile_id.
Exception Handling: Rejection currently relies on downstream Pydantic model initialization, which raises an unhandled pydantic_core.ValidationError rather than a clean, user-friendly ValueError expected by the command handler.
### Steps to Reproduce
from ghdcbot.core.social_validators import LinkedInProfileValidator
validator = LinkedInProfileValidator()
normalized = validator._normalize_url("https://evil-phishing.com/in/target")
profile_id = validator._extract_profile_id("https://evil-phishing.com/in/target")
print("Normalized:", normalized) # Output: https://evil-phishing.com/in/target
print("Profile ID:", profile_id) # Output: target
## Proposed Fix
### 1. In `src/ghdcbot/core/social_validators.py` (`LinkedInProfileValidator`):
- Parse the URL using `urllib.parse.urlparse`.
- Validate that the scheme is `http` or `https` (and canonicalize to `https://`).
- Extract `hostname`, strip leading `www.`, and enforce that it strictly matches `linkedin.com`.
- Validate that the path strictly matches `/in/<profile-id>`.
- Raise clean `ValueError` exceptions with descriptive error messages.
### 2. In `tests/test_social_validators.py`:
- Add unit tests verifying rejection of:
- `https://evil-phishing.com/in/target`
- `https://linkedin.com.attacker.org/in/target`
- `https://fake-linkedin.com/in/target`
- Malicious schemes (e.g., `javascript:`, `ftp:`)
---
## Acceptance Criteria
- [ ] `LinkedInProfileValidator.validate()` rejects non-LinkedIn domains containing `/in/`.
- [ ] Subdomain spoofing (e.g. `linkedin.com.attacker.com`) is rejected with a `ValueError`.
- [ ] Valid LinkedIn formats (`https://linkedin.com/in/user`, `https://www.linkedin.com/in/user`, `linkedin.com/in/user`) continue to pass.
- [ ] All test suites pass cleanly (`pytest tests/test_social_validators.py`).
### Logs and Screenshots
_No response_
### Environment Details
_No response_
### Impact
High - Major feature is broken
### Code of Conduct
- [x] I have joined the [Discord server](https://discord.gg/hjUhu33uAn) and will post updates there
- [x] I have searched existing issues to avoid duplicates
Description
LinkedInProfileValidator(src/ghdcbot/core/social_validators.py) me hostname validation missing hai. Validator sirf check karta hai ke URL me/in/maujood hai ya nahi, lekin yeh verify nahi karta ke domainlinkedin.comhai.Impact
https://evil-phishing.com/in/target) via/connect-social platform:LinkedIn profile:https://evil-phishing.com/in/target./profileembeds, where community members may trust and click it as a verified LinkedIn profile.Technical Details & Root Cause
In
src/ghdcbot/core/social_validators.py: