From aaa9e2a370d6c5fbf5414bb9505d2b75191b5e1c Mon Sep 17 00:00:00 2001 From: FragginWagon Date: Wed, 9 Sep 2026 22:42:35 -0400 Subject: [PATCH] fix: require https for external pricing providers Require HTTPS-only external pricing-provider URLs and verify the adapter contract with the application suite. --- .../providers/http-pricing-provider.js | 13 +++++++++++- .../application/pricing-provider.test.js | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/apps/api/src/modules/pricing/providers/http-pricing-provider.js b/apps/api/src/modules/pricing/providers/http-pricing-provider.js index 654ef3a..b61d916 100644 --- a/apps/api/src/modules/pricing/providers/http-pricing-provider.js +++ b/apps/api/src/modules/pricing/providers/http-pricing-provider.js @@ -10,10 +10,21 @@ export function createHttpPricingProvider({ throw new Error('Pricing provider endpoint is required.'); } + let parsedUrl; + try { + parsedUrl = new URL(endpoint); + } catch { + throw new Error('Pricing provider endpoint must be a valid HTTPS URL.'); + } + + if (parsedUrl.protocol !== 'https:') { + throw new Error('Pricing provider endpoint must use HTTPS.'); + } + return createPricingProvider({ id, async observe(input) { - const url = new URL(endpoint); + const url = new URL(parsedUrl.toString()); for (const [key, value] of Object.entries(input)) { if (value) url.searchParams.set(key, value); } diff --git a/apps/api/tests/application/pricing-provider.test.js b/apps/api/tests/application/pricing-provider.test.js index f2972ce..48b4872 100644 --- a/apps/api/tests/application/pricing-provider.test.js +++ b/apps/api/tests/application/pricing-provider.test.js @@ -58,6 +58,26 @@ test("fixture provider returns deterministic normalized observations", async () }); }); +test("http provider rejects insecure or malformed external provider URLs", () => { + assert.throws( + () => + createHttpPricingProvider({ + id: "http-provider", + endpoint: "http://provider.example/prices", + }), + /HTTPS/i, + ); + + assert.throws( + () => + createHttpPricingProvider({ + id: "http-provider", + endpoint: "not-a-url", + }), + /valid https URL/i, + ); +}); + test("http provider sends mapping context and normalizes its response", async () => { let request; const provider = createHttpPricingProvider({