feat(security): strengthen theme security against multiple attack vectors
All checks were successful
Code check / Check code (push) Successful in 1m6s

- Detect dangerous modules, functions, attributes, and system/network operations
- Prevent code execution via dynamic imports, reflection, and importlib
- Block f-string injection and dangerous expressions
- Detect obfuscated code patterns, including string concatenation (im+port, ev+al),
  Base64-encoded payloads, and character code arrays
- Validate image files using extension checks, magic bytes, and size limits
- Implement AST-based analysis for deep code inspection

Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
2025-12-25 16:02:34 +05:00
parent 80d3b69311
commit 61c59814a5
3 changed files with 473 additions and 105 deletions

View File

@@ -3,7 +3,10 @@
import sys
from pathlib import Path
import re
import ast
# Import the security checker from the main module
sys.path.insert(0, str(Path(__file__).parent.parent)) # Add project root to path
from portprotonqt.theme_security import ThemeSecurityChecker
# Запрещенные QSS-свойства
FORBIDDEN_PROPERTIES = {
@@ -13,57 +16,29 @@ FORBIDDEN_PROPERTIES = {
"text-shadow",
}
# Запрещенные модули и функции
FORBIDDEN_MODULES = {
"os",
"subprocess",
"shutil",
"sys",
"socket",
"ctypes",
"pathlib",
"glob",
}
FORBIDDEN_FUNCTIONS = {
"exec",
"eval",
"open",
"__import__",
}
def check_qss_files():
has_errors = False
for qss_file in Path("portprotonqt/themes").glob("**/*.py"):
with open(qss_file, "r") as f:
# Check for forbidden QSS properties first
with open(qss_file, "r", encoding='utf-8') as f:
content = f.read()
# Проверка на запрещённые QSS-свойства
for prop in FORBIDDEN_PROPERTIES:
if re.search(rf"{prop}\s*:", content, re.IGNORECASE):
print(f"ERROR: Unknown QSS property found '{prop}' in file {qss_file}")
has_errors = True
# Проверка на опасные импорты и функции
try:
tree = ast.parse(content)
for node in ast.walk(tree):
# Проверка импортов
if isinstance(node, (ast.Import, ast.ImportFrom)):
for name in node.names:
if name.name in FORBIDDEN_MODULES:
print(f"ERROR: Forbidden module '{name.name}' found in file {qss_file}")
has_errors = True
# Проверка вызовов функций
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name) and node.func.id in FORBIDDEN_FUNCTIONS:
print(f"ERROR: Forbidden function '{node.func.id}' found in file {qss_file}")
has_errors = True
except SyntaxError as e:
print(f"ERROR: Syntax error in file {qss_file}: {e}")
for prop in FORBIDDEN_PROPERTIES:
if re.search(rf"{prop}\s*:", content, re.IGNORECASE):
print(f"ERROR: Unknown QSS property found '{prop}' in file {qss_file}")
has_errors = True
# Use the imported ThemeSecurityChecker to check for dangerous imports and functions
checker = ThemeSecurityChecker()
is_safe, errors = checker.check_theme_safety(str(qss_file))
if not is_safe:
for error in errors:
print(error)
has_errors = True
return has_errors
if __name__ == "__main__":
if check_qss_files():
sys.exit(1)
sys.exit(1)