Skip to content

Commit f323c6e

Browse files
committed
security: improve URL validation in Confluence base class
1 parent 8b81956 commit f323c6e

File tree

1 file changed

+39
-7
lines changed

1 file changed

+39
-7
lines changed

atlassian/confluence/base.py

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,48 @@ def _is_cloud_url(url: str) -> bool:
7878
url: The URL to validate
7979
8080
Returns:
81-
bool: True if the URL is a valid Confluence Cloud URL
81+
bool: True if the URL is a valid Confluence Cloud URL, False otherwise
82+
83+
Security:
84+
This method implements strict URL validation:
85+
- Only allows http:// and https:// schemes
86+
- Properly validates domain names using full hostname matching
87+
- Prevents common URL parsing attacks
8288
"""
83-
parsed = urlparse(url)
84-
# Ensure we have a valid URL with a hostname
85-
if not parsed.hostname:
89+
try:
90+
parsed = urlparse(url)
91+
92+
# Validate scheme
93+
if parsed.scheme not in ('http', 'https'):
94+
return False
95+
96+
# Ensure we have a valid hostname
97+
if not parsed.hostname:
98+
return False
99+
100+
# Convert to lowercase for comparison
101+
hostname = parsed.hostname.lower()
102+
103+
# Split hostname into parts and validate
104+
parts = hostname.split('.')
105+
106+
# Must have at least 3 parts (e.g., site.atlassian.net)
107+
if len(parts) < 3:
108+
return False
109+
110+
# Check exact matches for allowed domains
111+
# This prevents attacks like: evil.com?atlassian.net
112+
# or malicious-atlassian.net.evil.com
113+
if hostname.endswith('.atlassian.net'):
114+
return hostname == f"{parts[-3]}.atlassian.net"
115+
elif hostname.endswith('.jira.com'):
116+
return hostname == f"{parts[-3]}.jira.com"
117+
86118
return False
87119

88-
# Check if the hostname ends with .atlassian.net or .jira.com
89-
hostname = parsed.hostname.lower()
90-
return hostname.endswith('.atlassian.net') or hostname.endswith('.jira.com')
120+
except Exception:
121+
# Any parsing error means invalid URL
122+
return False
91123

92124
def __init__(
93125
self,

0 commit comments

Comments
 (0)