Files
dify/api/services/file_scan/errors.py
JyongandClaude Fable 5.2 7d6c1845b8 feat(file-scan): scan uploaded knowledge base files for malware
Add a shared file malware-scanning module and use it in the Classic
Knowledge Base, RAG Pipeline local files and the Agent Knowledge Base.

- core/file_scan: scanner adapters for ClamAV (deployment-configured),
  Cloudmersive, Scanii, OPSWAT MetaDefender Cloud and API-based
  extensions (new `file.malware_scan` extension point).
- services/file_scan: FileScanService is the single entry point other
  modules call. Providers are workspace-wide; a policy belongs to a
  scope (dataset, knowledge_fs_space), so further modules can adopt
  scanning without schema changes.
- Each file is scanned on its own: a rejected file fails only its own
  document. Malware always blocks and deletes the stored original;
  invalid credentials and exhausted quota stop processing regardless of
  the "allow" fallback.
- Console: workspace scanner management and a per-knowledge-base
  policy section in both settings forms; the Agent Knowledge Base
  upload keeps going after a rejected file and explains each failure.
- Off by default behind FILE_SCAN_ENABLED.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-11 18:37:03 +08:00

26 lines
700 B
Python

from services.file_scan.entities import ScanOutcome
class FileScanError(Exception):
"""Base error of the file scan services."""
class FileScanValidationError(FileScanError, ValueError):
"""Provider or policy input is invalid."""
class FileScanProviderNotFoundError(FileScanError):
pass
class FileScanProviderInUseError(FileScanError):
"""The provider is selected by at least one policy and cannot be deleted."""
class FileScanBlockedError(FileScanError):
"""Raised by callers that stop a pipeline when ``ScanOutcome.allowed`` is false."""
def __init__(self, outcome: ScanOutcome) -> None:
super().__init__(outcome.describe())
self.outcome = outcome