fiix: Database error information disclosure (#16634)

* fix: Loki LogQL Injection

* fiix: Database error information disclosure

* fix: timing-unsafe `bootstrap_token` comparison

---------

Co-authored-by: wangruidong <940853815@qq.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
This commit is contained in:
fit2bot
2026-07-08 16:28:53 +08:00
committed by GitHub
parent 1e2dc97156
commit 60608f149c
3 changed files with 26 additions and 5 deletions

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
#
import hmac
import time
from django.conf import settings
@@ -55,7 +56,10 @@ class WithBootstrapToken(permissions.BasePermission):
return False
request_bootstrap_token = authorization.split()[-1]
return settings.BOOTSTRAP_TOKEN == request_bootstrap_token
return hmac.compare_digest(
settings.BOOTSTRAP_TOKEN.encode(),
request_bootstrap_token.encode()
)
class ServiceAccountSignaturePermission(permissions.BasePermission):

View File

@@ -18,8 +18,11 @@ from django.urls import reverse
from django.utils import timezone
from rest_framework import status
from common.utils import get_logger
from .utils import set_current_request
logger = get_logger(__name__)
IGNORE_CSRF_CHECK = '*' in os.getenv("DOMAINS", "").split(',')
@@ -148,8 +151,9 @@ class EndMiddleware:
def process_exception(self, request, exception):
if isinstance(exception, OperationalError):
logger.debug("Database operational error: %s", exception)
return JsonResponse({
'error': 'Database OperationalError: ' + str(exception),
'error': 'Service temporarily unavailable',
'message': 'Database operation failed, please try again later.',
'code': 'DB_ERROR'
}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

View File

@@ -1,4 +1,5 @@
import os
import re
from django.utils.translation import get_language
@@ -15,11 +16,23 @@ class LokiMixin:
return get_loki_client()
@staticmethod
def create_loki_query(components, search):
def _escape_loki_regex(value):
# 转义 \ " { } | = ~ ! 等 LogQL stream selector 特殊字符
return re.sub(r'([\\"{}\[\]|=~!()])', r"\\\1", str(value))
@staticmethod
def _escape_loki_filter(value):
# 转义 line filter 中的 \ 和 " 防止逃逸
return str(value).replace("\\", "\\\\").replace('"', '\\"')
@classmethod
def create_loki_query(cls, components, search):
stream_selector = '{component!=""}'
if components:
stream_selector = '{component=~"%s"}' % components
query = f'{stream_selector} |="{search}"'
escaped = cls._escape_loki_regex(components)
stream_selector = '{component=~"%s"}' % escaped
escaped_search = cls._escape_loki_filter(search)
query = f'{stream_selector} |="{escaped_search}"'
return query