DSH / Atlas
2026-09-08implementedfeaturearchived 2026-09-30

Authenticated file display reuses filesystem byte reads

鉴权文件展示复用文件系统字节读取

Session prose can reference screenshots in temporary directories or files stored by a remote filesystem provider. A Host-local workspace allowlist cannot serve those paths. An image response without a byte limit can also make the browser download a 1 GiB image before attempting to decode it.

English

Problem

Session prose can reference screenshots in temporary directories or files stored by a remote filesystem provider. A Host-local workspace allowlist cannot serve those paths. An image response without a byte limit can also make the browser download a 1 GiB image before attempting to decode it.

Decision

The authenticated /api/file route reads ordinary files through ctx.fs. Authentication and the composed provider's read policy govern access; directory and MIME allowlists do not. This supersedes the serving policy in the local-media display note, which retains renderer ownership and its rationale.

GET calls the existing readBytes(target, signal, maxBytes): providers reject known oversized files before content I/O and enforce the limit while reading. HEAD uses metadata without reading content. FS_TOO_LARGE becomes 413. MIME lookup supplies response metadata without sniffing file contents; unknown extensions use application/octet-stream. A sandbox CSP prevents directly opened HTML/SVG from executing with the authenticated API origin.

All files use the resolved ctx.attachments.imageLimits.maxImageBytes limit, normally 20 MiB. The attachment service owns this deployment setting. All responses contain complete files; Range is ignored and no range support is advertised.

Alternatives considered

Workspace and media allowlists. They limit which authenticated bytes can be read, but exclude ordinary screenshot locations and remote files. The chosen policy permits every regular file the composed provider can read.

A new filesystem byte-stream API. Efficient large-file delivery and audio/video seeking would require implementations in every provider, including remote range handling. Complete bounded reads satisfy the current display scope without widening that interface. Streaming and Range can be added when those use cases justify the provider work.

Duplicate size checks in the route. GET needs no additional stat/read loop: readBytes already owns preflight limits, growth detection, and cancellation. HEAD checks size separately because it must not read the body.

Consequences

Temporary and remote files use the same filesystem provider as read_image, without adding model-facing events. The local sandbox provider constrains mutations and permits reads; an authenticated client therefore has broader access than registered workspace roots. Files remain subject to the provider's permissions and the route's byte limits.

Each GET buffers the complete file in Host memory. Audio/video work as complete responses without incremental transfer or guaranteed seeking. Encoded byte limits do not bound decoded pixel dimensions. Failed image loads show authored alt text or the original destination when alt is empty.

Testing

Route tests cover sparse 1 GiB rejection before content I/O, post-stat growth, the shared attachment byte limit, ordinary MIME types, temporary paths and symlinks, opaque remote targets, provider failures, metadata-only HEAD, ignored Range, and disposal. Browser expectations cover rendered images, 413/404 and corrupt-image fallbacks, and an image outside the workspace. Remote byte transfer remains owned by the existing filesystem provider tests.

中文

Problem

会话正文可能引用临时目录中的截图或远程文件系统提供方中的文件。Host 本地工作区白名单无法提供这些路径。没有字节上限的图片响应还可能让浏览器先下载一张 1 GiB 图片,再尝试解码。

Decision

鉴权 /api/file 路由通过 ctx.fs 读取普通文件。鉴权和所组合提供方的读取策略决定访问权限;目录与 MIME 白名单不参与准入。这取代了本地媒体展示记录中的文件服务策略;该记录保留渲染器归属及其理由。

GET 调用现有 readBytes(target, signal, maxBytes):提供方在内容 I/O 前拒绝已知超限文件,并在读取过程中执行上限。HEAD 使用元数据,不读取内容。FS_TOO_LARGE 转换为 413。MIME 查询提供响应元数据,不嗅探文件内容;未知扩展名使用 application/octet-stream。sandbox CSP 阻止直接打开的 HTML/SVG 以鉴权 API 源身份执行脚本。

所有文件均使用已解析的 ctx.attachments.imageLimits.maxImageBytes 上限,通常为 20 MiB。附件服务拥有此部署配置。所有响应均包含完整文件;忽略 Range,也不声明支持 Range。

Alternatives considered

工作区和媒体白名单。 它们限制鉴权后能读取哪些字节,却排除了常见截图位置和远程文件。所选策略允许读取所组合提供方可读的任意普通文件。

新增文件系统字节流 API。 高效的大文件传输和音视频跳转需要每个提供方实现,包括远端 Range 处理。有界完整读取满足当前展示范围,无需扩展该接口。相关用例足以支持这项提供方工作时,可以加入流式传输与 Range。

在路由重复实现大小检查。 GET 无需额外的 stat/read 循环:readBytes 已经负责读取前上限、增长检测和取消。HEAD 单独检查大小,因为它不能读取正文。

Consequences

临时与远程文件使用与 read_image 相同的文件系统提供方,不增加模型可见事件。本地沙箱提供方约束变更操作并允许读取,因此鉴权客户端的访问范围大于已注册工作区根目录。文件仍受提供方权限和路由字节上限约束。

每个 GET 都会在 Host 内存中缓存完整文件。音视频使用完整响应,不支持增量传输,也不保证跳转播放。编码字节上限不限制解码后的像素尺寸。图片加载失败后展示作者提供的 alt 文本;alt 为空时展示原始目标路径。

Testing

路由测试覆盖内容 I/O 前拒绝稀疏 1 GiB 文件、stat 后增长、共用附件字节上限、普通 MIME 类型、临时路径与符号链接、不透明远程目标、提供方失败、仅元数据 HEAD、忽略 Range 和释放。浏览器期望覆盖图片渲染、413/404 及损坏图片回退,以及工作区之外的图片。远程字节传输仍由现有文件系统提供方测试负责。