Image attachments can overwrite each other #7707

Closed
opened 2025-12-29 20:27:17 +01:00 by adam · 5 comments
Owner

Originally created by @ChefAustin on GitHub (Mar 2, 2023).

NetBox version

v3.4.5

Python version

3.10

Steps to Reproduce

  1. Create a bogus Device Type, call it "JuniperRouter", and attach an image of a duck that has a filename of router.png
  2. View the "JuniperRouter" device type record that was just created and note that the picture of the duck (router.png) exists and is displayed properly
  3. Create a second bogus Device Type, call it "PaloAltoRouter", and attach an image of a porcupine that has a filename of router.png
  4. View the "PaloAltoRouter" device type record that was just created and note that the picture of the porcupine (router.png) exists and is displayed properly
  5. Navigate back to the "JuniperRouter" device type record that was created in step 1 above, and notice that the picture displayed is the porcupine (not the duck)

Expected Behavior

I expected either one of two (maybe three) behaviors:

  1. [Most ideal end-user experience] Under-the-hood, Netbox prepends/appends a model object-specific identifier (or some form of unique identifier) to the image attachment (i.e. JuniperRouter-router.png && PaloAltoRouter-router.png) to avoid filename collisions and overwrites.
  2. The record creation/modification request recognizes the impending collision, throws an error to the user, and fails to save.
  3. The record creation/modification request recognizes the impending collision, automatically appends a iterator value to the attached image's filename (which increments automatically upon each successive, impending collision), and proceeds with upload using the new filename.

Observed Behavior

When these reproduction steps are followed, the image attachments overwrite one another due to the fact that the image filename is the same. IOW, Netbox uploads the image with the "as-is filename" which results in the duck image being overwritten with the porcupine image.

Originally created by @ChefAustin on GitHub (Mar 2, 2023). ### NetBox version v3.4.5 ### Python version 3.10 ### Steps to Reproduce 1. Create a bogus Device Type, call it "JuniperRouter", and attach an image of a duck that has a filename of `router.png` 2. View the "JuniperRouter" device type record that was just created and note that the picture of the duck (`router.png`) exists and is displayed properly 3. Create a second bogus Device Type, call it "PaloAltoRouter", and attach an image of a porcupine that has a filename of `router.png` 4. View the "PaloAltoRouter" device type record that was just created and note that the picture of the porcupine (`router.png`) exists and is displayed properly 5. Navigate back to the "JuniperRouter" device type record that was created in step 1 above, and notice that the picture displayed is the porcupine (not the duck) ### Expected Behavior I expected either one of two (maybe three) behaviors: 1. [Most ideal end-user experience] Under-the-hood, Netbox prepends/appends a model object-specific identifier (or some form of unique identifier) to the image attachment (i.e. `JuniperRouter-router.png` && `PaloAltoRouter-router.png`) to avoid filename collisions and overwrites. 2. The record creation/modification request recognizes the impending collision, throws an error to the user, and fails to save. 3. The record creation/modification request recognizes the impending collision, automatically appends a iterator value to the attached image's filename (which increments automatically upon each successive, impending collision), and proceeds with upload using the new filename. ### Observed Behavior When these reproduction steps are followed, the image attachments overwrite one another due to the fact that the image filename is the same. IOW, Netbox uploads the image with the "as-is filename" which results in the duck image being overwritten with the porcupine image.
adam added the type: bugstatus: under review labels 2025-12-29 20:27:17 +01:00
adam closed this issue 2025-12-29 20:27:17 +01:00
Author
Owner

@jeremystretch commented on GitHub (Mar 7, 2023):

I'm not able to reproduce this, despite the delightfully entertaining instructions. 🙂 When the second file is uploaded, Django detects the duplicate filename and appends a random string to avoid overwriting the first file. The image associated with JuniperRouter is located at /media/devicetype-images/router.png, whereas the image associated with PaloAltoRouter is located at /media/devicetype-images/router_hUN1nRe.png. Both display their respective woodland creatures.

The automatic renaming is a function of Django's default storage backend, so I suspect one of two things is happening:

  1. You're using a different storage backend (e.g. django-storages) which is not handling this automatically; or
  2. NetBox has permission to write but not read files in the media path.

Can you confirm either of these conditions?

@jeremystretch commented on GitHub (Mar 7, 2023): I'm not able to reproduce this, despite the delightfully entertaining instructions. :slightly_smiling_face: When the second file is uploaded, Django detects the duplicate filename and appends a random string to avoid overwriting the first file. The image associated with JuniperRouter is located at `/media/devicetype-images/router.png`, whereas the image associated with PaloAltoRouter is located at `/media/devicetype-images/router_hUN1nRe.png`. Both display their respective woodland creatures. The automatic renaming is a function of Django's default [storage backend](https://docs.djangoproject.com/en/4.1/ref/files/storage/#django.core.files.storage.Storage.get_available_name), so I suspect one of two things is happening: 1. You're using a different storage backend (e.g. [django-storages](https://django-storages.readthedocs.io/en/stable/)) which is not handling this automatically; or 2. NetBox has permission to write but not read files in the media path. Can you confirm either of these conditions?
Author
Owner

@ChefAustin commented on GitHub (Mar 7, 2023):

Interesting.

You are correct insofar that I'm using S3 storage backend but Netbox does have full CRUD permissions on the storage path (bucket).

@ChefAustin commented on GitHub (Mar 7, 2023): Interesting. You are correct insofar that I'm using S3 storage backend but Netbox does have full CRUD permissions on the storage path (bucket).
Author
Owner

@jeremystretch commented on GitHub (Mar 7, 2023):

Thanks. It's almost certainly a limitation of the S3 backend then. We'll need to dig into it a bit further to determine if this is something that can be resolved upstream or if we need to accommodate the limitation in NetBox itself.

@jeremystretch commented on GitHub (Mar 7, 2023): Thanks. It's almost certainly a limitation of the S3 backend then. We'll need to dig into it a bit further to determine if this is something that can be resolved upstream or if we need to accommodate the limitation in NetBox itself.
Author
Owner

@kkthxbye-code commented on GitHub (Mar 7, 2023):

I don't think there's anything to fix here, he just needs to pass AWS_S3_FILE_OVERWRITE: False to STORAGE_CONFIG.

https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

https://docs.netbox.dev/en/stable/configuration/system/#storage_config

@kkthxbye-code commented on GitHub (Mar 7, 2023): I don't think there's anything to fix here, he just needs to pass `AWS_S3_FILE_OVERWRITE: False` to `STORAGE_CONFIG`. https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html https://docs.netbox.dev/en/stable/configuration/system/#storage_config
Author
Owner

@ChefAustin commented on GitHub (Mar 8, 2023):

Just added AWS_S3_FILE_OVERWRITE: False to STORAGE_CONFIG, tested, and confirmed that default overwrite behavior has been disabled. Works as desired now.

Thanks for the insights, @kkthxbye-code and @jeremystretch; much appreciated!

@ChefAustin commented on GitHub (Mar 8, 2023): Just added `AWS_S3_FILE_OVERWRITE: False` to `STORAGE_CONFIG`, tested, and confirmed that default overwrite behavior has been disabled. Works as desired now. Thanks for the insights, @kkthxbye-code and @jeremystretch; much appreciated!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/netbox#7707