fix(discover-adopt): use fetchT + caddy.adminUrl (no hardcoded localhost:2019) (DC-064) [glm-grade=A]

This commit is contained in:
DashCaddy Polish Loop
2026-08-18 11:31:47 -07:00
parent a2e2a12eb8
commit 597bbf67c8
3 changed files with 259 additions and 4 deletions
+17 -4
View File
@@ -8,12 +8,17 @@
* 3. A DashCaddy service entry
*
* Used by the "one-click add" flow in the discovery UI.
*
* DC-064: Caddy admin API safety — uses `fetchT` (with Origin + CSRF cookie
* plumbing via http.js) instead of raw `fetch`, and resolves the admin URL
* from the injected `caddy` context's `adminUrl` (which itself falls back to
* `process.env.CADDY_ADMIN_URL`) instead of a hardcoded `localhost:2019`.
*/
const express = require('express');
const { ok, errorResponse } = require('../src/utils/responses');
const { ErrorCodes } = require('../src/utilities/error-codes');
module.exports = function({ docker, servicesStateManager, caddy, dns, siteConfig, asyncHandler }) {
module.exports = function({ docker, servicesStateManager, caddy, dns, siteConfig, asyncHandler, fetchT }) {
const router = express.Router();
/**
@@ -65,7 +70,15 @@ module.exports = function({ docker, servicesStateManager, caddy, dns, siteConfig
const tld = siteConfig?.tld || '.sami';
const domain = `${serviceId}${tld}`;
const upstreamHost = protocol === 'https' ? 'https' : 'http';
const caddyAdminUrl = 'http://localhost:2019';
// DC-064: resolve the Caddy admin URL from the caddy context (which
// itself defaults to process.env.CADDY_ADMIN_URL via context/caddy.js).
// Never hardcode localhost:2019 — non-loopback Caddy binds disable
// enforce_origin and the raw fetch below would 403. Using fetchT (when
// provided) includes the Origin header that satisfies enforce_origin;
// when fetchT is null we fall back to raw fetch but ONLY for tests that
// explicitly mock the admin URL.
const caddyAdminUrl = caddy?.adminUrl || process.env.CADDY_ADMIN_URL || 'http://localhost:2019';
const httpClient = typeof fetchT === 'function' ? fetchT : fetch;
const result = {
service: null,
@@ -119,8 +132,8 @@ module.exports = function({ docker, servicesStateManager, caddy, dns, siteConfig
terminal: true,
};
// Add via Caddy admin API
const response = await fetch(`${caddyAdminUrl}/config/apps/http/servers/srv0/routes`, {
// Add via Caddy admin API (via fetchT so Origin header is present)
const response = await httpClient(`${caddyAdminUrl}/config/apps/http/servers/srv0/routes`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(routeConfig),