SA-4 SSRF protections implemented.

This commit is contained in:
2026-08-26 16:52:59 +02:00
parent 3e61302bf6
commit c70850b44d
9 changed files with 151 additions and 35 deletions
+12 -9
View File
@@ -5,10 +5,11 @@ import json
import logging
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen
from urllib.request import Request
from backend.app.plugins.base import BasePlugin
from backend.app.services.secret_store import decrypt_secret
from backend.app.services.mastodon_security import open_no_redirect, validate_public_instance
DEFAULT_POST_PREFIX = 'From my #LinkLog: '
logger = logging.getLogger(__name__)
@@ -50,9 +51,10 @@ class MastodonPlugin(BasePlugin):
config.update(json.loads(row['config']))
config['access_token'] = decrypt_secret(config.get('access_token', ''))
instance = str(config.get('instance', '')).strip().rstrip('/')
if instance and '://' not in instance:
instance = f'https://{instance}'
try:
instance = validate_public_instance(str(config.get('instance', '')))
except ValueError as error:
return {'status': 'failed', 'plugin': self.name, 'reason': str(error)}
access_token = str(config.get('access_token', '')).strip()
if not instance or not access_token:
logger.debug(
@@ -92,7 +94,7 @@ class MastodonPlugin(BasePlugin):
},
method='POST',
)
with urlopen(request, timeout=5) as response:
with open_no_redirect(request, timeout=5) as response:
response_body = response.read().decode('utf-8')
logger.debug(
'Mastodon post response: endpoint=%s status=%s body_length=%d',
@@ -139,9 +141,10 @@ class MastodonPlugin(BasePlugin):
config.update(json.loads(row['config']))
config['access_token'] = decrypt_secret(config.get('access_token', ''))
instance = str(config.get('instance', '')).strip().rstrip('/')
if instance and '://' not in instance:
instance = f'https://{instance}'
try:
instance = validate_public_instance(str(config.get('instance', '')))
except ValueError as error:
return {'status': 'failed', 'plugin': self.name, 'reason': str(error)}
access_token = str(config.get('access_token', '')).strip()
post_ids = event.get('mastodon_post_ids') or []
if not post_ids and event.get('mastodon_post_id'):
@@ -156,7 +159,7 @@ class MastodonPlugin(BasePlugin):
headers={'Authorization': f'Bearer {access_token}', 'User-Agent': 'LinkLog/1.0'},
method='DELETE',
)
with urlopen(request, timeout=5) as response:
with open_no_redirect(request, timeout=5) as response:
response.read()
return {'status': 'deleted', 'plugin': self.name, 'count': len(post_ids)}
except HTTPError as error: