Files

44 lines
1.5 KiB
Python
Raw Permalink Normal View History

2025-06-17 12:58:00 +05:30
"""
Setup configuration for compsio core.
"""
from pathlib import Path
from setuptools import find_packages, setup
setup(
name="composio",
author="Composio",
author_email="tech@composio.dev",
description="Core package to act as a bridge between composio platform and other services.",
long_description=(Path(__file__).parent / "README.md").read_text(encoding="utf-8"),
long_description_content_type="text/markdown",
url="https://github.com/composiohq/composio",
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
],
chore(py): refresh Python dependencies (#3627) Refreshes the Python SDK's core + provider dependency ranges and uv locks to the **newest cutoff-compatible** versions, and makes the locks self-consistent. ## What changed - Bumps core + provider dependency ranges (`pyproject.toml` / `setup.py`) and regenerates all three uv locks (root, `openai`, `claude_agent_sdk`) to the newest available versions. - Keeps `composio-client==1.41.0` (the current newest, released 2026-06-19). - Caps `crewai>=0.134.0,<0.135.0`: crewai 1.x requires `pydantic>=2.11.9,<2.13`, which conflicts with composio core's `pydantic>=2.13.4`. Staying on crewai 0.x keeps the newest pydantic for everything else; the provider only uses `crewai.tools.BaseTool`, which is unaffected. - Drops the one-shot `--exclude-newer` cutoff that had been recorded in the lock `[options]` but was not backed by any `[tool.uv]` config — it broke `uv lock --check` and held packages a few releases behind newest. - Pins nox-installed tools/stubs in `noxfile.py` to the matching newest versions. ## Resolution result - Root lock: **161 upgrades, 0 downgrades** vs `next`. - Provider locks: **0 downgrades** vs `next` (openai +14, claude_agent_sdk +29). ## Verification - `uv lock --check` — clean on all three locks. - `uv run --frozen --all-packages pytest python/tests/test_imports.py` — 8/8 passing. - `uv run --frozen nox -s chk` — ruff clean + mypy 0 issues across 80 source files. Supersedes https://github.com/ComposioHQ/composio/pull/3622 (which was opened from a fork).
2026-06-22 18:23:17 +04:00
python_requires=">=3.10,<4",
2025-06-17 12:58:00 +05:30
packages=find_packages(include=["composio*"]),
install_requires=[
"pysher>=1.0.8",
chore(deps): refresh SDK, Python, and CI dependencies (#3955) This PR: - splits https://github.com/ComposioHQ/composio/pull/3953 in two: this PR carries every dependency and GitHub Actions bump **except** the docs site, which follows in a stacked PR - consolidates and supersedes Dependabot PRs #3915, #3916, and #3934 through #3942 - adopts TypeScript 7.0.2 for primary compilation while retaining the `@typescript/typescript6` API lane that TypeScript-ESLint still requires, following the upstream side-by-side guidance - refreshes Python core and provider dependencies, lockfiles, and the Ruff 0.16 lint configuration - updates every GitHub Action with a verified newer official release, including majors, while retaining immutable commit SHA pins and migrating setup-uv cache pruning - deletes four per-package `eslint.config.mjs` shims: under ESLint 10 the default per-file config lookup re-anchors the root config's globs into each package, so `pnpm lint` stayed green while the CLI's try/catch, `process.env` and node-builtin bans went unenforced - bounds and documents the new `brace-expansion` and `@hono/node-server` security overrides, raising the `@hono/node-server` floor to 2.0.10 to clear GHSA-9mqv-5hh9-4cgg - preserves intentional compatibility fixtures and lanes for AI SDK 6, Zod 3, TypeScript 5.8, Mastra AI SDK 5, and Python provider constraints ## Context The docs site is a separate Bun workspace with its own `bun.lock` and is not a pnpm workspace member, so the two halves share no lockfile and no build. Splitting them keeps the Fumadocs 11 migration (a breaking API change with real refactoring) reviewable on its own, independently of the mechanical version bumps here. The `brace-expansion` override deliberately spans majors: GHSA-mh99-v99m-4gvg (HIGH) is published as a single `<=5.0.7` range with no 1.x or 2.x backport, so narrowing it to the 5.x line puts `brace-expansion` 2.1.2 back under `core>minimatch>brace-expansion` and `pnpm audit --prod --audit-level=high` exits 1. Verified both ways; the trade-off it buys is recorded inline in `pnpm-workspace.yaml`. Verified on this branch standalone: `pnpm install --frozen-lockfile`, `pnpm lint`, `pnpm typecheck`, `pnpm build:packages`, `pnpm test` (963 tests, 26/26 tasks), and `pnpm audit --prod --audit-level=high`.
2026-07-27 13:27:29 +01:00
"pydantic>=2.11.9",
"composio-client==1.43.0",
"typing-extensions>=4.16.0",
"openai>=2.48.0",
chore(py): refresh Python dependencies (#3627) Refreshes the Python SDK's core + provider dependency ranges and uv locks to the **newest cutoff-compatible** versions, and makes the locks self-consistent. ## What changed - Bumps core + provider dependency ranges (`pyproject.toml` / `setup.py`) and regenerates all three uv locks (root, `openai`, `claude_agent_sdk`) to the newest available versions. - Keeps `composio-client==1.41.0` (the current newest, released 2026-06-19). - Caps `crewai>=0.134.0,<0.135.0`: crewai 1.x requires `pydantic>=2.11.9,<2.13`, which conflicts with composio core's `pydantic>=2.13.4`. Staying on crewai 0.x keeps the newest pydantic for everything else; the provider only uses `crewai.tools.BaseTool`, which is unaffected. - Drops the one-shot `--exclude-newer` cutoff that had been recorded in the lock `[options]` but was not backed by any `[tool.uv]` config — it broke `uv lock --check` and held packages a few releases behind newest. - Pins nox-installed tools/stubs in `noxfile.py` to the matching newest versions. ## Resolution result - Root lock: **161 upgrades, 0 downgrades** vs `next`. - Provider locks: **0 downgrades** vs `next` (openai +14, claude_agent_sdk +29). ## Verification - `uv lock --check` — clean on all three locks. - `uv run --frozen --all-packages pytest python/tests/test_imports.py` — 8/8 passing. - `uv run --frozen nox -s chk` — ruff clean + mypy 0 issues across 80 source files. Supersedes https://github.com/ComposioHQ/composio/pull/3622 (which was opened from a fork).
2026-06-22 18:23:17 +04:00
"json-schema-to-pydantic>=0.4.11",
"jsonschema>=4.23.0",
fix(sdk): pin the validated address when fetching URLs (SSRF DNS rebinding) (#4172) Fixes #4151. ## The problem Both SDKs validated a URL by resolving its hostname, and then handed the *hostname* to the HTTP client, which resolved it again when it opened the socket. Two lookups, two answers: a short-TTL record under an attacker's control answers publicly for the check and with `169.254.169.254`, `127.0.0.1`, or RFC 1918 space for the connect. The guard passes and the connection lands inside the network — classic TOCTOU DNS rebinding, documented in both modules until now as a known residual. ```mermaid sequenceDiagram participant SDK participant DNS as Attacker DNS participant Meta as 169.254.169.254 Note over SDK,Meta: before SDK->>DNS: resolve evil.example.com (validate) DNS-->>SDK: 93.184.216.34 — passes the guard SDK->>DNS: resolve evil.example.com (connect) DNS-->>SDK: 169.254.169.254 SDK->>Meta: GET /latest/meta-data/… Meta-->>SDK: credentials ``` ## The fix Resolve once, validate every answer, then connect to the address that was validated. There is no second lookup left to rebind. - **Python** — `safe_get` / `safe_request` mount a transport adapter that swaps the connect target for the duration of the socket connect only. The `Host` header and TLS SNI keep the hostname, so certificate verification is unchanged; rewriting `conn._dns_host` for the whole connection would have sent `Host: <ip>` and offered the IP as SNI, failing against every real origin. Every fetch call site now goes through those two helpers, so no `requests.get` sits next to a bare check any more: - `_files.py::_fetch_file_from_url`, `_files.py::FileDownloadable.download` - `tool_router_session_files.py::_fetch_url_bytes` - `safe_request`, per redirect hop - **TypeScript** — `assertSafeFetchTarget` returns the validated address and `ssrfSafeFetch` hands `fetch` a dispatcher pinned to it, re-pinned per redirect hop. The dispatcher goes to the runtime's own `fetch`, so callers that stub `globalThis.fetch` keep working. The pinned `lookup` answers both shapes Node calls it with — the address *list* it uses for Happy Eyeballs, and the single `(address, family)` it uses when `autoSelectFamily` is off — since answering in the wrong shape is rejected as an invalid address. - A fail-closed peer assertion runs on the Python side before a byte is written to the socket — redundant while pinning works, and a tripwire if a urllib3 upgrade ever breaks it. - `workerd` is unchanged: it already fails closed for user-supplied URLs. Redirect *validation* already existed in both SDKs (`safe_request` / `ssrfSafeFetch`); what was missing was re-pinning each hop. ## Tests The existing suites could not express this bug: they mock both the resolver and the HTTP client, so check and use are the same mock. The new tests use real sockets. - `python/tests/test_url_safety_pinning.py` — two loopback servers and a resolver that answers the first lookup with one endpoint and every later one with another, which is what a short-TTL rebinding record does. Asserts the rebound endpoint receives **zero** connections, and that `Host` still carries the hostname. Both tests fail on `next` and pass here. - `ts/packages/core/test/utils/pinnedDispatcher.node.test.ts` — a real server plus a hostname under `.invalid`, which RFC 2606 guarantees never resolves. A request that arrives proves the connect used the pinned address and never consulted DNS. The third case shows the contrast: unpinned, the same fetch cannot resolve at all. - `ssrfGuard.test.ts` gains assertions that each hop is pinned to that hop's own validated address. - `pinnedDispatcher.node.test.ts` also pins with `setDefaultAutoSelectFamily(false)`, which is the branch Node takes for the single-address callback. ## Notes - Supersedes #4157, which diagnosed this correctly. Its post-response peer check turned out not to hold: with an HTTP/1.0 or `Connection: close` server, urllib3 detaches the socket (`conn.sock is None`) while `r.content` still returns the full body, so the check fails open exactly where exfiltration succeeds. That is why the assertion here runs at connect time instead. - The Python package now declares `urllib3>=2` directly. `url_safety` imports it for `NameResolutionError`, which only exists from 2.0, and the pinning adapter reaches into 2.x connection internals; `requests` alone allows 1.x, where `import composio` would have failed outright. - `@composio/core` gains an `undici` dependency, pinned to `^7`: undici 8 dispatchers are rejected by the `fetch` in every Node version this package supports (22/24/25, verified). The real-socket test runs on the full CI matrix, so a future incompatibility fails loudly instead of silently un-pinning. - `undici` is imported on first pinned request rather than at module load: importing it installs a process-wide global dispatcher, which would have handed the host application's own unrelated `fetch` calls this package's undici merely because it imported `@composio/core`. - Residuals, now documented in the modules: - Requests routed through an environment proxy keep the pre-flight check only. The proxy resolves the hostname itself and the SDK cannot see or pin that resolution. - A process that does perform a pinned fetch still ends up on this package's `Agent` if nothing had claimed the global dispatcher slot yet. undici defines that slot non-configurable, so it cannot be handed back — assigning `undefined` leaves the runtime's own `fetch` asserting on a missing dispatcher.
2026-08-20 13:34:37 +02:00
# `get_connection_with_tls_context` (the pinning adapter's mount
# point) is only called by `HTTPAdapter.send` on requests >= 2.32.2.
# 2.32.4 fixes GHSA-9hjg-9r4m-mvj7 (.netrc credentials leak).
"requests>=2.32.4",
fix(sdk): pin the validated address when fetching URLs (SSRF DNS rebinding) (#4172) Fixes #4151. ## The problem Both SDKs validated a URL by resolving its hostname, and then handed the *hostname* to the HTTP client, which resolved it again when it opened the socket. Two lookups, two answers: a short-TTL record under an attacker's control answers publicly for the check and with `169.254.169.254`, `127.0.0.1`, or RFC 1918 space for the connect. The guard passes and the connection lands inside the network — classic TOCTOU DNS rebinding, documented in both modules until now as a known residual. ```mermaid sequenceDiagram participant SDK participant DNS as Attacker DNS participant Meta as 169.254.169.254 Note over SDK,Meta: before SDK->>DNS: resolve evil.example.com (validate) DNS-->>SDK: 93.184.216.34 — passes the guard SDK->>DNS: resolve evil.example.com (connect) DNS-->>SDK: 169.254.169.254 SDK->>Meta: GET /latest/meta-data/… Meta-->>SDK: credentials ``` ## The fix Resolve once, validate every answer, then connect to the address that was validated. There is no second lookup left to rebind. - **Python** — `safe_get` / `safe_request` mount a transport adapter that swaps the connect target for the duration of the socket connect only. The `Host` header and TLS SNI keep the hostname, so certificate verification is unchanged; rewriting `conn._dns_host` for the whole connection would have sent `Host: <ip>` and offered the IP as SNI, failing against every real origin. Every fetch call site now goes through those two helpers, so no `requests.get` sits next to a bare check any more: - `_files.py::_fetch_file_from_url`, `_files.py::FileDownloadable.download` - `tool_router_session_files.py::_fetch_url_bytes` - `safe_request`, per redirect hop - **TypeScript** — `assertSafeFetchTarget` returns the validated address and `ssrfSafeFetch` hands `fetch` a dispatcher pinned to it, re-pinned per redirect hop. The dispatcher goes to the runtime's own `fetch`, so callers that stub `globalThis.fetch` keep working. The pinned `lookup` answers both shapes Node calls it with — the address *list* it uses for Happy Eyeballs, and the single `(address, family)` it uses when `autoSelectFamily` is off — since answering in the wrong shape is rejected as an invalid address. - A fail-closed peer assertion runs on the Python side before a byte is written to the socket — redundant while pinning works, and a tripwire if a urllib3 upgrade ever breaks it. - `workerd` is unchanged: it already fails closed for user-supplied URLs. Redirect *validation* already existed in both SDKs (`safe_request` / `ssrfSafeFetch`); what was missing was re-pinning each hop. ## Tests The existing suites could not express this bug: they mock both the resolver and the HTTP client, so check and use are the same mock. The new tests use real sockets. - `python/tests/test_url_safety_pinning.py` — two loopback servers and a resolver that answers the first lookup with one endpoint and every later one with another, which is what a short-TTL rebinding record does. Asserts the rebound endpoint receives **zero** connections, and that `Host` still carries the hostname. Both tests fail on `next` and pass here. - `ts/packages/core/test/utils/pinnedDispatcher.node.test.ts` — a real server plus a hostname under `.invalid`, which RFC 2606 guarantees never resolves. A request that arrives proves the connect used the pinned address and never consulted DNS. The third case shows the contrast: unpinned, the same fetch cannot resolve at all. - `ssrfGuard.test.ts` gains assertions that each hop is pinned to that hop's own validated address. - `pinnedDispatcher.node.test.ts` also pins with `setDefaultAutoSelectFamily(false)`, which is the branch Node takes for the single-address callback. ## Notes - Supersedes #4157, which diagnosed this correctly. Its post-response peer check turned out not to hold: with an HTTP/1.0 or `Connection: close` server, urllib3 detaches the socket (`conn.sock is None`) while `r.content` still returns the full body, so the check fails open exactly where exfiltration succeeds. That is why the assertion here runs at connect time instead. - The Python package now declares `urllib3>=2` directly. `url_safety` imports it for `NameResolutionError`, which only exists from 2.0, and the pinning adapter reaches into 2.x connection internals; `requests` alone allows 1.x, where `import composio` would have failed outright. - `@composio/core` gains an `undici` dependency, pinned to `^7`: undici 8 dispatchers are rejected by the `fetch` in every Node version this package supports (22/24/25, verified). The real-socket test runs on the full CI matrix, so a future incompatibility fails loudly instead of silently un-pinning. - `undici` is imported on first pinned request rather than at module load: importing it installs a process-wide global dispatcher, which would have handed the host application's own unrelated `fetch` calls this package's undici merely because it imported `@composio/core`. - Residuals, now documented in the modules: - Requests routed through an environment proxy keep the pre-flight check only. The proxy resolves the hostname itself and the SDK cannot see or pin that resolution. - A process that does perform a pinned fetch still ends up on this package's `Agent` if nothing had claimed the global dispatcher slot yet. undici defines that slot non-configurable, so it cannot be handed back — assigning `undefined` leaves the runtime's own `fetch` asserting on a missing dispatcher.
2026-08-20 13:34:37 +02:00
# `url_safety` imports urllib3 directly and needs 2.x: 1.x has no
# `NameResolutionError` and different connection internals.
# 2.7.0 fixes GHSA-mf9v-mfxr-j63j and GHSA-qccp-gfcp-xxvc.
"urllib3>=2.7.0",
2025-06-17 12:58:00 +05:30
],
include_package_data=True,
)