Spaces:
Sleeping
Sleeping
Download scripts/lib/chat/safe_chatbot.py from defenestrate/asa: direct link, hf CLI and curl.
- Browser
- Download file 2.17 kB
-
https://huggingface.co/spaces/defenestrate/asa/resolve/main/scripts/lib/chat/safe_chatbot.py
- Command line
-
hf download hf://spaces/defenestrate/asa/scripts/lib/chat/safe_chatbot.py
-
curl -L -o safe_chatbot.py https://huggingface.co/spaces/defenestrate/asa/resolve/main/scripts/lib/chat/safe_chatbot.py
2.17 kB
| """A Chatbot that never turns message text into file downloads. | |
| Gradio 4.44.1's ``Chatbot(type="messages")`` checks every space-separated | |
| word of every message with ``Path(word).is_file()`` and, on a match, copies | |
| that file into its cache and sends it to the browser as a download. Since | |
| the user's own message is echoed into the chatbot, any logged-in user could | |
| type a server path (``/proc/self/environ``, a knowledge-pack file) and | |
| download it, secrets included. Our chats only ever show text, so this | |
| subclass keeps the message and drops the file extraction. | |
| It also refuses to move any file or URL into its cache. A crafted request | |
| can put a file entry in the chat history it sends; for a URL, Gradio | |
| downloads it on the server and hands back the result (a server-side | |
| request forgery). Refusing the move stops both before anything is read | |
| or fetched. | |
| """ | |
| from __future__ import annotations | |
| import gradio as gr | |
| from gradio.components.chatbot import ChatMessage, Message | |
| class TextOnlyChatbot(gr.Chatbot): | |
| # The browser picks a component's code by this name. A subclass would | |
| # report "textonlychatbot", which the page then tries to load as a | |
| # custom component that doesn't exist, and it spins forever after login. | |
| # It is the stock Chatbot on the page; only the server side differs. | |
| def get_block_name(self) -> str: | |
| return "chatbot" | |
| def move_resource_to_block_cache(self, url_or_file_path): # type: ignore[override] | |
| raise gr.Error("This chat accepts text only.") | |
| async def async_move_resource_to_block_cache(self, url_or_file_path): # type: ignore[override] | |
| raise gr.Error("This chat accepts text only.") | |
| def _postprocess_message_messages(self, message): # type: ignore[override] | |
| if isinstance(message, dict): | |
| message["content"] = self._postprocess_content(message["content"]) | |
| return [Message(**message)] | |
| if isinstance(message, ChatMessage): | |
| content = self._postprocess_content(message.content) | |
| return [Message(role=message.role, content=content, metadata=message.metadata)] | |
| return super()._postprocess_message_messages(message) | |