mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-06-30 19:00:57 +08:00
feat(skills): harden the file upload validation section in django-security (#2338)
* feat(skills): harden the file upload validation section in django-security * Update skills/django-security/SKILL.md Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * add missing stuff to second code block * add import to the top of the code block --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
This commit is contained in:
parent
ec4925135c
commit
8c75abf02e
@ -392,27 +392,77 @@ def webhook_view(request):
|
||||
|
||||
```python
|
||||
import os
|
||||
import magic # pip install python-magic
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
def validate_file_extension(value):
|
||||
"""Validate file extension."""
|
||||
ext = os.path.splitext(value.name)[1]
|
||||
valid_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.pdf']
|
||||
if not ext.lower() in valid_extensions:
|
||||
raise ValidationError('Unsupported file extension.')
|
||||
ALLOWED_MIMES = {
|
||||
'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
|
||||
}
|
||||
|
||||
MIME_TO_EXTENSIONS = {
|
||||
'image/jpeg': {'.jpg', '.jpeg'},
|
||||
'image/png': {'.png'},
|
||||
'image/gif': {'.gif'},
|
||||
'application/pdf': {'.pdf'},
|
||||
}
|
||||
|
||||
def validate_file_type(value):
|
||||
"""Validate file type using magic bytes and cross-check extension."""
|
||||
mime = magic.from_buffer(value.read(2048), mime=True)
|
||||
value.seek(0)
|
||||
|
||||
if mime not in ALLOWED_MIMES:
|
||||
raise ValidationError('Unsupported file type.')
|
||||
|
||||
ext = os.path.splitext(value.name)[1].lower()
|
||||
if ext not in MIME_TO_EXTENSIONS.get(mime, set()):
|
||||
raise ValidationError('File extension does not match file content.')
|
||||
|
||||
def validate_file_size(value):
|
||||
"""Validate file size (max 5MB)."""
|
||||
filesize = value.size
|
||||
if filesize > 5 * 1024 * 1024:
|
||||
if value.size > 5 * 1024 * 1024:
|
||||
raise ValidationError('File too large. Max size is 5MB.')
|
||||
|
||||
# models.py
|
||||
class Document(models.Model):
|
||||
file = models.FileField(
|
||||
upload_to='documents/',
|
||||
validators=[validate_file_extension, validate_file_size]
|
||||
validators=[validate_file_type, validate_file_size]
|
||||
)
|
||||
|
||||
```
|
||||
|
||||
For environments where installing libmagic is difficult (e.g., minimal containers),
|
||||
use the pure-Python `filetype` package as an alternative:
|
||||
|
||||
```python
|
||||
import os
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
import filetype # pip install filetype
|
||||
|
||||
ALLOWED_MIMES = {
|
||||
'image/jpeg', 'image/png', 'image/gif', 'application/pdf',
|
||||
}
|
||||
|
||||
MIME_TO_EXTENSIONS = {
|
||||
'image/jpeg': {'.jpg', '.jpeg'},
|
||||
'image/png': {'.png'},
|
||||
'image/gif': {'.gif'},
|
||||
'application/pdf': {'.pdf'},
|
||||
}
|
||||
|
||||
def validate_file_type(value):
|
||||
"""Validate file type using magic bytes."""
|
||||
kind = filetype.guess(value.read(2048))
|
||||
value.seek(0)
|
||||
|
||||
if kind is None or kind.mime not in ALLOWED_MIMES:
|
||||
raise ValidationError('Unsupported file type.')
|
||||
|
||||
ext = os.path.splitext(value.name)[1].lower()
|
||||
if ext not in MIME_TO_EXTENSIONS.get(kind.mime, set()):
|
||||
raise ValidationError('File extension does not match file content.')
|
||||
```
|
||||
|
||||
### Secure File Storage
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user