Skip to content

Commit d14466a

Browse files
fix(dns): trust the name, not the value after --registry
`dns trust <name>` found the name with `rest.find(a => !a.startsWith("-"))`, which grabs the value after `--registry`/`--port` (a URL does not start with "-"). So `dns trust --registry <url> <name>` tried to trust the registry host and silently dropped <name> — and `--registry` is exactly the flag `trust` exists to use, since it verifies the served key against that registry's pin. Use the resolveArgument parser the sibling `resolve` verb already uses one line below, which skips those flags and their values. Adds a regression test through dnsCommand plus a control on the plain no-flag form. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent dffd166 commit d14466a

2 files changed

Lines changed: 42 additions & 1 deletion

File tree

src/dns.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2047,7 +2047,11 @@ export async function dnsCommand(args = [], out = console.log, deps = {}) {
20472047
}
20482048

20492049
if (sub === "trust") {
2050-
return trustName(rest.find((a) => !a.startsWith("-")) || "", out, { registryBase, ...deps });
2050+
// resolveArgument, not a bare `find(!startsWith("-"))`: the latter grabs the
2051+
// value after `--registry`/`--port` (a URL does not start with "-"), so
2052+
// `dns trust --registry <url> <name>` would trust the registry host instead
2053+
// of <name>. The sibling `resolve` verb below already parses it this way.
2054+
return trustName(resolveArgument(rest) || "", out, { registryBase, ...deps });
20512055
}
20522056

20532057
if (sub === "resolve") {

test/dns-trust-arg.test.mjs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import assert from "node:assert/strict";
2+
import test from "node:test";
3+
4+
import { dnsCommand } from "../src/dns.mjs";
5+
6+
// `dns trust <name>` picks the name out of the argument list itself. The list
7+
// can carry `--registry <url>` — the flag is documented for `dns` and is the
8+
// natural one to pass to `trust`, whose whole job is checking the served key
9+
// against the registry's published pin. The name must survive that flag.
10+
//
11+
// The certificate fetch is stubbed to fail, which makes trustName report the
12+
// exact name it tried to read a cert for — so the first output line is a clean
13+
// witness of which token was parsed as the name.
14+
function runTrust(args) {
15+
const output = [];
16+
const runner = async () => ({ ok: false, stdout: "", stderr: "", code: 1 });
17+
return dnsCommand(args, (line) => output.push(String(line)), { runner })
18+
.then(() => output);
19+
}
20+
21+
test("dns trust reads the name, not the value after --registry", async () => {
22+
const output = await runTrust(["trust", "--registry", "https://reg.example", "blue.eggs"]);
23+
assert.match(output[0], /blue\.eggs:443/);
24+
assert.doesNotMatch(output[0], /reg\.example/);
25+
});
26+
27+
test("dns trust reads the name, not the value after --port", async () => {
28+
const output = await runTrust(["trust", "--port", "8443", "blue.eggs"]);
29+
assert.match(output[0], /blue\.eggs:443/);
30+
});
31+
32+
// Control: the plain form has to keep behaving exactly the same, so the fix is
33+
// visibly a no-op on the path that already worked.
34+
test("dns trust with no flags still reads the name", async () => {
35+
const output = await runTrust(["trust", "blue.eggs"]);
36+
assert.match(output[0], /blue\.eggs:443/);
37+
});

0 commit comments

Comments
 (0)