Fix Bandit B314: Replace xml.etree with defusedxml

Security scan (Bandit) identified vulnerable XML parsing in 3MF file
processing. The standard xml.etree.ElementTree is vulnerable to XXE
(XML External Entity) attacks.

Changes:
- Add defusedxml>=0.7.0 to requirements.txt
- Replace all xml.etree.ElementTree imports with defusedxml.ElementTree
  in production code (6 files)

Affected files:
- backend/app/services/archive.py
- backend/app/services/print_scheduler.py
- backend/app/api/routes/print_queue.py
- backend/app/api/routes/library.py
- backend/app/api/routes/printers.py
- backend/app/api/routes/archives.py

Test files intentionally left unchanged (test XML is trusted).
This commit is contained in:
maziggy
2026-02-05 17:30:14 +01:00
parent 5da769be31
commit 4b3b615a2c
7 changed files with 16 additions and 10 deletions
+6 -4
View File
@@ -1833,7 +1833,8 @@ async def get_archive_capabilities(
):
"""Check what viewing capabilities are available for this 3MF file."""
import json
import xml.etree.ElementTree as ET
import defusedxml.ElementTree as ET
service = ArchiveService(db)
archive = await service.get_archive(archive_id)
@@ -2113,7 +2114,7 @@ async def get_plate_preview(
plate_num = 1
if "Metadata/slice_info.config" in names:
try:
import xml.etree.ElementTree as ET
import defusedxml.ElementTree as ET
slice_content = zf.read("Metadata/slice_info.config").decode("utf-8")
root = ET.fromstring(slice_content)
@@ -2254,7 +2255,8 @@ async def get_archive_plates(
"""
import json
import re
import xml.etree.ElementTree as ET
import defusedxml.ElementTree as ET
service = ArchiveService(db)
archive = await service.get_archive(archive_id)
@@ -2560,7 +2562,7 @@ async def get_filament_requirements(
archive_id: The archive ID
plate_id: Optional plate index to filter filaments for (for multi-plate files)
"""
import xml.etree.ElementTree as ET
import defusedxml.ElementTree as ET
service = ArchiveService(db)
archive = await service.get_archive(archive_id)
+4 -2
View File
@@ -1312,9 +1312,10 @@ async def get_library_file_plates(
"""
import json
import re
import xml.etree.ElementTree as ET
import zipfile
import defusedxml.ElementTree as ET
# Get the library file
result = await db.execute(select(LibraryFile).where(LibraryFile.id == file_id))
lib_file = result.scalar_one_or_none()
@@ -1613,9 +1614,10 @@ async def get_library_file_filament_requirements(
file_id: The library file ID
plate_id: Optional plate index to get filaments for a specific plate
"""
import xml.etree.ElementTree as ET
import zipfile
import defusedxml.ElementTree as ET
# Get the library file
result = await db.execute(select(LibraryFile).where(LibraryFile.id == file_id))
lib_file = result.scalar_one_or_none()
+1 -1
View File
@@ -2,11 +2,11 @@
import json
import logging
import xml.etree.ElementTree as ET
import zipfile
from datetime import datetime
from pathlib import Path
import defusedxml.ElementTree as ET
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
+2 -1
View File
@@ -852,9 +852,10 @@ async def get_printer_file_plates(
"""Get available plates from a multi-plate 3MF file stored on a printer."""
import io
import json
import xml.etree.ElementTree as ET
import zipfile
import defusedxml.ElementTree as ET
# Validate printer
result = await db.execute(select(Printer).where(Printer.id == printer_id))
printer = result.scalar_one_or_none()
+1 -1
View File
@@ -6,8 +6,8 @@ import shutil
import zipfile
from datetime import datetime
from pathlib import Path
from xml.etree import ElementTree as ET
from defusedxml import ElementTree as ET
from sqlalchemy import and_, or_, select
from sqlalchemy.ext.asyncio import AsyncSession
+1 -1
View File
@@ -3,11 +3,11 @@
import asyncio
import json
import logging
import xml.etree.ElementTree as ET
import zipfile
from datetime import datetime, timedelta
from pathlib import Path
import defusedxml.ElementTree as ET
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
+1
View File
@@ -20,6 +20,7 @@ pyftpdlib>=2.0.0
cryptography>=41.0.0
# 3MF Processing (standard zipfile is sufficient for Bambu 3MF files)
defusedxml>=0.7.0 # Safe XML parsing (prevents XXE attacks)
# Excel Export
openpyxl>=3.1.0