block urls pointing to internal addresses (#1012)

This commit is contained in:
Shuchang Zheng
2024-10-20 18:33:05 -07:00
committed by GitHub
parent b31b77707c
commit 3e40267cfa
4 changed files with 41 additions and 2 deletions

View File

@@ -34,6 +34,7 @@ class Settings(BaseSettings):
LOG_LEVEL: str = "INFO" LOG_LEVEL: str = "INFO"
PORT: int = 8000 PORT: int = 8000
ALLOWED_ORIGINS: list[str] = ["*"] ALLOWED_ORIGINS: list[str] = ["*"]
BLOCKED_HOSTS: list[str] = ["localhost"]
# Secret key for JWT. Please generate your own secret key in production # Secret key for JWT. Please generate your own secret key in production
SECRET_KEY: str = "PLACEHOLDER" SECRET_KEY: str = "PLACEHOLDER"

View File

@@ -502,3 +502,11 @@ class InvalidUrl(SkyvernHTTPException):
super().__init__( super().__init__(
f"Invalid URL: {url}. Skyvern supports HTTP and HTTPS urls.", status_code=status.HTTP_400_BAD_REQUEST f"Invalid URL: {url}. Skyvern supports HTTP and HTTPS urls.", status_code=status.HTTP_400_BAD_REQUEST
) )
class BlockedHost(SkyvernHTTPException):
def __init__(self, host: str) -> None:
super().__init__(
f"The host in your url is blocked: {host}",
status_code=status.HTTP_400_BAD_REQUEST,
)

View File

@@ -1,5 +1,8 @@
import ipaddress
from pydantic import HttpUrl, ValidationError, parse_obj_as from pydantic import HttpUrl, ValidationError, parse_obj_as
from skyvern.config import settings
from skyvern.exceptions import InvalidUrl from skyvern.exceptions import InvalidUrl
@@ -11,3 +14,18 @@ def validate_url(url: str) -> str:
except ValidationError: except ValidationError:
# Handle the validation error # Handle the validation error
raise InvalidUrl(url=url) raise InvalidUrl(url=url)
def is_blocked_host(host: str) -> bool:
try:
ip = ipaddress.ip_address(host)
# Check if the IP is private, link-local, loopback, or reserved
return ip.is_private or ip.is_link_local or ip.is_loopback or ip.is_reserved
except ValueError:
# If the host is not a valid IP address (e.g., it's a domain name like localhost), handle it here
for blocked_host in settings.BLOCKED_HOSTS:
if blocked_host == host:
return True
return False
except Exception:
return False

View File

@@ -4,9 +4,10 @@ from datetime import datetime
from enum import StrEnum from enum import StrEnum
from typing import Any from typing import Any
from pydantic import BaseModel, Field, HttpUrl from pydantic import BaseModel, Field, HttpUrl, field_validator
from skyvern.exceptions import InvalidTaskStatusTransition, TaskAlreadyCanceled from skyvern.exceptions import BlockedHost, InvalidTaskStatusTransition, TaskAlreadyCanceled
from skyvern.forge.sdk.core.validators import is_blocked_host
class ProxyLocation(StrEnum): class ProxyLocation(StrEnum):
@@ -89,6 +90,17 @@ class TaskRequest(TaskBase):
) )
totp_verification_url: HttpUrl | None = None totp_verification_url: HttpUrl | None = None
@field_validator("url", "webhook_callback_url", "totp_verification_url")
@classmethod
def validate_urls(cls, v: HttpUrl | None) -> HttpUrl | None:
if not v or not v.host:
return None
host = v.host
blocked = is_blocked_host(host)
if blocked:
raise BlockedHost(host=host)
return v
class TaskStatus(StrEnum): class TaskStatus(StrEnum):
created = "created" created = "created"