Skip to content

Add domain allowlist and private IP blocking to prevent SSRF attacks#5

Closed
Copilot wants to merge 7 commits intosentinel/security-hardening-11579332874360293602from
copilot/add-url-validation-restrictions
Closed

Add domain allowlist and private IP blocking to prevent SSRF attacks#5
Copilot wants to merge 7 commits intosentinel/security-hardening-11579332874360293602from
copilot/add-url-validation-restrictions

Conversation

Copy link

Copilot AI commented Dec 13, 2025

The folder URL validation only checked HTTPS protocol, allowing SSRF attacks against internal services via URLs like https://localhost:8080/admin or https://192.168.1.1/.

Changes

  • Domain allowlist: Restrict URLs to github.com and githubusercontent.com (including subdomains)
  • IP address blocking: Reject direct IP access to private ranges (RFC 1918), loopback, link-local, and reserved addresses for both IPv4 and IPv6
  • Validation order: Check IP addresses before domain allowlist to prevent bypass attempts
  • Enhanced logging: Provide specific rejection reasons for debugging

Implementation

def validate_folder_url(url: str) -> bool:
    """
    Validate that the folder URL is safe (HTTPS only, trusted domains).
    Blocks SSRF attacks by allowing only trusted domains and blocking private IPs.
    """
    if not url.startswith("https://"):
        return False
    
    parsed = urlparse(url)
    host = parsed.hostname
    
    # Block private/loopback IPs
    try:
        ip = ipaddress.ip_address(host)
        if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved:
            return False
    except ValueError:
        pass  # Not an IP, continue to domain check
    
    # Allowlist domains
    ALLOWED_DOMAINS = {"github.com", "githubusercontent.com"}
    host_lower = host.lower()
    return any(host_lower == d or host_lower.endswith(f".{d}") for d in ALLOWED_DOMAINS)

Attack Vectors Mitigated

  • Localhost: https://localhost:8080/admin, https://127.0.0.1/
  • Private networks: https://192.168.1.1/, https://10.0.0.1/, https://172.16.0.1/
  • IPv6: https://[::1]/, https://[fd00::1]/
  • Untrusted domains: https://evil.com/malicious
Original prompt

Pull Request: #1

The folder URL validation only checks for the HTTPS protocol but doesn't validate the host. This could still allow SSRF attacks against internal services accessible via HTTPS (e.g., "https://localhost:8080/admin" or "https://192.168.1.1/"). Consider adding an allowlist of trusted domains (e.g., only allowing github.com and githubusercontent.com) or at minimum blocking private IP ranges and localhost.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI and others added 2 commits December 13, 2025 00:24
Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
…nt entry

Co-authored-by: abhimehro <84992105+abhimehro@users.noreply.github.com>
@abhimehro abhimehro marked this pull request as ready for review December 13, 2025 00:26
Copilot AI review requested due to automatic review settings December 13, 2025 00:26
Copilot AI changed the title [WIP] Enhance folder URL validation to prevent SSRF attacks Add domain allowlist and private IP blocking to prevent SSRF attacks Dec 13, 2025
Copilot AI requested a review from abhimehro December 13, 2025 00:28
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request enhances the folder URL validation function to prevent Server-Side Request Forgery (SSRF) attacks by implementing domain allowlisting and blocking private IP addresses. The changes address a security vulnerability where the previous implementation only validated the HTTPS protocol without checking the target host.

Key changes:

  • Added domain allowlist validation restricting URLs to github.com and githubusercontent.com (including subdomains)
  • Implemented IP address validation to block private, loopback, link-local, and reserved IP ranges for both IPv4 and IPv6
  • Added comprehensive error logging for different validation failure scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

main.py Outdated
Comment on lines +127 to +136
# First, check if the hostname is an IP address
# If it is, ensure it's not a private IP (reject all direct IP access)
try:
ip = ipaddress.ip_address(host)
if ip.is_private or ip.is_loopback or ip.is_link_local or ip.is_reserved:
log.warning(f"Skipping URL with private/internal IP address: {url}")
return False
except ValueError:
# Not an IP address, it's a domain name - continue with domain validation
pass
Copy link

Copilot AI Dec 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation only checks the hostname at URL parsing time, which doesn't protect against DNS rebinding attacks. An attacker could register a subdomain under github.com or githubusercontent.com (if possible) or exploit Time-of-Check-Time-of-Use (TOCTOU) issues where a domain resolves to a safe IP during validation but to a private IP during the actual HTTP request. Consider implementing additional protections such as: 1) Resolving the hostname to IP addresses before making requests and validating those IPs, or 2) Configuring the httpx client with connection restrictions to block private IP ranges at the connection level.

Copilot uses AI. Check for mistakes.
Comment on lines +114 to +117
ALLOWED_DOMAINS = {
"github.com",
"githubusercontent.com",
}
Copy link

Copilot AI Dec 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ALLOWED_DOMAINS constant is defined inside the function, which means it's recreated on every function call. Consider moving this to a module-level constant (e.g., after the imports or with other constants like API_BASE) to improve performance and make it easier to maintain and test. This would also make it more discoverable for future configuration needs.

Copilot uses AI. Check for mistakes.
abhimehro and others added 4 commits December 12, 2025 18:33
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@abhimehro abhimehro deleted the branch sentinel/security-hardening-11579332874360293602 December 13, 2025 00:35
@abhimehro abhimehro closed this Dec 13, 2025
@abhimehro abhimehro deleted the copilot/add-url-validation-restrictions branch December 13, 2025 00:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants