From f80bcac7d599a663f84c84fd7a3b21bb5944b33f Mon Sep 17 00:00:00 2001 From: Ayla Croft Date: Thu, 8 Oct 2026 10:17:22 -0400 Subject: [PATCH] fix(s061): beam_mcp 0.10.1, the security patch hex.audit asks for mix hex.audit refuses beam_mcp 0.9.0 since 2026-10-08 for EEF-CVE-2026-88257 (nested tool argument constraints advertised but not enforced) and EEF-CVE-2026-104634 (JSON booleans and null reached dispatch as strings), which turned the gate red on every branch. 0.10.1 fixes both; 0.10.0 changed copy and CI only, and the pin (~> 0.10.1) excludes the affected releases. The MCP suite passes on 0.10.1 (62 tests), including the catalog load that now refuses a schema keyword it would not enforce; the full gate passes. Signed-off-by: Ayla Croft --- THIRD_PARTY_LICENSES.md | 2 +- VERSIONS.md | 2 +- lib/trinity/versions.ex | 4 ++-- mix.exs | 2 +- mix.lock | 2 +- test/trinity/mcp/boundary_test.exs | 11 ++++++----- 6 files changed, 12 insertions(+), 11 deletions(-) diff --git a/THIRD_PARTY_LICENSES.md b/THIRD_PARTY_LICENSES.md index b56273d..1bc334e 100644 --- a/THIRD_PARTY_LICENSES.md +++ b/THIRD_PARTY_LICENSES.md @@ -23,7 +23,7 @@ it, and a reader should not infer from an entry here that the component is in a | `asn1` | `5.4.3` | Apache-2.0 | bom | | `axon` | `0.8.1` | Apache-2.0 | bom | | `bandit` | `1.12.5` | MIT | bom | -| `beam_mcp` | `0.9.0` | Apache-2.0 | bom | +| `beam_mcp` | `0.10.1` | Apache-2.0 | bom | | `boundary` | `0.10.4` | MIT | bom | | `bumblebee` | `0.7.1` | Apache-2.0 | bom | | `bunt` | `1.0.0` | MIT | bom | diff --git a/VERSIONS.md b/VERSIONS.md index 4cf769e..42ed347 100644 --- a/VERSIONS.md +++ b/VERSIONS.md @@ -96,7 +96,7 @@ never pin a version hex marks as retired or vulnerable. | `oban_web` | ~> 2.13 | ✅ in `mix.lock` | The Oban dashboard, a LiveView mounted at /oban (dev, and behind `config :trinity, :oban_web, true` elsewhere). Apache-2.0 on hex.pm since the 2.12 line (2.13.0 measured 2026-09-22); the plan of 2026-09-05 wrote it in when it was commercial. Added at Slice 050. | | `req` | ~> 0.5 | ✅ in `mix.lock` | HTTP client. | | `req_llm` | ~> 1.22 | ✅ in `mix.lock` | Provider layer (streaming, tools, structured output, usage). ⚠️ The pin was `~> 1.10` against a recorded latest of 1.10.0; the real latest was twelve minors ahead. Check event shapes against the current version at Slice 011, not against this file's prose. Added at Slice 011. | -| `beam_mcp` | ~> 0.9 | ✅ in `mix.lock` | MCP server core, Apache-2.0, ADR-0007 decision 5 (owner decision 2026-09-08, recorded 2026-09-20). 0.9.0 on hex.pm (2026-09-22): the :server seam on both transports and the core server as a named behaviour, which slice 061's wrapper implements; standing before 1.0.0. Server side only: the client, MRTR and OAuth are Trinity's, above it. Added at Slice 059, bumped at 061. The earlier candidate list (anubis_mcp, fastest_mcp, gen_mcp) is history. | +| `beam_mcp` | ~> 0.10.1 | ✅ in `mix.lock` | MCP server core, Apache-2.0, ADR-0007 decision 5 (owner decision 2026-09-08, recorded 2026-09-20). 0.9.0 on hex.pm (2026-09-22): the :server seam on both transports and the core server as a named behaviour, which slice 061's wrapper implements; standing before 1.0.0. Bumped 2026-10-08 to 0.10.1 (2026-09-26), a security patch: `mix hex.audit` refused 0.9.0 for EEF-CVE-2026-88257 (nested schema constraints advertised, not enforced) and EEF-CVE-2026-104634 (JSON booleans and null reached dispatch as strings); 0.10.0 changed copy and CI only, and the pin excludes it. Server side only: the client, MRTR and OAuth are Trinity's, above it. Added at Slice 059, bumped at 061. The earlier candidate list (anubis_mcp, fastest_mcp, gen_mcp) is history. | | `jido` | not used (ADR-0009, decided 2026-09-20) | 🔍 not a single package | Measured at the Slice 012 checkpoint and not adopted: the agent runtime duplicates PubSub, Oban and the gateways and adds a second tool executor; the action shape is written in-tree at Slice 020 with `jsv` for its schemas. The row stays so the decision is visible where a reader would look for the package. | | `jason` | ~> 1.2 | ✅ in `mix.lock` | | | `boundary` | ~> 0.10 | ✅ in `mix.lock` | Compile-time module dependency enforcement. Measured at Slice 000: it compiles and enforces on Elixir 1.20.4 / OTP 28, and it reports violations as **warnings**, so it enforces only while `--warnings-as-errors` is on the compile step. ⚠️ No release since 2024-09-25. | diff --git a/lib/trinity/versions.ex b/lib/trinity/versions.ex index 5b984be..77e9b11 100644 --- a/lib/trinity/versions.ex +++ b/lib/trinity/versions.ex @@ -198,10 +198,10 @@ defmodule Trinity.Versions do }, %{ name: "beam_mcp", - pin: "~> 0.9", + pin: "~> 0.10.1", lock: "beam_mcp", note: - "MCP server core, Apache-2.0, ADR-0007 decision 5 (owner decision 2026-09-08, recorded 2026-09-20). 0.9.0 on hex.pm (2026-09-22): the :server seam on both transports and the core server as a named behaviour, which slice 061's wrapper implements; standing before 1.0.0. Server side only: the client, MRTR and OAuth are Trinity's, above it. Added at Slice 059, bumped at 061. The earlier candidate list (anubis_mcp, fastest_mcp, gen_mcp) is history." + "MCP server core, Apache-2.0, ADR-0007 decision 5 (owner decision 2026-09-08, recorded 2026-09-20). 0.9.0 on hex.pm (2026-09-22): the :server seam on both transports and the core server as a named behaviour, which slice 061's wrapper implements; standing before 1.0.0. Bumped 2026-10-08 to 0.10.1 (2026-09-26), a security patch: `mix hex.audit` refused 0.9.0 for EEF-CVE-2026-88257 (nested schema constraints advertised, not enforced) and EEF-CVE-2026-104634 (JSON booleans and null reached dispatch as strings); 0.10.0 changed copy and CI only, and the pin excludes it. Server side only: the client, MRTR and OAuth are Trinity's, above it. Added at Slice 059, bumped at 061. The earlier candidate list (anubis_mcp, fastest_mcp, gen_mcp) is history." }, %{ name: "jido", diff --git a/mix.exs b/mix.exs index f68e239..ae3c6ac 100644 --- a/mix.exs +++ b/mix.exs @@ -185,7 +185,7 @@ defmodule Trinity.MixProject do {:file_system, "~> 1.1"}, # Slice 059: the MCP server core (ADR-0007 decision 5), reached only through the # Trinity.MCP boundary; the slice measures its gap, 060 and 061 build on it. - {:beam_mcp, "~> 0.9"}, + {:beam_mcp, "~> 0.10.1"}, # Slice 050: durable scheduled work. Oban's Lite engine on SQLite, the Basic engine on # Postgres; Oban Web is the dashboard, Apache-2.0 on hex since its 2.12 line. {:oban, "~> 2.24"}, diff --git a/mix.lock b/mix.lock index e661a48..e58f829 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "abnf_parsec": {:hex, :abnf_parsec, "2.1.0", "c4e88d5d089f1698297c0daced12be1fb404e6e577ecf261313ebba5477941f9", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "e0ed6290c7cc7e5020c006d1003520390c9bdd20f7c3f776bd49bfe3c5cd362a"}, "axon": {:hex, :axon, "0.8.1", "c4a975e62a14ab6c374997b77367ec3a4c2740952ac474d3b0f202c91b7f75c4", [:mix], [{:kino, "~> 0.7", [hex: :kino, repo: "hexpm", optional: true]}, {:kino_vega_lite, "~> 0.1.7", [hex: :kino_vega_lite, repo: "hexpm", optional: true]}, {:nx, "~> 0.10", [hex: :nx, repo: "hexpm", optional: false]}, {:polaris, "~> 0.1", [hex: :polaris, repo: "hexpm", optional: false]}, {:table_rex, "~> 3.1 or ~> 4.1", [hex: :table_rex, repo: "hexpm", optional: true]}], "hexpm", "682a3517489300507ac9345f28341e7fa95bc5b4960d645816074ce551795d37"}, "bandit": {:hex, :bandit, "1.12.5", "af205a8e550f304caae09a97d29fd3c79a7f337526ea7cd772d2ff11d2f7c800", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.5", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "c5684ca062fa407cac115aec3256383f3e2ec9fdced7904d59cf5a7bb7ed6181"}, - "beam_mcp": {:hex, :beam_mcp, "0.9.0", "05def1a4d6b4d24fa37531c975d6e4799d14fd3a7bc3557d1446748fdac0c762", [:mix], [{:bandit, "~> 1.5", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2bf9615c901174210a09b31e4f88e3abb1ff6a092fffd2de0b7b02a25b9caa0d"}, + "beam_mcp": {:hex, :beam_mcp, "0.10.1", "7345827f19db43b07c32707374a813bf781687eaf6ee1297beb89e113f86a0e9", [:mix], [{:bandit, "~> 1.5", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.16", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d59b6e75b8c5d06a9d5c71711b1cab4ad7fb84f96495e7907822aa0e3966da20"}, "boundary": {:hex, :boundary, "0.10.4", "5fec5d2736c12f9bfe1720c3a2bd8c48c3547c24d6002ebf8e087570afd5bd2f", [:mix], [], "hexpm", "8baf6f23987afdb1483033ed0bde75c9c703613c22ed58d5f23bf948f203247c"}, "bumblebee": {:hex, :bumblebee, "0.7.1", "0d6a757f955671a379ebcf4ed07565513fa767b1869169b989f65ba7958a80f4", [:mix], [{:axon, "~> 0.8.0", [hex: :axon, repo: "hexpm", optional: false]}, {:jason, "~> 1.4.0", [hex: :jason, repo: "hexpm", optional: false]}, {:nx, "~> 0.12.0 or ~> 0.13.0", [hex: :nx, repo: "hexpm", optional: false]}, {:nx_image, "~> 0.1.0", [hex: :nx_image, repo: "hexpm", optional: false]}, {:nx_signal, "~> 0.2.0", [hex: :nx_signal, repo: "hexpm", optional: false]}, {:safetensors, "~> 0.1.3", [hex: :safetensors, repo: "hexpm", optional: false]}, {:tokenizers, "~> 0.4", [hex: :tokenizers, repo: "hexpm", optional: false]}, {:unpickler, "~> 0.1.0", [hex: :unpickler, repo: "hexpm", optional: false]}, {:unzip, "~> 0.12.0 or ~> 0.13.0", [hex: :unzip, repo: "hexpm", optional: false]}], "hexpm", "f26b3355700e3c7580014d41ce477d87d9fd71a60b76d5b64701dacb07830a58"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, diff --git a/test/trinity/mcp/boundary_test.exs b/test/trinity/mcp/boundary_test.exs index 93ed4c6..b5d9bea 100644 --- a/test/trinity/mcp/boundary_test.exs +++ b/test/trinity/mcp/boundary_test.exs @@ -12,12 +12,13 @@ defmodule Trinity.MCP.BoundaryTest do """ use ExUnit.Case, async: true - # Slice 061 bumped the pin to 0.9.0 (the :server seam); the row and the lock moved together. - test "beam_mcp is in mix.lock at 0.9.0 and the VERSIONS row reads in mix.lock" do + # Slice 061 bumped the pin to 0.9.0 (the :server seam); 2026-10-08 to 0.10.1, the security + # patch `mix hex.audit` asked for. The row and the lock move together. + test "beam_mcp is in mix.lock at 0.10.1 and the VERSIONS row reads in mix.lock" do lock = Mix.Dep.Lock.read() - assert {:hex, :beam_mcp, "0.9.0", _, _, _, _, _} = lock[:beam_mcp] - assert File.read!("VERSIONS.md") =~ ~r/`beam_mcp` \| ~> 0\.9 \| ✅ in `mix\.lock`/ - assert Trinity.MCP.core_version() == "0.9.0" + assert {:hex, :beam_mcp, "0.10.1", _, _, _, _, _} = lock[:beam_mcp] + assert File.read!("VERSIONS.md") =~ ~r/`beam_mcp` \| ~> 0\.10\.1 \| ✅ in `mix\.lock`/ + assert Trinity.MCP.core_version() == "0.10.1" end test "the boundary compiler checks calls into beam_mcp everywhere, and Trinity.MCP is the boundary that lists it" do