Commit graph

85 commits

Author SHA1 Message Date
Classic298
2e16a761ee
refactor: scope tool export to tools the caller can write (#29310)
The bulk tool export returned every tool the caller could read, while the per-tool export path returns only what the caller can write. This aligns the two, matching how model export already scopes its query.

Callers still export their own tools and any tool shared with them for writing; admins running with BYPASS_ADMIN_ACCESS_CONTROL are unaffected.
2026-09-06 17:44:45 -04:00
Timothy Jaeryang Baek
5c62cc0517 chore: format 2026-08-25 16:53:53 -04:00
Timothy Jaeryang Baek
4807866a1c refac
Co-Authored-By: Classic298 <27028174+Classic298@users.noreply.github.com>
2026-08-23 01:31:30 -04:00
Timothy Jaeryang Baek
954613944b refac 2026-08-16 23:51:38 -07:00
Classic298
c05de13b4f
fix: do not expose tool source code to read-only users (#27005)
* fix: do not expose tool source code to read-only users

The tool read endpoints build their responses from a content-bearing model via
model_dump() under ConfigDict(extra='allow'). ToolResponse deliberately omits
content (the Python source) and specs, but extra='allow' re-admits both, and the
get_tools defer_content flag was a no-op, so GET /tools/, GET /tools/list and GET
/tools/id/{id} returned a tool's full source to any caller with mere read access,
including any authenticated user for a publicly read-shared tool. Tool source
commonly embeds hard-coded credentials and internal URLs.

Strip content and specs for callers without write access across the three read
endpoints. Tool execution loads source server-side, so tool use is unaffected,
and writers still receive content where they did before. The duplicated
write-access check is extracted into a small helper.

Co-authored-by: bogdancherniy11-sudo <229690748+bogdancherniy11-sudo@users.noreply.github.com>

* fix: limit the tool source strip to the per-id endpoint

Upstream dev has since fixed the defer_content no-op in Tools.get_tools, so the list endpoints (GET /tools/ and GET /tools/list) no longer fetch tool source at all and the stripping added there is redundant. Stripping specs also broke the chat Available Tools modal, which lists a tool's functions from specs for every user who can use the tool.

Reduce the change to the one remaining leak: GET /tools/id/{id} builds its response from a full model_dump() and ConfigDict(extra='allow') re-admits content, so drop content there for callers without write access. Specs stay visible to read users as before and the helper functions are no longer needed.

---------

Co-authored-by: bogdancherniy11-sudo <229690748+bogdancherniy11-sudo@users.noreply.github.com>
2026-07-27 01:51:01 -04:00
Timothy Jaeryang Baek
8e46450acd refac 2026-07-09 17:28:34 -05:00
Timothy Jaeryang Baek
517cd8d102 refac 2026-06-29 13:03:14 -05:00
Timothy Jaeryang Baek
0883638027 refac 2026-06-29 05:47:21 -05:00
Timothy Jaeryang Baek
396d9ac181 refac 2026-06-29 05:27:51 -05:00
Timothy Jaeryang Baek
cdd7b88bec refac 2026-06-29 05:14:57 -05:00
alvarellos
368b4a5b22
solve-valves-icon-disappear-issue (#26256) 2026-06-29 00:56:44 -05:00
Timothy Jaeryang Baek
b5c43968db refac 2026-06-25 03:31:45 +01:00
Timothy Jaeryang Baek
91762ed807 refac
Some checks are pending
Python CI / Ruff Format (3.11) (push) Waiting to run
Python CI / Ruff Format (3.12) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / copy-to-dockerhub (, main) (push) Blocked by required conditions
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / merge (map[name:cuda suffix:-cuda]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:cuda126 suffix:-cuda126]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:main suffix:]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:ollama suffix:-ollama]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:slim suffix:-slim]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda, cuda) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda126, cuda126) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-ollama, ollama) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-slim, slim) (push) Blocked by required conditions
2026-06-23 00:25:21 +02:00
Timothy Jaeryang Baek
5cdcdbaeec refac 2026-06-17 02:52:35 +02:00
Timothy Jaeryang Baek
6fce92aa12 chore: format 2026-06-01 13:56:55 -07:00
Timothy Jaeryang Baek
260ead64da refac 2026-05-21 14:01:57 +04:00
Timothy Jaeryang Baek
6d0295588e refac: modernize type annotations (PEP 604 / PEP 585) 2026-05-12 17:10:15 +09:00
Timothy Jaeryang Baek
c951b4f262 chore: format 2026-05-11 02:29:13 +09:00
Classic298
841c9045d7
fix: gate tool content updates behind workspace.tools to match create endpoint (#24513)
* fix: gate tool content updates behind workspace.tools to match create endpoint

`update_tools_by_id` (routers/tools.py:452) authorizes a caller as long as
they are the tool's owner, hold a `write` access grant on the tool, or are
an admin. This means a verified user who has been given a write grant on
a tool — typically as part of a metadata-collaboration workflow (edit
description, adjust valves, manage access grants) — can also overwrite
the tool's Python source. Because `load_tool_module_by_id` further down
calls `exec(content, module.__dict__)` at module-import time, anything
the new content puts outside the `class Tools:` body executes immediately
on the server with the worker's privileges (root in the default Docker
deployment).

The `create_new_tools` endpoint already requires
`workspace.tools` (or `workspace.tools_import`) precisely because creating
a tool means submitting executable code. The update endpoint did not
mirror that check, producing an asymmetric authorization surface in which
a write-grantee with no workspace permission can still reach the same
exec sink as a workspace.tools-trusted creator. SECURITY.md frames
`workspace.tools` as the trust signal an admin uses to delegate
code-execution capability; the previous behavior let that signal be
bypassed by a per-resource share.

Fix: after the existing ownership / write-grant / admin gate, add a
content-change check. If `form_data.content != tools.content`, require
`workspace.tools` or `workspace.tools_import` (or admin role). Metadata
edits — `name`, `description`, valves config, access grants — continue
to flow through the existing gate, so the legitimate share-for-
collaboration workflow is unaffected.

Reported by KadirArslan in GHSA-p4fx-23fq-jfg6 with a working three-user
PoC (Alice trusted with workspace.tools creates a tool and shares write
to Bob; Bob updates content and the new code runs as root inside the
container, with Burp Collaborator confirming outbound exfiltration).

Co-authored-by: KadirArslan <KadirArslan@users.noreply.github.com>

* chore: trim comment

---------

Co-authored-by: KadirArslan <KadirArslan@users.noreply.github.com>
2026-05-11 01:08:12 +09:00
Timothy Jaeryang Baek
8ff7ff459b chore: format 2026-04-24 18:48:21 +09:00
Timothy Jaeryang Baek
678c44c7cd refac 2026-04-24 16:17:46 +09:00
Timothy Jaeryang Baek
6cc799b1bb chore: format 2026-04-21 15:52:00 +09:00
Timothy Jaeryang Baek
56c5bc1d34 refac 2026-04-20 08:36:24 +09:00
Timothy Jaeryang Baek
d0188f3fe1 refac 2026-04-13 14:08:58 -05:00
Timothy Jaeryang Baek
25898116ea chore: format 2026-04-12 18:12:59 -05:00
Timothy Jaeryang Baek
d40f31982b refac 2026-04-12 14:24:08 -05:00
Timothy Jaeryang Baek
27169124f2 refac: async db 2026-04-12 14:22:11 -05:00
Timothy Jaeryang Baek
4632f200a9 refac 2026-04-02 02:06:21 -05:00
Timothy Jaeryang Baek
60676bfdcf refac 2026-04-01 06:40:49 -05:00
Tim Baek
f949d17db1 refac 2026-03-24 14:37:03 -05:00
Timothy Jaeryang Baek
ade617efa8 refac 2026-03-24 04:49:48 -05:00
Timothy Jaeryang Baek
de3317e26b refac 2026-03-17 17:58:01 -05:00
Timothy Jaeryang Baek
bc5b3ec6b8 refac 2026-03-15 17:21:14 -05:00
Timothy Jaeryang Baek
8da29566a1 refac: safer tool server handling 2026-03-11 15:22:51 -05:00
Timothy Jaeryang Baek
67e26fd3af refac 2026-03-08 16:40:20 -05:00
Timothy Jaeryang Baek
c85afce702 fix: import
Co-Authored-By: Steven Schveighoffer <580778+schveiguy@users.noreply.github.com>
2026-03-06 14:10:50 -06:00
Timothy Jaeryang Baek
345f3e3559 refac 2026-02-25 15:15:59 -06:00
Timothy Jaeryang Baek
176f9a7816 refac 2026-02-23 16:01:03 -06:00
Timothy Jaeryang Baek
3d99de6771 enh: access grant level perms 2026-02-23 15:49:05 -06:00
Timothy Jaeryang Baek
9044abf3bb chore: format 2026-02-23 01:40:53 -06:00
Timothy Jaeryang Baek
b48594a166 refac 2026-02-21 16:27:25 -06:00
Timothy Jaeryang Baek
09dc28df1e chore: format 2026-02-16 00:43:32 -06:00
Timothy Jaeryang Baek
911eecac85 fix: disabled mcp display issue
Co-Authored-By: Dario Ruellan <6965667+druellan@users.noreply.github.com>
2026-02-15 18:10:18 -06:00
Timothy Jaeryang Baek
626d236d13 chore: format 2026-02-13 15:00:39 -06:00
Timothy Jaeryang Baek
df6e38039f refac 2026-02-13 13:29:22 -06:00
Classic298
73776d54b8
fix: enforce public sharing permission checks across all resource types (#21358)
The sharePublic prop in editor components (Knowledge, Tools, Skills,
Prompts, Models) incorrectly included an "|| edit" / "|| write_access"
condition, allowing users with write access to see and use the "Public"
sharing option regardless of their actual public sharing permission.
Additionally, all backend access/update endpoints only verified write
authorization but did not check the corresponding sharing.public_*
permission, allowing direct API calls to bypass frontend restrictions
entirely.
Frontend: removed the edit/write_access bypass from sharePublic in all
five editor components so visibility is gated solely by the user's
sharing.public_* permission or admin role.
Backend: added has_public_read_access_grant checks to the access/update
endpoints in knowledge.py, tools.py, prompts.py, skills.py, models.py,
and notes.py. Public grants are silently stripped when the user lacks
the corresponding permission.
Fixes #21356
2026-02-13 11:22:32 -06:00
Timothy Jaeryang Baek
f376d4f378 chore: format 2026-02-11 16:24:11 -06:00
Timothy Jaeryang Baek
3e56261c5e refac 2026-02-11 02:06:43 -06:00
Timothy Jaeryang Baek
e3a8257690 refac 2026-02-10 15:41:11 -06:00
Timothy Jaeryang Baek
f7406ff576 refac 2026-02-09 13:28:14 -06:00