From 376dfbd2c25ca26b08caefa9a6ac18395a6f1d37 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 30 Sep 2026 14:46:22 +0200 Subject: [PATCH] Startup database failure names the input and a code, not the URL's parts The entrypoint harness showed pg printing a piece of the database URL file on a failed startup: `getaddrinfo ENOTFOUND ` for an unresolvable host. A password with an unescaped delimiter moves part of itself into the host or the database name, and the resolver or server error then prints it. The only thing keeping a malformed URL out of stderr was pg dropping Node's `input` property (Soul S5). createStore now turns a schema-preparation failure into one error naming GC_ACCESS_DATABASE_URL_FILE and the error code, with no cause. The harness cases expect that message, and a new case puts the canary in the host. Co-Authored-By: Claude Opus 5.5 --- src/store/index.ts | 13 ++++++++++++- tests/entrypoint-secrets.test.ts | 15 +++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/store/index.ts b/src/store/index.ts index 7617594..90ffd79 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -14,7 +14,18 @@ export async function createStore(config: HeimdallConfig): Promise ({ GC_ACCESS_DATABASE_URL_FILE: file("db-port", `postgres://heimdall:${CANARY}port@db:notaport/heimdall\n`) }), - expect: /./, + expect: /Postgres storage could not be prepared \(ERR_INVALID_URL\)/, }, { name: "a database URL that does not parse", env: () => ({ GC_ACCESS_DATABASE_URL_FILE: file("db-parse", `postgres://heimdall:${CANARY} parse@[bad/heimdall\n`) }), - expect: /./, + expect: /Postgres storage could not be prepared \(E[A-Z_]+\)/, }, { name: "a database URL with a broken percent escape", env: () => ({ GC_ACCESS_DATABASE_URL_FILE: file("db-percent", `postgres://heimdall:${CANARY}%zz@127.0.0.1:1/heimdall\n`) }), - expect: /./, + expect: /Postgres storage could not be prepared \(ECONNREFUSED\)/, }, { name: "a database that refuses the connection", env: () => ({ GC_ACCESS_DATABASE_URL_FILE: file("db-refused", `postgres://heimdall:${CANARY}refused@127.0.0.1:1/heimdall\n`) }), - expect: /ECONNREFUSED/, + expect: /Postgres storage could not be prepared \(ECONNREFUSED\)/, + }, + { + // A password holding an unescaped delimiter moves part of it into the + // host, and the resolver's error names the host. + name: "a database host that does not resolve", + env: () => ({ GC_ACCESS_DATABASE_URL_FILE: file("db-host", `postgres://heimdall:pw@${CANARY}host.invalid/heimdall\n`) }), + expect: /Postgres storage could not be prepared \(E[A-Z_]+\)/, }, { name: "private key text bound to the signing key path",