From 0572a2cffd298b22dca4c9256b129901f37f2a54 Mon Sep 17 00:00:00 2001 From: Scott Karp Date: Sun, 23 Aug 2026 12:00:32 -0400 Subject: [PATCH] =?UTF-8?q?specs=20=C2=A71.5=20+=20Doorpost:=20postgrex=20?= =?UTF-8?q?~>=200.22.3=20=E2=80=94=20ma'akeh=20before=20the=20roof=20is=20?= =?UTF-8?q?walked=20on?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TORAH ANCHOR — Devarim 22:8: כִּי תִבְנֶה בַּיִת חָדָשׁ וְעָשִׂיתָ מַעֲקֶה לְגַגֶּךָ וְלֹא תָשִׂים דָּמִים בְּבֵיתֶךָ כִּי יִפֹּל הַנֹּפֵל מִמֶּנּוּ. "When you BUILD a new house, make a parapet for your roof, and do not place blood in your house, for the faller will fall from it." The obligation attaches at BUILD time and to the BUILDER — ki tivneh, not ki teshev. The kohen who dwells in the house does not owe the parapet; the one who builds it does. That is why this is Bezalel's commit and not the kohen's, and why it lands before the vessel is handed over rather than after. The roof in question is /peah/ask. It is unauthenticated BY DESIGN — Vayikra 19:9-10, lo techalleh pe'at sadcha b'kutzrecha. The corner is left open on purpose. Ma'akeh is not a wall around the corner; it is what keeps a deliberate opening from becoming a fall. WHAT WAS FOUND (kohen escalation, BUILDER_HANDOFF_amd64.md §Second Finding, confirmed by `mix deps.get` advisory output in an amd64 container on 2026-08-23): postgrex 0.17.5 VULNERABLE EEF-CVE-2026-32687 / GHSA-r73h-97w8-m54h HIGH SQL injection via channel name in Postgrex.Notifications.listen/3 and unlisten/3 introduced 0.16.0, fixed 0.22.2 EEF-CVE-2026-58225 / GHSA-4mw9-4qgj-m97w LOW SQL injection via unescaped dollar-quote in reconnect replay → notification denial of service introduced 0.16.0, fixed 0.22.3 plug 1.19.1 VULNERABLE EEF-CVE-2026-54892 / GHSA-j43x-5hjq-rgxf HIGH quadratic-time decoding of nested query/body parameters → denial of service 1.19.x line fixed in 1.19.3 Affected ranges read from api.osv.dev, not from the advisory titles. There is no 0.17.6; the postgrex fix does not exist below 0.22.2, so the pin must cross two minor lines. 0.22.3 is the lowest version that clears BOTH postgrex advisories. THE SPEC CHANGE (Layer 1, lo_tosif.md): specs/shorashim_vayakhel.md §1.5 {:postgrex, "~> 0.17.4"} → {:postgrex, "~> 0.22.3"} vav_pipeline/lib/vav_pipeline/doorpost.ex @expected_hash c7ac85cd…b98bb6af → ed2a6aec…6b72c2e22 Committed atomically per specs/lo_tosif.md Layer 1: the spec file and its witness move together, in one reviewable unit, with the Torah anchor named. Verified before the hash was updated that the mechanism actually fired — verify_identity/0 returned SPEC_INTEGRITY_FAILED and chatzotzrot :assembly_leaders (teruah) sounded on the drift. The doorpost is not decorative; it caught this change on the way through. NOT A SPEC CHANGE: plug is not pinned in §1.5, so the plug bump (1.19.1 → 1.20.3) is an operations change per lo_tosif.md "What is NOT a spec change" and touches mix.lock only. Same for the transitive movers that came with the resolution: db_connection 2.9.0→2.10.2, decimal 2.3.0→2.4.1, jason 1.4.4→1.4.5, plug_crypto 2.1.1→2.2.0, telemetry 1.4.1→1.4.2. VERIFIED: - `mix deps.get` reports no advisories against the resolved tree - `mix compile --force` clean - `mix test` — 412 tests, 0 failures, 35 excluded (:l3, need PostgreSQL) - VavPipeline.Doorpost.verify_identity() → :ok - l1/integrity.sha256 unchanged: 99bbd07a…4ea377 FLAGGED, NOT FIXED — §1.5 has further drift this commit deliberately does not touch. The block still lists {:phoenix, "~> 1.7.11"} and {:ecto, "~> 3.11.1"}, while vav_pipeline/mix.exs actually depends on ecto_sql, bandit, plug and the sanhedrin path dep, and has never depended on phoenix. Correcting that is a larger category-grade question than the security finding I was handed, and lo tosif says the builder does not widen a commanded change on his own motion. Raised in the handoff-back instead. Co-Authored-By: Claude Opus 5 --- specs/shorashim_vayakhel.md | 2 +- vav_pipeline/lib/vav_pipeline/doorpost.ex | 2 +- vav_pipeline/mix.exs | 2 +- vav_pipeline/mix.lock | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/specs/shorashim_vayakhel.md b/specs/shorashim_vayakhel.md index 8dda94d3..b7c50a8b 100644 --- a/specs/shorashim_vayakhel.md +++ b/specs/shorashim_vayakhel.md @@ -106,7 +106,7 @@ defp deps do {:phoenix, "~> 1.7.11"}, {:jason, "~> 1.4.1"}, {:ecto, "~> 3.11.1"}, - {:postgrex, "~> 0.17.4"}, + {:postgrex, "~> 0.22.3"}, {:telemetry, "~> 1.2.1"} ] end diff --git a/vav_pipeline/lib/vav_pipeline/doorpost.ex b/vav_pipeline/lib/vav_pipeline/doorpost.ex index 9e8a72de..69765515 100644 --- a/vav_pipeline/lib/vav_pipeline/doorpost.ex +++ b/vav_pipeline/lib/vav_pipeline/doorpost.ex @@ -175,7 +175,7 @@ defmodule VavPipeline.Doorpost do # changes; the update is a deliberate operator commit. A bare # hash-update commit (without a corresponding spec change in the # same commit) is itself a drift signal. - @expected_hash "c7ac85cd6968ebceda1d9dbb71ac41ce97e2a5f645b3d486309c315ab98bb6af" + @expected_hash "ed2a6aece482392b4d900d4e3f9947076746b3103e3a8c70d3a97436b72c2e22" @doc "Return the list of files that constitute the category-grade specification." @spec files() :: [String.t()] diff --git a/vav_pipeline/mix.exs b/vav_pipeline/mix.exs index 2665ae4e..562a57cc 100644 --- a/vav_pipeline/mix.exs +++ b/vav_pipeline/mix.exs @@ -36,7 +36,7 @@ defmodule VavPipeline.MixProject do # L3 — Oral Tradition (PostgreSQL append-only) # Architecture §3.7, Construction §1.5 {:ecto_sql, "~> 3.11.1"}, - {:postgrex, "~> 0.17.4"}, + {:postgrex, "~> 0.22.3"}, # Bigdei Kodesh — HTTP API layer (Shemot 28:2) {:bandit, "~> 1.2"}, {:plug, "~> 1.15"} diff --git a/vav_pipeline/mix.lock b/vav_pipeline/mix.lock index e4568d01..a245c112 100644 --- a/vav_pipeline/mix.lock +++ b/vav_pipeline/mix.lock @@ -1,17 +1,17 @@ %{ "bandit": {:hex, :bandit, "1.10.3", "1e5d168fa79ec8de2860d1b4d878d97d4fbbe2fdbe7b0a7d9315a4359d1d4bb9", [: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.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "99a52d909c48db65ca598e1962797659e3c0f1d06e825a50c3d75b74a5e2db18"}, - "db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"}, - "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, + "db_connection": {:hex, :db_connection, "2.10.2", "ae391e803a5adff104da913c2fc1c0c14a37f8b10001dcef568796e1fb7bf95c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "510b14482330f1af6490a2fa0efd8d4f1435d1529b165647df22ac0f2df0fa93"}, + "decimal": {:hex, :decimal, "2.4.1", "6c0fbede12fb122ba685e9ab41c6a40c129e322b3aa192f9e072e61f3a6ffaf2", [:mix], [], "hexpm", "7e618897933a8455f19a727d7c5e50a2c071a544b700e5e724298ecb4340187f"}, "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, "ecto_sql": {:hex, :ecto_sql, "3.11.3", "4eb7348ff8101fbc4e6bbc5a4404a24fecbe73a3372d16569526b0cf34ebc195", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e5f36e3d736b99c7fee3e631333b8394ade4bafe9d96d35669fca2d81c2be928"}, "hpax": {:hex, :hpax, "1.0.3", "ed67ef51ad4df91e75cc6a1494f851850c0bd98ebc0be6e81b026e765ee535aa", [:mix], [], "hexpm", "8eab6e1cfa8d5918c2ce4ba43588e894af35dbd8e91e6e55c817bca5847df34a"}, - "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, + "jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"}, "jsx": {:hex, :jsx, "3.1.0", "d12516baa0bb23a59bb35dccaf02a1bd08243fcbb9efe24f2d9d056ccff71268", [:rebar3], [], "hexpm", "0c5cc8fdc11b53cc25cf65ac6705ad39e54ecc56d1c22e4adb8f5a53fb9427f3"}, "mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"}, - "plug": {:hex, :plug, "1.19.1", "09bac17ae7a001a68ae393658aa23c7e38782be5c5c00c80be82901262c394c0", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "560a0017a8f6d5d30146916862aaf9300b7280063651dd7e532b8be168511e62"}, - "plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"}, - "postgrex": {:hex, :postgrex, "0.17.5", "0483d054938a8dc069b21bdd636bf56c487404c241ce6c319c1f43588246b281", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "50b8b11afbb2c4095a3ba675b4f055c416d0f3d7de6633a595fc131a828a67eb"}, - "telemetry": {:hex, :telemetry, "1.4.1", "ab6de178e2b29b58e8256b92b382ea3f590a47152ca3651ea857a6cae05ac423", [:rebar3], [], "hexpm", "2172e05a27531d3d31dd9782841065c50dd5c3c7699d95266b2edd54c2dafa1c"}, + "plug": {:hex, :plug, "1.20.3", "56c480c633ec2ce10140e236e15233bf576e1d323887d7c96711bd02ab5160db", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "be266aee1b8536ef6409d58cf39a3121319f0ec47cfa1b24024485aa0e76ad76"}, + "plug_crypto": {:hex, :plug_crypto, "2.2.0", "144014737daaf485407f5ed77daeaad74d651b216a28c87543f8cc7043f8efc8", [:mix], [], "hexpm", "83a95744ab1c75876542b6fab135fcc176280e0f301a111c1f757fddcec95d2c"}, + "postgrex": {:hex, :postgrex, "0.22.4", "d271f595dfd25230b6398354e19d17bb5e2d20130fd2d9bdca7e15f125d43552", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "4aae45a2d60e35b04eea2602440be152fae332901f1fc7a60fc7cb7f0f9a9c5a"}, + "telemetry": {:hex, :telemetry, "1.4.2", "a0cb522801dffb1c49fe6e30561badffc7b6d0e180db1300df759faa22062855", [:rebar3], [], "hexpm", "928f6495066506077862c0d1646609eed891a4326bee3126ba54b60af61febb1"}, "thousand_island": {:hex, :thousand_island, "1.4.3", "2158209580f633be38d43ec4e3ce0a01079592b9657afff9080d5d8ca149a3af", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6e4ce09b0fd761a58594d02814d40f77daff460c48a7354a15ab353bb998ea0b"}, "websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"}, }