Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<p align="center">
<a href="https://www.python.org/downloads/"><img alt="Python 3.12+" src="https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white" /></a>
<a href="https://github.com/TencentCloud/Octop/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-green" /></a>
<a href="https://github.com/TencentCloud/Octop/releases"><img alt="Version" src="https://img.shields.io/badge/version-1.0.2b6-orange" /></a>
<a href="https://github.com/TencentCloud/Octop/releases"><img alt="Version" src="https://img.shields.io/badge/version-1.0.2b7-orange" /></a>
<a href="https://pypi.org/project/octop/"><img src="https://img.shields.io/pypi/v/octop" alt="PyPI" /></a>
<a href="https://github.com/astral-sh/ruff"><img alt="Code Style: Ruff" src="https://img.shields.io/badge/code%20style-ruff-000000?logo=ruff&logoColor=white" /></a>
<a href="https://github.com/TencentCloud/Octop"><img alt="GitHub stars" src="https://img.shields.io/github/stars/TencentCloud/Octop?style=social" /></a>
Expand Down
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<p align="center">
<a href="https://www.python.org/downloads/"><img alt="Python 3.12+" src="https://img.shields.io/badge/python-3.12%2B-blue?logo=python&logoColor=white" /></a>
<a href="https://github.com/TencentCloud/Octop/blob/main/LICENSE"><img alt="License: MIT" src="https://img.shields.io/badge/license-MIT-green" /></a>
<a href="https://github.com/TencentCloud/Octop/releases"><img alt="Version" src="https://img.shields.io/badge/version-1.0.2b6-orange" /></a>
<a href="https://github.com/TencentCloud/Octop/releases"><img alt="Version" src="https://img.shields.io/badge/version-1.0.2b7-orange" /></a>
<a href="https://pypi.org/project/octop/"><img src="https://img.shields.io/pypi/v/octop" alt="PyPI" /></a>
<a href="https://github.com/astral-sh/ruff"><img alt="Code Style: Ruff" src="https://img.shields.io/badge/code%20style-ruff-000000?logo=ruff&logoColor=white" /></a>
<a href="https://github.com/TencentCloud/Octop"><img alt="GitHub stars" src="https://img.shields.io/github/stars/TencentCloud/Octop?style=social" /></a>
Expand Down
2 changes: 1 addition & 1 deletion fnos/docker/app/docker/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
octop:
image: ghcr.io/tencentcloud/octop:1.0.2b6
image: ghcr.io/tencentcloud/octop:1.0.2b7
container_name: octop
restart: unless-stopped
pull_policy: missing
Expand Down
2 changes: 1 addition & 1 deletion fnos/docker/manifest
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
appname=octop
version=1.0.2b6
version=1.0.2b7
display_name=Octop
desc=腾讯开源的多用户多智能体 AI 助手平台,支持 Web 控制台、CLI、IM 渠道与定时任务,数据全部本地存储。<br/><br/><strong>安装后使用:</strong><br/>首次会从 ghcr.io 下载与本包版本对应的镜像(设备需能访问 GitHub Container Registry),请等到应用中心显示「运行中」再点「打开」,或访问 http://设备IP:8088,用安装向导里设置的账号登录。<br/>忘记密码可到数据目录 octop-login.txt 查看备份(仅记录安装或应用「设置」改密;网页改密后不会自动更新)。<br/><br/><strong>首次登录后:</strong><br/>请在控制台「设置 → 模型」配置 API Key,并按需配置 IM 渠道、远程桌面、浏览器等。<br/><br/>注意:Docker 版通过容器部署,会拉取 ghcr.io/tencentcloud/octop 上与本包版本相同的镜像。
source=thirdparty
Expand Down
2 changes: 1 addition & 1 deletion fnos/native/manifest
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
appname=octop-native
version=1.0.2b6
version=1.0.2b7
display_name=Octop
desc=腾讯开源的多用户多智能体 AI 助手平台,支持 Web 控制台、CLI、IM 渠道与定时任务,数据全部本地存储。<br/><br/><strong>安装后使用:</strong><br/>请等到应用中心显示「运行中」再点「打开」,或访问 http://设备IP:8089,用安装向导里设置的用户名或邮箱登录。<br/>忘记密码时打开飞牛「文件管理」,进入应用共享里的 Octop 数据目录,查看 octop-login.txt(仅备份安装或应用「设置」改密;网页改密后不会自动更新);也可在应用「设置」中改密。<br/><br/><strong>命令行管理:</strong><br/>支持官方 octop CLI(octop provider list / agent list / user list / skills / backup 等,详见 octop --help)。<br/><br/><strong>首次登录后:</strong><br/>请在控制台「设置 → 模型」配置 API Key,并按需配置 IM 渠道、远程桌面、浏览器等。<br/><br/>注意:本地版直接运行在飞牛主机上,安装前会自动关联安装「Python 3.12」开发工具。
source=thirdparty
Expand Down
2 changes: 1 addition & 1 deletion src/octop/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from octop.infra.utils.httpx_proxy import install_httpx_cidr_no_proxy

__version__ = "1.0.2b6"
__version__ = "1.0.2b7"

# httpx 0.28 treats NO_PROXY CIDR as an exact IP (see issue #1347). Patch once
# at import so CLI, ``octop run``, and in-process harness clients all honor it.
Expand Down
7 changes: 7 additions & 0 deletions src/octop/infra/gateway/media/backend_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,14 @@ def is_allowed_host_temp_path(resolved: Path) -> bool:

def file_url_to_abs_path(file_url: str) -> str:
parsed = urllib.parse.urlparse(file_url)
netloc = parsed.netloc
path = parsed.path
# file://C:/… — two slashes, so urlparse puts the drive letter in netloc
# and path alone loses it. Without this the result is drive-relative
# (D:\Users\… when the workdir is on D:), which both escapes the
# containment check and writes somewhere the caller did not name.
if len(netloc) == 2 and netloc[1] == ":" and netloc[0].isalpha():
return str(Path(f"{netloc}{urllib.parse.unquote(path)}"))
# file:///C:/… — Windows drive in URL path
if len(path) >= 3 and path[0] == "/" and path[2] == ":":
return str(Path(urllib.parse.unquote(path[1:])))
Expand Down
25 changes: 25 additions & 0 deletions tests/unit/test_host_download_allow.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,28 @@ def test_file_url_windows_drive_decodes_unicode() -> None:
"""file:///C:/… must unquote and match native Path form (Windows CI)."""
url = "file:///C:/Users/me/out/%E4%BF%9D%E6%8A%A4.pptx"
assert file_url_to_abs_path(url) == str(Path("C:/Users/me/out/保护.pptx"))


def test_file_url_windows_drive_in_netloc_keeps_drive() -> None:
"""``file://C:/…`` — two slashes, so the drive lands in netloc, not path.

Windows CI builds these URLs from ``Path.as_posix()``, which yields
``file://C:/…``. ``urlparse`` puts ``C:`` in netloc, so reading ``path``
alone loses the drive and returns ``/Users/…``. On a runner whose workdir
is on D: that resolves drive-relative, which both escapes the containment
check and writes somewhere the caller did not name — SEC-2's file://
write test came back 200 instead of 403.
"""
assert file_url_to_abs_path("file://C:/Users/me/out/a.pptx") == str(
Path("C:/Users/me/out/a.pptx")
)
# Percent-decoding still applies on this branch.
assert file_url_to_abs_path("file://C:/Users/me/out/%E4%BF%9D%E6%8A%A4.pptx") == str(
Path("C:/Users/me/out/保护.pptx")
)
# The three-slash form is unchanged by the fix.
assert file_url_to_abs_path("file:///C:/Users/me/out/a.pptx") == str(
Path("C:/Users/me/out/a.pptx")
)
# A UNC host is still a host, not a drive letter.
assert file_url_to_abs_path("file://server/share/a.pptx") != str(Path("C:/share/a.pptx"))
Loading