Commit Graph
1572 Commits
Author SHA1 Message Date
Alexandre Teixeira 4992cc620f test: protect chat document context owner boundaries 2026-10-29 02:09:37 +00:00
Raul JuarezandRaul 5bf4524618 fix(chatgpt): omit temperature from subscription requests (#6498)
Co-authored-by: Raul <9117159+raultcj@users.noreply.github.com>
2026-10-29 01:34:52 +01:00
Alexandre Teixeira 6d102a213f fix(security): confine teardown paths and avoid interpolating exception data in logs
- routes/gallery/gallery_routes.py: use stable diagnostic log message without
  interpolating raw exception, resolver details, tokens, or destination strings.
- tests/e2e/teardown.js: remove environment-variable path overrides from production
  code, strictly confine test options and temp directories, and prevent arbitrary
  directory cleanup.
- Add regression tests covering non-leakage of synthetic tokens/queries/exceptions
  into logs and responses, and path confinement during teardown.
2026-10-28 21:14:43 +00:00
Alexandre Teixeira de8f151632 fix(security): harden trace teardown and gallery error responses
- CodeQL #1202 (tests/e2e/teardown.js): replace execSync shell execution with
  execFileSync, passing python executable and sanitizer arguments separately with
  shell: false. Preserve ODYSSEUS_TEST_PYTHON support, timeout handling, and
  fail-closed deletion.
- CodeQL #1203 (routes/gallery/gallery_routes.py): prevent exception information
  exposure in /api/image/edit-progress by returning a generic rejection response
  without leaking internal hostnames, IPs, resolver errors, or credentials.
- Add regression tests covering paths with spaces, metacharacters, synthetic command
  substitutions, process failure modes, fail-closed artifact purge, and SSRF
  rejection confidentiality.
2026-10-28 21:10:12 +00:00
Alexandre Teixeira cce5892eeb test(css): update approved photo editor visual baseline
Record the Product Owner-approved 13 element changes across 48 page/variant
combinations for PR #6741. The regenerated baseline exactly matches the
visually reviewed candidate; retain the upstream PR #6840 sidebar styles.

Validation: 49 CSS snapshot/layout tests and 26 frontend/mobile browser tests.
Visual acceptance evidence remains outside the repository.
2026-10-28 20:56:09 +00:00
Alexandre Teixeira 671cbd79ac merge(dev): integrate latest upstream dev (PR #6840 sidebar animations)
- Merge upstream/dev at 0116f0a62b
- Incorporate upstream sidebar toggle animation and auto-collapse measurement fixes
- Preserve upstream CSS snapshot baseline in tests/css_snapshot/baseline.json
- Retain all PR #6741 photo-editor features, security controls, and mobile fixes
2026-10-28 19:30:57 +00:00
Alexandre Teixeira 2e1c2a343a merge(dev): reconcile photo editor security and upstream changes
- Reconcile conflict resolution in routes/editor_agent_routes.py and src/editor_agent_model.py
- Enforce strict server-authorized endpoint resolution and reject client URL overrides
- Enforce bearer-token privilege separation: delegated API tokens are capped at non-admin scope per src/tool_security.py and cannot inspect private base URLs or probe metadata
- Preserve chat-scope authorization, missing-session 401 rejection, and owner-scoped browser bridge/SSE queues
- Preserve administrator-disabled-tool denylist enforcement introduced by PR #6357
- Fix mobile toolbar flyout hit-testing and stacking context trapping on viewports <= 700px via scoped elevation and mask suppression
- Stabilize project recovery test fixture by awaiting document draft quiescence prior to baseline capture
2026-10-28 19:30:08 +00:00
Alexandre Teixeira 0116f0a62b Merge pull request #6840 from eesoymilk/fix/sidebar-toggle-animation
fix(sidebar): animate the sidebar toggle instead of snapping
2026-10-28 18:15:15 +00:00
Alexandre Teixeira c237a1cb9c feat(editor): harden photo editor security and interactions 2026-10-28 17:37:10 +00:00
57a1859f08 fix(security): stop the agent from re-enabling tools an admin disabled (#6357)
* fix(security): stop the agent from re-enabling tools an admin disabled

settings.json:disabled_tools is the only global tool-permission boundary
the Settings > Agent Tools panel offers, yet manage_settings exposed an
`enable_tool` action that removed entries from it. Any agent turn could
undo the admin's restriction, and because the agent reads untrusted web
pages, emails and documents, a planted instruction could re-enable bash,
email or any other tool that had been switched off.

The denylist can now only be narrowed from a turn: `disable_tool` and
`list_tools` keep working, `enable_tool` is refused with a message that
points the user to Settings > Agent Tools, and the action is dropped from
the function schema, the prompt rule and the tool index so models are not
steered into calling it. The free-form set/delete/reset actions were
already unable to reach `disabled_tools`; a test now pins that.

Fixes #5523

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UAB5sz5srMKR7rbeDFtdMH

* fix(settings): close internal API tool-policy bypass

Refuse global tool-policy replacement from internal-token requests even when an admin owner is impersonated, and block the same write in app_api. Route explicit image re-enable requests to list_tools with a Settings pointer. Keep disabled_tools outside general settings actions even if a default is added later. Remove the retired action from capability metadata. Validation: 573 focused tests passed; the running app rejected handler, generic API and encoded-path internal HTTP attempts while preserving human administrator controls.

* fix(mcp): block agent writes to per-server MCP tool policy

PATCH /api/mcp/servers/{id}/tools only checked require_admin, which accepts
the internal tool token, and app_api still forwarded it, so an agent turn
could re-enable MCP tools an admin had switched off. Refuse the internal
token on that route (same check as POST /api/tools) and add PATCH
/api/mcp/servers to the app_api blocklist, with regression tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BCbhLNC7mJsunxqfwwshqn

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Afonso Junior <chatgpt@yack.com.br>
2026-10-27 22:50:35 -06:00
Alexandre Teixeira 4079f12ae6 fix(editor): resolve preview authorization and CI regressions 2026-10-28 00:31:42 +00:00
Alexandre Teixeira 091364f7e6 Merge branch 'dev' into review/pewds-pr6738-terra-20261027
Integrate PR #6739 foundation (backend security, bridge hardening, Python 3.11 test fixture correction) with PR #6738 remediations.
- Reconcile routes/email/email_routes.py harmonizing _LIST_LOCK and _LIST_EPOCH with #6738 cache invalidation and thread-safe mutation.
- Preserve editor-session validation, legacy-browser tool restrictions, image-tool authorization, and email cache concurrency invariants.
2026-10-27 18:12:05 +00:00
Alexandre Teixeira 0133de6f0e feat(security): apply audited PR #6738 remediations and test hardening
- Enforce vision probe SSRF safe local host validation, SafeProbeBackend TOCTOU elimination, and session owner authorization
- Authorize session titling endpoints against registered owner configuration
- Sanitize sensitive metadata logging from agent loop debug logs
- Add async non-blocking execution for spec router tools and thinking decisions
- Harden email cache invalidation fencing and thread-safe mutation
- Add regression test suites for legacy browser authority, spec contracts, spec router request scoping, and task MCP delivery
2026-10-27 17:25:25 +00:00
Alexandre Teixeira 25c2fad3e1 test(editor): preserve ASGI event loop across bridge requests 2026-10-27 16:20:08 +00:00
Alexandre Teixeira d105fbde95 fix(editor): harden bridge isolation and completion semantics 2026-10-27 15:36:17 +00:00
pewdiepie-archdaemon 020fe02aa0 Scope backend checks to backend behavior and retain ownership regression coverage 2026-10-26 16:53:52 +00:00
pewdiepie-archdaemon 375e263419 Merge backend ownership checks and test ownership cleanup 2026-10-26 16:53:52 +00:00
pewdiepie-archdaemon 8865c975aa Keep chat-editor integration and shutdown checks with the runtime review 2026-10-26 16:53:52 +00:00
pewdiepie-archdaemon a58a5e6632 Merge backend ownership checks and test ownership cleanup 2026-10-26 16:53:52 +00:00
pewdiepie-archdaemon 106b1e7c86 Verify saved action names and steps cannot inject HTML 2026-10-26 16:50:09 +00:00
pewdiepie-archdaemon 49d57a43fe Merge recolor cleanup regression coverage 2026-10-26 16:50:09 +00:00
pewdiepie-archdaemon e67cb8bbb9 Merge recolor cleanup regression coverage 2026-10-26 16:50:08 +00:00
pewdiepie-archdaemon d9797ce10f Cover recolor normalization with pathological whitespace 2026-10-26 16:50:07 +00:00
pewdiepie-archdaemon 9ab440c4cb Keep Gallery image-model picker tests with the editor client 2026-10-26 16:49:01 +00:00
pewdiepie-archdaemon ff1d7df8b0 Merge backend prompt hardening and scoped tests 2026-10-26 16:49:01 +00:00
pewdiepie-archdaemon 6c2a1e6873 Avoid regex backtracking in prompt cleanup and keep Gallery UI tests with client reviews 2026-10-26 16:49:01 +00:00
pewdiepie-archdaemon fa29a86696 Merge backend prompt hardening and scoped tests 2026-10-26 16:49:01 +00:00
pewdiepie-archdaemon 56b85c359c Normalize final newlines in integrated review files 2026-10-26 16:31:23 +00:00
pewdiepie-archdaemon ae28501e7f Normalize final newlines in integrated review files 2026-10-26 16:31:23 +00:00
pewdiepie-archdaemon 89b41b9224 Use explicit editor endpoints in backend regression fixtures 2026-10-26 16:23:29 +00:00
pewdiepie-archdaemon e8551e9cbc Use explicit editor endpoints in backend regression fixtures 2026-10-26 16:23:29 +00:00
pewdiepie-archdaemon 3d47888559 Use explicit editor endpoints in backend regression fixtures 2026-10-26 16:23:29 +00:00
pewdiepie-archdaemon 36a71886bb Merge current dev and refresh PR #6741 from the 7011 integration 2026-10-26 16:21:28 +00:00
pewdiepie-archdaemon 444b60d14e Merge current dev and refresh PR #6738 from the 7011 integration 2026-10-26 16:21:22 +00:00
pewdiepie-archdaemon 93da30c4af Merge current dev and refresh PR #6739 from the 7011 integration 2026-10-26 16:21:17 +00:00
4d0610a1eb fix(email): guard user-supplied IMAP/SMTP hosts against SSRF (#6355)
* fix(email): guard user-supplied IMAP/SMTP hosts against SSRF

POST /api/email/accounts/test opened raw imaplib/smtplib connections to
whatever host:port the request body named, and POST/PUT /api/email/accounts
and PUT /api/email/config persisted arbitrary hosts for the background
pollers to contact. All of these sit behind require_user/require_owner with
no admin gate, so any authenticated user could make the server connect to
loopback, LAN and cloud-metadata targets (169.254.169.254) and read the
first 200 characters of the remote banner back out of the friendly error.
THREAT_MODEL.md lists email as admin-only; the tool layer honours that but
the HTTP routes did not.

Add check_outbound_host() to src/url_safety.py, a bare-host companion to
check_outbound_url() with the same classification (link-local, multicast,
reserved and unspecified always rejected; private/loopback only with
block_private) plus localhost-name handling and an explicit policy for names
that do not resolve. Wire it into the four email routes via
_check_mail_host(): non-admin owners (and everyone when
EMAIL_BLOCK_PRIVATE_IPS=true) also lose private/loopback targets, admins
keep the local-first LAN/Dovecot setups. Unresolvable names pass through
because the connect that follows fails with the same DNS error.

Regression tests cover the helper's policy table and each route: the test
route rejects before any socket opens, save routes reject before touching
the DB, admins keep loopback unless locked down, and an update that fails
validation leaves the stored row untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwcwfY2uQMxNRsK3y6xBAp

* fix(email): harden IMAP/SMTP SSRF protection against rebinding, TOCTOU, and unvetted hosts

- P0: Implement safe_create_connection() in src/url_safety.py to resolve hostnames once, validate every returned address against SSRF policy, and connect directly to the pinned IP. This eliminates DNS rebinding and TOCTOU while preserving TLS SNI and certificate hostname verification across IMAP, IMAPS, STARTTLS, SMTP, and SMTP_SSL.
- P1: Ensure unresolvable or deferred hostnames cannot become an unrestricted future connection capability by enforcing runtime SSRF validation fail-closed on every connection, while maintaining compatibility with offline configurations.
- P2: Extend SSRF enforcement to the core connection layer (_open_imap_connection, _send_smtp_message, _imap_connect) using ContextVar owner scoping, protecting pre-existing DB rows, restored configs, background pollers, and scheduled operations.
- P3: Allow admin and single-user access to IPv6 loopback (::1, [::1]) for local mail servers (e.g. Dovecot) by checking loopback before is_reserved, while keeping link-local, cloud metadata (169.254.169.254, 100.100.100.200), and non-admin restrictions strictly enforced.
- Add comprehensive regression and adversarial test coverage in tests/test_email_account_host_ssrf.py.

* fix(email): reject unresolved saved hosts without stdlib monkeypatches

Use the existing explicit policy IMAP/SMTP classes and canonical connect_outbound_tcp helper. Remove process-wide stdlib assignments, context-variable plumbing, redundant aliases and resolver-signature retries. Reject unsafe or unresolved hosts before account/config persistence, keep DNS work off the event loop, return fixed client errors, identify Alibaba metadata accurately and reject invalid TCP ports. Validation: 654 relevant email, URL-safety and CodeQL regression tests passed, 3 skipped. Three unrelated browser checks were excluded after environment failures (missing Playwright browser and Chromium timeout). Running-app checks verified rejected create/update/config requests leave stored data unchanged, administrator LAN configuration still works, and metadata/non-admin loopback are blocked.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: PR #6029 Reviewer <reviewer@odysseus-review.local>
Co-authored-by: Afonso Junior <chatgpt@yack.com.br>
2026-10-26 09:47:03 -06:00
be9f575b59 fix(security): block read-only cookbook tools for non-admin owners (#6353)
* fix(security): block read-only cookbook tools for non-admin owners

list_cached_models, list_served_models, tail_serve_output, list_downloads,
search_hf_models, list_serve_presets and list_cookbook_servers were in the
plan-mode read-only allowlist but in neither NON_ADMIN_BLOCKED_TOOLS nor the
dispatcher's _ADMIN_TOOLS. Each implementation calls a require_admin route
over the internal loopback with the process-wide INTERNAL_TOOL_TOKEN and
never checks the owner, so a non-admin user's agent inherited admin reach
through them. list_cached_models is the worst case: a caller-chosen `host`
is forwarded to /api/model/cached, which SSHes to that host with the app
user's keys and walks caller-chosen model_dirs. THREAT_MODEL.md lists model
serving as admin-only, so gate the read side the same way as serve/download.

Adding the names to NON_ADMIN_BLOCKED_TOOLS also hides them from non-admin
tool schemas and caps bearer-token agent runs; _ADMIN_TOOLS blocks them at
dispatch. Regression test covers both lists, schema hiding, and that the
loopback is never reached for a non-admin owner.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TwcwfY2uQMxNRsK3y6xBAp

* fix(cookbook): bind request authority in admin gate regressions

Keep all seven read-only Cookbook tools in the admin prompt inventory. Grant request authority in dispatch tests so the admin gate itself is exercised, and verify administrators still reach each handler. Validation: 359 focused authorization, tool-policy and schema tests passed. Against the running app with real auth accounts, all seven tools reject a non-admin and an admin reaches the authenticated Cookbook HTTP API.

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Co-authored-by: Afonso Junior <chatgpt@yack.com.br>
2026-10-26 09:46:57 -06:00
GrzegorzandClaude Opus 5.5 1000b6582c fix(agent): give file tools the agent workspace as root when no workspace is set (#6722)
* fix(agent): give file tools the agent workspace as root when no workspace is set (#6679)

With no workspace bound, bash/python run in data/agent_workspace, but
RequestAuthority sealed no filesystem root, so every native file tool
failed with "requires a sealed resource root", and an approved
write_file failed with "no sealed resource identity". Seal the agent
workspace instead, and resolve relative paths in _resolve_tool_path
against it rather than the server's cwd.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* test: re-seal resource roots when a test swaps the authority owner (#6679)

A no-workspace authority now seals the agent workspace for its owner, so
replace(authority, owner="bob") copied alice's root and was rejected
before the approval-binding check the tests are about.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(agent): only seal a vetted agent workspace as the file-tool root (#6679)

Apply the agent_cwd() check before sealing data/agent_workspace: it must
be a real directory in the readable data subdirs, otherwise no root is
sealed. A symlinked workspace no longer redirects the file tools or the
bash/python launch scope. Tighten the dispatch test assertions to the
exact 'outside the sealed roots' message.

* refactor(agent): vet the no-workspace file root with default_agent_workspace (#6679)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 09:46:52 -06:00
pewdiepie-archdaemon 30430acfea fix(harness): ignore dotted email local parts in artifact inference 2026-10-25 17:04:43 +00:00
Yu-Wei Chang 4954cc2e8c fix(sidebar): animate the sidebar toggle instead of snapping
The global .hidden utility (display: none) also matches #sidebar.hidden,
so the collapsed sidebar was removed from layout before its width/opacity
transition could run, and opening and closing both snapped in one frame.

Keep the collapsed sidebar rendered and take it out of interaction once
closed: .sidebar.hidden stays display: flex, gains pointer-events: none,
and visibility: hidden that is transitioned so it only flips after the
collapse finishes (keeping the closed sidebar out of the tab order).

On desktop the icon rail now tucks under the sidebar and slides out as it
collapses, so the combined width eases instead of jumping by 48px when
the two swap. On mobile the drawer keeps its width while off so it slides
out as well as in, and switching it to the right edge before opening no
longer animates it across the screen. Transitions are disabled under
prefers-reduced-motion, and the auto-collapse restore measures the chat
width with the transition suppressed.

Re-record the computed-style snapshot baseline for the sidebar and icon
rail.
2026-10-24 22:26:40 -07:00
Tim FandLéo a0c93f38ef chore: harden and update supporting services (#6788)
* chore: harden and update supporting services

* chore(compose): pin ChromaDB and ntfy images by tag and digest

chromadb/chroma:latest and a bare binwiederhier/ntfy change underneath
an existing install on the next pull, so two hosts on the same commit
can run different sidecar builds. SearXNG is already pinned this way.

Pin chroma 1.5.9 and ntfy v2.32.0 to the multi-arch index digests that
:latest currently resolves to, so nothing changes at runtime today. The
standalone GPU files carry the same references, as
test_gpu_compose_standalone.py requires. Add a test that every sidecar
image has a release tag and a digest.

---------

Co-authored-by: Léo <leograndcontact@gmail.com>
2026-10-24 17:44:07 +02:00
RaresKeYandLéo ed78beee1b fix(security): refresh client trust and adopt corrected upstream SearXNG (#6791)
Select the official immutable SearXNG release with corrected system and certifi stores in all Compose deployments. Retain native offline, actual-entrypoint and Compose/live regression checks while removing the custom trust-repair image and registry publication path. Reuse the canonical CA inventory checker.

Include released Python, certifi, grpcio, uv and Docker CLI trust updates and strict fourteen-chain validation. Keep unreleased CPython verifier and native-helper fixes separate from claims about shipped artifacts.

Part of #6784 and #6790.

Co-authored-by: Léo <leograndcontact@gmail.com>
2026-10-24 17:26:21 +02:00
GrzegorzandClaude Opus 5.5 f8e043e8ca fix(approvals): seal approved bash/python and file writes in the agent workspace when no workspace is set (#6705)
#6683 made an exact approval seal a launch boundary (and a filesystem root)
in the request's workspace, but only when a workspace is bound. Agent mode
with no folder picked is the default, and there the approval still sealed
nothing, so "Allow" always ended in "Approved action has no sealed
process/job identity" (bash/python) or "Approved filesystem action has no
sealed resource identity" (write_file). In Docker every agent turn carries
the backend runtime context, so bash and write_file always ask for approval
and never ran.

With no workspace, seal the root in the agent workspace, which is where
agent_cwd() already runs bash/python in that case. Inherited (child)
authorities still cannot widen.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 13:19:04 -06:00
Isharakandisharak7m 98a16242c6 fix(security): add SSRF validation to manage_endpoints agent tool (#6327)
The manage_endpoints agent tool accepts arbitrary user-supplied base_urls
and writes them to the database without calling check_outbound_url(),
while the HTTP route (POST /api/model-endpoints) enforces full SSRF
hardening. A prompt-injection payload smuggled into a skill, note, fetched
page, or email could instruct the model to register a cloud-metadata or
internal-network endpoint via this tool path.

Add the same check_outbound_url() guard used by the HTTP route to the
agent tool's 'add' action. Also sanitize the error message in the except
block to avoid leaking raw exception text.

Add 8 regression tests covering: cloud metadata, non-HTTP schemes,
loopback (local-first), strict mode, safe URLs, empty URLs, gopher
scheme, and error message sanitization.

Co-authored-by: isharak7m <192635824+isharak7m@users.noreply.github.com>
2026-10-23 13:18:59 -06:00
IsharakSantoshkumarpuppalaisharak7m
0dbf457c00 fix(security): block SSRF via user-supplied model endpoint URLs (#6316)
* fix: block SSRF via user-supplied model endpoint URLs

* fix(test): stub DNS in loopback SSRF tests for deterministic results

Replace environment-dependent test_loopback_always_rejected with two
deterministic tests using a stub resolver:
- test_loopback_accepted_by_default (local-first, block_private=False)
- test_loopback_rejected_in_strict_mode (block_private=True)

The old test only passed when localhost resolved to ::1 (hit is_reserved),
not because loopback was actually always rejected.

Co-Authored-By: Santoshkumarpuppala

* fix: guard PATCH base_url against SSRF and add ipv6 loopback coverage

---------

Co-authored-by: isharak7m <192635824+isharak7m@users.noreply.github.com>
2026-10-23 13:18:54 -06:00
Raul JuarezandRaul b4ae7ebcc4 feat(agent): expose chat history with existing chat scope (#6443)
Co-authored-by: Raul <9117159+raultcj@users.noreply.github.com>
2026-10-23 13:18:49 -06:00
RaresKeY 01566b158e fix(ci): lowercase container image repository names (#6802) 2026-10-22 17:08:05 +01:00
RaresKeY 77a02c30ff fix(security): verify deployed trust before dependency work 2026-10-21 21:40:05 +00:00
RaresKeY cd9f1f734f fix(security): detect incident CAs in custom trust stores
Reject the published compromised intermediates and cross-signed G3 issuer when supplied as trust anchors. Add explicit CA-override inspection and offline chain regressions with a fixed verification time and affected positive control.
2026-10-21 20:48:34 +00:00
RaresKeY 5d0a219ede fix: distrust incident certificates in Chromium and gRPC 2026-10-21 20:09:54 +00:00