[Security] [Feature Request]: File URI security and simplification.
Is there an existing issue for this?
- [X] I have searched the existing issues and checked the recent builds/commits
What would your feature do ?
For file-view URI's, omit the obvious... ;-)
I have a couple of other "things" I want to suggest/take a look at in the coming time, and this actually kind of sets the stage in a few ways.
When loading a rendered image, the path takes the form of {host}(:{port})/file={full_file_path}, the full_file_path includes everything from system root, up to the webui root, and subsequently images directory. This is not only redundant, but also a security concern, as anyone who has access to the WebUI can gain knowledge into the layout of the underlying file system.
There is a LOT there that is identical to each file, and therefore unnecessary. Additionally, most of that path is already known by the backend, so passing it from user-space is unnecessary.
As such, I propose the following:
Proposed workflow
- Re-structure the URI and subsequent back-end processing to take a
hintand relative file path.
Eg:127.0.0.1:7860/file=Q:/stable-diffusion-webui/outputs/img2img/file.pngBecomes:127.0.0.1:7860/file=img2img/file.png - The server sees
img2imgand auto-fills the remainder (if it sees a hint that does NOT exist, it fails). - Back-end verification of ownership and location can continue as it currently does (I did check for directory traversal, and was encouraged to see that that was prevented).
Additional information
Side-effect for a future date:
This would allow for instancing of image dirs, ie: If there is a user mechanism in the future, the path img2img/file.png leaks no information, and the backend can auto-expand it to an img2img sub-directory such as Q:/stable-diffusion-webui/outputs/img2img/{username}/file.png and validate accordingly, allowing for some cross-user privacy. (this is actually my primary request, but, baby-steps)
Your point is valid when default path is used, but what if it's on other drive for windows user? I assume full path was required to implement this.
The USER (in-so-far as the WebUI is concerned) shouldn't set their own path. WRT users in my enhancement, I am referring to WebUI users (logging in to the web front end). To clarify...
Bigger picture:
- Session handler added.
- (optional) User Management
- Authentication component added to accept usernames and passwords, and set Session information accordingly.
- Users are either hard-coded via YAML file, or SQLite DB (more involved, let's start with YAML).
- "Admin" can set paths as currently able, additionally have full access to settings.
- Users other than Admin (this includes un-authenticated users, which encompasses 'not' adding formal User Management), ONLY have access to Settings added to Quick Settings, etc (promoted from the Settings page).
- WRT file save paths: the base path that is set in Settings is used, and the system adds either the Session UUID, OR the Username (when Authentication is possible). Thus limiting the viewing of images to just your images.
Ok, I didn't want to get too much more involved. Yes, there are a LOT of other considerations:
- Converting "Batches" to some form of "Job Queue"
- Each User/Session can only have one "Job"
- Interleaving processing of Job Items between Users/Sessions
- I would have to look in to how things are currently processed, but I imagine there would have to be come converting to how user scripts execute (to allow, say, for X/Y Grid to have it's overall "Job," but each task is a single render).
- Switching between Job Contexts during Interleaving.
- MUCH more, I am sure...
The Jobs thing is kind of the "big wrench," but it also brings a lot to the table:
- Currently, the Web UI can get into a state where the render HAS stopped, but the UI is not unlocking it's self.
- Additionally, it is possible to have a render executing, and clock around, and LOSE CONTROL of the render (can't view it's progress, can't stop it).
- OR, accidental F5.
Having a Job Queue of some kind could alleviate all of that.
Again, I quite literally haven't looked at a line of code yet, for all I know this is neigh impossible, but something to think about.
This is comprehensive to the point where i'm confused.
First thing with the path: so you're suggesting that server is able to control path through some setting on backend, and users using frontend would be able to choose path only relative to it from there, right?
Current condition of this repo might surprise you, if you haven't look at the code. There's no separate server-client logic implemented here, all of it works on gradio and server is tightly connected with client. And honestly, that's a black box. Every other frontend for this repo that has been created uses REST API to run the same processing that starts when you press button in gradio ui.
And what do you mean by server and clients? Server being current instance of webui + gradio front to control it as host, and clients being those which use another frontend communicating through API? OR webui instance server and many gradio front clients?
Mind you, i'm no expert on the matter despite being collaborator, dont take my word for it, but i did a few pr's and i'm afraid to implement just those relative paths one would have to rethink whole current client-server relation, but to implement everything else you suggest means simply to rewrite it from scratch.
Ah, all front-end, you say... Good to know, that actually kind of helps, in a way...
Well... i wouldnt say it's frontend. I would say that's a template in a form of python scripts for gradio library to build it's server and provide appropriate client, and most of the interactions are hidden from us. That's how i see it.
Check out the examples and they will look familiar to you :D

Ah, nice, so Gradio generates the routes, UI, and Rest API, all from Python. Brilliant! That means the documentation is all in one spot... ;-)
Yahtzee!
Found the Queueing implimentation:
https://gradio.app/setting_up_a_demo_for_maximum_performance/#enabling-gradios-queueing-system (literally JUST found it, copied and pasted here, checking it out now).
One more note, for some reason API here implemented through fastapi, not Gradio. I have no idea why.
Annnnd Authentication!
https://gradio.app/sharing_your_app/#authentication
Likely using FastAPI for bidirectional. It is actually documented just below "Authentication" above.
Using the auth hooks provided, it should be trivial to do the rest... NEAT
Oh authentification is here already. https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings#command-line-arguments , but current state is not enough for what you described.
Oh authentification is here already. https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings#command-line-arguments
Yes, but this is flat auth (all at same access level, no restriction to Settings), and it doesn't do the compartmentalizing I was mentioning above, just auths to the app.
Yes, that's what i meant, "not enough".
Oh, sorry, typing fast.. :-)
The module responsible for queueing https://github.com/AUTOMATIC1111/stable-diffusion-webui/blob/master/modules/call_queue.py , as you can see it's not gradio, but manual queue lock. i assume that's why server itself maintains its queue perfectly, but sometimes desyncs with gradio frontend.