Harden security
This commit is contained in:
@@ -17,6 +17,10 @@ from django.core.cache import cache
|
||||
|
||||
from core.clients import signalapi
|
||||
from core.messaging import media_bridge
|
||||
from core.security.attachments import (
|
||||
validate_attachment_metadata,
|
||||
validate_attachment_url,
|
||||
)
|
||||
from core.transports.capabilities import supports, unsupported_reason
|
||||
from core.util import logs
|
||||
|
||||
@@ -665,17 +669,21 @@ async def _normalize_gateway_attachment(service: str, row: dict, session):
|
||||
if isinstance(content, memoryview):
|
||||
content = content.tobytes()
|
||||
if isinstance(content, bytes):
|
||||
filename, content_type = validate_attachment_metadata(
|
||||
filename=normalized.get("filename") or "attachment.bin",
|
||||
content_type=normalized.get("content_type") or "application/octet-stream",
|
||||
size=normalized.get("size") or len(content),
|
||||
)
|
||||
blob_key = media_bridge.put_blob(
|
||||
service=service,
|
||||
content=content,
|
||||
filename=normalized.get("filename") or "attachment.bin",
|
||||
content_type=normalized.get("content_type") or "application/octet-stream",
|
||||
filename=filename,
|
||||
content_type=content_type,
|
||||
)
|
||||
return {
|
||||
"blob_key": blob_key,
|
||||
"filename": normalized.get("filename") or "attachment.bin",
|
||||
"content_type": normalized.get("content_type")
|
||||
or "application/octet-stream",
|
||||
"filename": filename,
|
||||
"content_type": content_type,
|
||||
"size": normalized.get("size") or len(content),
|
||||
}
|
||||
|
||||
@@ -685,33 +693,39 @@ async def _normalize_gateway_attachment(service: str, row: dict, session):
|
||||
source_url = normalized.get("url")
|
||||
if source_url:
|
||||
try:
|
||||
async with session.get(source_url) as response:
|
||||
safe_url = validate_attachment_url(source_url)
|
||||
async with session.get(safe_url) as response:
|
||||
if response.status == 200:
|
||||
payload = await response.read()
|
||||
blob_key = media_bridge.put_blob(
|
||||
service=service,
|
||||
content=payload,
|
||||
filename, content_type = validate_attachment_metadata(
|
||||
filename=normalized.get("filename")
|
||||
or source_url.rstrip("/").split("/")[-1]
|
||||
or safe_url.rstrip("/").split("/")[-1]
|
||||
or "attachment.bin",
|
||||
content_type=normalized.get("content_type")
|
||||
or response.headers.get(
|
||||
"Content-Type", "application/octet-stream"
|
||||
),
|
||||
size=normalized.get("size") or len(payload),
|
||||
)
|
||||
blob_key = media_bridge.put_blob(
|
||||
service=service,
|
||||
content=payload,
|
||||
filename=filename,
|
||||
content_type=content_type,
|
||||
)
|
||||
return {
|
||||
"blob_key": blob_key,
|
||||
"filename": normalized.get("filename")
|
||||
or source_url.rstrip("/").split("/")[-1]
|
||||
or "attachment.bin",
|
||||
"content_type": normalized.get("content_type")
|
||||
or response.headers.get(
|
||||
"Content-Type", "application/octet-stream"
|
||||
),
|
||||
"filename": filename,
|
||||
"content_type": content_type,
|
||||
"size": normalized.get("size") or len(payload),
|
||||
}
|
||||
except Exception:
|
||||
log.warning("%s attachment fetch failed for %s", service, source_url)
|
||||
except Exception as exc:
|
||||
log.warning(
|
||||
"%s attachment fetch failed for %s: %s",
|
||||
service,
|
||||
source_url,
|
||||
exc,
|
||||
)
|
||||
return normalized
|
||||
|
||||
|
||||
@@ -1074,21 +1088,27 @@ async def fetch_attachment(service: str, attachment_ref: dict):
|
||||
if blob_key:
|
||||
return media_bridge.get_blob(blob_key)
|
||||
if direct_url:
|
||||
safe_url = validate_attachment_url(direct_url)
|
||||
timeout = aiohttp.ClientTimeout(total=20)
|
||||
async with aiohttp.ClientSession(timeout=timeout) as session:
|
||||
async with session.get(direct_url) as response:
|
||||
async with session.get(safe_url) as response:
|
||||
if response.status != 200:
|
||||
return None
|
||||
content = await response.read()
|
||||
return {
|
||||
"content": content,
|
||||
"content_type": response.headers.get(
|
||||
filename, content_type = validate_attachment_metadata(
|
||||
filename=attachment_ref.get("filename")
|
||||
or safe_url.rstrip("/").split("/")[-1]
|
||||
or "attachment.bin",
|
||||
content_type=response.headers.get(
|
||||
"Content-Type",
|
||||
attachment_ref.get("content_type", "application/octet-stream"),
|
||||
),
|
||||
"filename": attachment_ref.get("filename")
|
||||
or direct_url.rstrip("/").split("/")[-1]
|
||||
or "attachment.bin",
|
||||
size=len(content),
|
||||
)
|
||||
return {
|
||||
"content": content,
|
||||
"content_type": content_type,
|
||||
"filename": filename,
|
||||
"size": len(content),
|
||||
}
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user