✨(back) allow to disable checking unsafe mimetype on attachment upload
We added the possibility to scan all uploaded files with an anti malware solution. Depending the backend used, we want to give the possibility to check the file mimtype to determine if this one is tagged as unsafe or not. To this you can set the environment variable DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED to False. The default value is True.
This commit is contained in:
@@ -15,6 +15,7 @@ and this project adheres to
|
|||||||
- 📝(project) add system-requirement doc #1066
|
- 📝(project) add system-requirement doc #1066
|
||||||
- 🔧(front) configure x-frame-options to DENY in nginx conf #1084
|
- 🔧(front) configure x-frame-options to DENY in nginx conf #1084
|
||||||
- (doc) add documentation to install with compose #855
|
- (doc) add documentation to install with compose #855
|
||||||
|
- ✨(backend) allow to disable checking unsafe mimetype on attachment upload
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ These are the environment variables you can set for the `impress-backend` contai
|
|||||||
| DJANGO_EMAIL_USE_TLS | Use tls for email host connection | false |
|
| DJANGO_EMAIL_USE_TLS | Use tls for email host connection | false |
|
||||||
| DJANGO_SECRET_KEY | Secret key | |
|
| DJANGO_SECRET_KEY | Secret key | |
|
||||||
| DJANGO_SERVER_TO_SERVER_API_TOKENS | | [] |
|
| DJANGO_SERVER_TO_SERVER_API_TOKENS | | [] |
|
||||||
|
| DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED | Check mime type extension to determine if a file is unsafe or not. Can be disable if an antivirus is used in the MALWARE_DETECTION_BACKEND | True |
|
||||||
| DOCUMENT_IMAGE_MAX_SIZE | Maximum size of document in bytes | 10485760 |
|
| DOCUMENT_IMAGE_MAX_SIZE | Maximum size of document in bytes | 10485760 |
|
||||||
| FRONTEND_CSS_URL | To add a external css file to the app | |
|
| FRONTEND_CSS_URL | To add a external css file to the app | |
|
||||||
| FRONTEND_HOMEPAGE_FEATURE_ENABLED | Frontend feature flag to display the homepage | false |
|
| FRONTEND_HOMEPAGE_FEATURE_ENABLED | Frontend feature flag to display the homepage | false |
|
||||||
|
|||||||
@@ -517,7 +517,8 @@ class FileUploadSerializer(serializers.Serializer):
|
|||||||
mime = magic.Magic(mime=True)
|
mime = magic.Magic(mime=True)
|
||||||
magic_mime_type = mime.from_buffer(file.read(1024))
|
magic_mime_type = mime.from_buffer(file.read(1024))
|
||||||
file.seek(0) # Reset file pointer to the beginning after reading
|
file.seek(0) # Reset file pointer to the beginning after reading
|
||||||
|
self.context["is_unsafe"] = False
|
||||||
|
if settings.DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED:
|
||||||
self.context["is_unsafe"] = (
|
self.context["is_unsafe"] = (
|
||||||
magic_mime_type in settings.DOCUMENT_UNSAFE_MIME_TYPES
|
magic_mime_type in settings.DOCUMENT_UNSAFE_MIME_TYPES
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -439,3 +439,56 @@ def test_api_documents_attachment_upload_unsafe():
|
|||||||
"application/octet-stream",
|
"application/octet-stream",
|
||||||
]
|
]
|
||||||
assert file_head["ContentDisposition"] == 'attachment; filename="script.exe"'
|
assert file_head["ContentDisposition"] == 'attachment; filename="script.exe"'
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_attachment_upload_unsafe_mime_types_disabled(settings):
|
||||||
|
"""A file with an unsafe mime type but checking disabled should not be tagged as unsafe."""
|
||||||
|
settings.DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED = False
|
||||||
|
|
||||||
|
user = factories.UserFactory()
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory(users=[(user, "owner")])
|
||||||
|
url = f"/api/v1.0/documents/{document.id!s}/attachment-upload/"
|
||||||
|
|
||||||
|
file = SimpleUploadedFile(
|
||||||
|
name="script.exe", content=b"\x4d\x5a\x90\x00\x03\x00\x00\x00"
|
||||||
|
)
|
||||||
|
with mock.patch.object(malware_detection, "analyse_file") as mock_analyse_file:
|
||||||
|
response = client.post(url, {"file": file}, format="multipart")
|
||||||
|
|
||||||
|
assert response.status_code == 201
|
||||||
|
|
||||||
|
pattern = re.compile(rf"^{document.id!s}/attachments/(.*)\.exe")
|
||||||
|
url_parsed = urlparse(response.json()["file"])
|
||||||
|
assert url_parsed.path == f"/api/v1.0/documents/{document.id!s}/media-check/"
|
||||||
|
query = parse_qs(url_parsed.query)
|
||||||
|
assert query["key"][0] is not None
|
||||||
|
file_path = query["key"][0]
|
||||||
|
match = pattern.search(file_path)
|
||||||
|
file_id = match.group(1)
|
||||||
|
|
||||||
|
document.refresh_from_db()
|
||||||
|
assert document.attachments == [f"{document.id!s}/attachments/{file_id!s}.exe"]
|
||||||
|
|
||||||
|
assert "-unsafe" not in file_id
|
||||||
|
# Validate that file_id is a valid UUID
|
||||||
|
uuid.UUID(file_id)
|
||||||
|
|
||||||
|
key = file_path.replace("/media/", "")
|
||||||
|
mock_analyse_file.assert_called_once_with(key, document_id=document.id)
|
||||||
|
# Now, check the metadata of the uploaded file
|
||||||
|
file_head = default_storage.connection.meta.client.head_object(
|
||||||
|
Bucket=default_storage.bucket_name, Key=key
|
||||||
|
)
|
||||||
|
assert file_head["Metadata"] == {
|
||||||
|
"owner": str(user.id),
|
||||||
|
"status": "processing",
|
||||||
|
}
|
||||||
|
# Depending the libmagic version, the content type may change.
|
||||||
|
assert file_head["ContentType"] in [
|
||||||
|
"application/x-dosexec",
|
||||||
|
"application/octet-stream",
|
||||||
|
]
|
||||||
|
assert file_head["ContentDisposition"] == 'attachment; filename="script.exe"'
|
||||||
|
|||||||
@@ -212,7 +212,11 @@ class Base(Configuration):
|
|||||||
"application/x-msdownload",
|
"application/x-msdownload",
|
||||||
"application/xml",
|
"application/xml",
|
||||||
]
|
]
|
||||||
|
DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED = values.BooleanValue(
|
||||||
|
True,
|
||||||
|
environ_name="DOCUMENT_ATTACHMENT_CHECK_UNSAFE_MIME_TYPES_ENABLED",
|
||||||
|
environ_prefix=None,
|
||||||
|
)
|
||||||
# Document versions
|
# Document versions
|
||||||
DOCUMENT_VERSIONS_PAGE_SIZE = 50
|
DOCUMENT_VERSIONS_PAGE_SIZE = 50
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user