Employ Indirect Object References Instead of Direct File Paths in open() Calls
Replace direct file path handling in open() calls with indirect object reference patterns where users provide opaque identifiers (UUIDs, database IDs, tokens) that the application maps to actual file paths, eliminating user control over paths passed to open() entirely. Implement database-backed file management: import uuid; class UploadedFile(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False); user = models.ForeignKey(User, on_delete=models.CASCADE); original_filename = models.CharField(max_length=255); storage_path = models.CharField(max_length=512); uploaded_at = models.DateTimeField(auto_now_add=True); file_size = models.IntegerField(); mime_type = models.CharField(max_length=100) where users receive UUID like '550e8400-e29b-41d4-a716-446655440000' instead of real filename. Access files via database lookup: file_record = UploadedFile.objects.get(id=uuid_from_request, user=request.user); with open(file_record.storage_path, 'rb') as f: content = f.read(); return FileResponse(f, filename=file_record.original_filename) where application controls paths passed to open() and enforces ownership through database query. For temporary file access, generate time-limited tokens: import secrets; from django.core.cache import cache; file_token = secrets.token_urlsafe(32); cache.set(f'file_access_{file_token}', {'file_id': str(file_obj.id), 'user_id': request.user.id}, timeout=3600); download_url = reverse('download_file', kwargs={'token': file_token}) then validate: token_data = cache.get(f'file_access_{token}'); if not token_data or token_data['user_id'] != request.user.id: raise PermissionDenied; file_obj = UploadedFile.objects.get(id=token_data['file_id']); with open(file_obj.storage_path, 'rb') as f: return FileResponse(f) providing secure temporary access without exposing paths. Implement signed URLs for downloads: from django.core.signing import TimestampSigner; signer = TimestampSigner(); signed_id = signer.sign(str(file_obj.id)); download_url = reverse('signed_download', kwargs={'signed_id': signed_id}) then verify: try: file_id = signer.unsign(signed_id, max_age=3600); except BadSignature: raise PermissionDenied; file_obj = UploadedFile.objects.get(id=file_id); with open(file_obj.storage_path, 'rb') as f: return FileResponse(f) preventing ID tampering. Use content-addressed storage with cryptographic hashes: import hashlib; file_content = uploaded_file.read(); file_hash = hashlib.sha256(file_content).hexdigest(); storage_subdir = file_hash[:2]; storage_path = Path(settings.SECURE_STORAGE) / storage_subdir / file_hash[2:4] / file_hash; storage_path.parent.mkdir(parents=True, exist_ok=True); with open(storage_path, 'wb') as f: f.write(file_content); FileRecord.objects.create(user_filename=uploaded_file.name, storage_hash=file_hash, storage_path=str(storage_path)) where users reference files by database ID, application maps to hash-based paths in open() calls. For user file organization, maintain virtual directory structures: class FileNode(models.Model): name = models.CharField(max_length=255); parent = models.ForeignKey('self', null=True, on_delete=models.CASCADE); user = models.ForeignKey(User, on_delete=models.CASCADE); actual_file = models.OneToOneField(UploadedFile, null=True, on_delete=models.CASCADE); node_type = models.CharField(choices=[('file', 'File'), ('folder', 'Folder')]) allowing user-friendly paths like 'My Documents/Reports/2024.pdf' mapped to secure storage paths in open(). Implement file access logging: class FileAccessLog(models.Model): file = models.ForeignKey(UploadedFile, on_delete=models.CASCADE); user = models.ForeignKey(User, on_delete=models.CASCADE); accessed_at = models.DateTimeField(auto_now_add=True); action = models.CharField(max_length=20); ip_address = models.GenericIPAddressField(); def log_file_access(file_obj, user, action, ip): FileAccessLog.objects.create(file=file_obj, user=user, action=action, ip_address=ip); with open(file_obj.storage_path, 'rb') as f: content = f.read() recording all access for audit trails. Create RESTful APIs using identifiers: @api_view(['GET']); def get_file_content(request, file_uuid): file_obj = get_object_or_404(UploadedFile, id=file_uuid, user=request.user); with open(file_obj.storage_path, 'r') as f: return Response({'content': f.read(), 'metadata': {'filename': file_obj.original_filename, 'size': file_obj.file_size}}) providing clean API without path exposure. Implement bulk operations: file_ids = request.data.get('file_ids', []); files = UploadedFile.objects.filter(id__in=file_ids, user=request.user); for file_obj in files: with open(file_obj.storage_path, 'rb') as f: archive.add(f, arcname=file_obj.original_filename) safely handling multiple files through IDs.