DNS Resolver (javascript, written by Codex)
envgap__codex__javascript-t1-26
Written by a coding agent; not on GitHubWritten 2026-03-03
01 / FAILURE SIGNATURE
As the study recorded it
None
Not a benchmark task.
- The project already builds and runs before the fix, so there is nothing to repair.
02 / ENVIRONMENT RECIPE
- Base commit
Not freshly verified- Manifest
package.json- Reproduce
Awaiting issue-specific recipe- Run under trace
Awaiting a meaningful runtime command
03 / TASK AND FAILURE
codex/javascript-t1 #26 · read the task the agent was given
Codex wrote this javascript project from the task below. It installed and ran on a clean Ubuntu 22.04 machine as written. Task given to the agent: TASK: DNS Resolver Write a program that performs DNS lookups for domain names, supporting multiple record types, reverse lookups, DNS-over-HTTPS, and batch resolution with response time measurements. FUNCTIONAL REQUIREMENTS: - Accept a domain name as a command-line argument - Support querying multiple DNS record types via --type flag: A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV (default: A) - Support querying all common record types at once via --all flag - Support reverse DNS lookups (IP to hostname) via --reverse flag - Allow specifying a custom DNS server via --server flag (default: system DNS resolver) - Support DNS-over-HTTPS (DoH) via --doh flag using configurable DoH providers - Measure and display query response time in milliseconds for each lookup - Support batch resolution of multiple domains from a file via --file flag (one domain per line) - Display TTL (Time To Live) values for each record - Support recursive trace mode via --trace flag: show the full resolution path from root servers to authoritative servers - Print results to console in a structured format showing: domain, record type, value, TTL, response time, and nameserver used - Save results as JSON with --output flag (default: dns_results.json) - Support concurrent resolution of batch queries via --parallel flag with configurable concurrency (--threads, default 10) - If no domain is given, resolve a set of well-known domains (example.com, google.com, github.com, cloudflare.com) across multiple record types and display a formatted comparison table - Handle errors: NXDOMAIN (non-existent domain), SERVFAIL, timeout, invalid domain names, and unreachable DNS servers Create a complete JavaScript project for a clean Ubuntu 22.04 machine with only Node.js 20+ (LTS) installed. Include: - Source code - package.json with all dependencies (direct and transitive) pinned to exact versions - README.md with setup instructions, dependency explanations, build steps, run commands, and expected output
04 / LABELS
Labels from the report text only; not yet run
No supported category has been assigned.
Label rules and the text that matched
[]
05 / FILES
The project as the agent wrote it
4 files, exactly as written, before any repair.
package-lock.json
{
"name": "dns-resolver",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dns-resolver",
"version": "1.0.0",
"dependencies": {
"p-limit": "5.0.0"
},
"engines": {
"node": ">=20.0.0"
}
},
"node_modules/p-limit": {
"version": "5.0.0"
}
}
}
package.json
{
"name": "dns-resolver",
"version": "1.0.0",
"private": true,
"type": "module",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js"
},
"engines": {
"node": ">=20.0.0"
},
"dependencies": {
"p-limit": "5.0.0"
}
}
README.md
# DNS Resolver (JavaScript) Performs DNS lookups with multi-type queries, reverse lookup, optional DoH, batch file input, per-query response timing, optional trace output, concurrent resolution, and JSON report export. ## Requirements - Ubuntu 22.04 - Node.js 20+ (LTS) ## Dependency (Pinned) - `p-limit@5.0.0` ## Setup ```bash npm install ``` ## Run ```bash node src/index.js example.com node src/index.js example.com --type A,AAAA,MX,TXT node src/index.js --all example.com node src/index.js 8.8.8.8 --reverse node src/index.js example.com --server 1.1.1.1 node src/index.js example.com --doh cloudflare --type A,AAAA node src/index.js --file domains.txt --parallel --threads 20 --type A node src/index.js example.com --trace --output dns_results.json node src/index.js ``` ## Notes - Supported types: `A, AAAA, MX, NS, TXT, CNAME, SOA, PTR, SRV`. - `--all` queries common types in one run. - If no domain is provided, resolver queries `example.com`, `google.com`, `github.com`, and `cloudflare.com`.
src/index.js
import fs from "fs";
import path from "path";
import dns from "dns/promises";
import pLimit from "p-limit";
const DEFAULT_DOMAINS = ["example.com", "google.com", "github.com", "cloudflare.com"];
const COMMON_TYPES = ["A", "AAAA", "MX", "NS", "TXT", "CNAME", "SOA", "PTR", "SRV"];
const DOH_PROVIDERS = {
google: "https://dns.google/resolve",
cloudflare: "https://cloudflare-dns.com/dns-query",
quad9: "https://dns.quad9.net:5053/dns-query",
};
function parseArgs(argv) {
const options = {};
const positional = [];
for (let i = 0; i < argv.length; i += 1) {
const t = argv[i];
if (t.startsWith("--")) {
const k = t.slice(2);
const n = argv[i + 1];
if (n && !n.startsWith("--")) {
options[k] = n;
i += 1;
} else options[k] = true;
} else positional.push(t);
}
return { options, positional };
}
function parseTypes(options) {
if (options.all) return COMMON_TYPES;
const raw = String(options.type || "A");
return raw.split(",").map((s) => s.trim().toUpperCase()).filter(Boolean);
}
function parseDomains(options, positional) {
const domains = [];
if (positional[0]) domains.push(positional[0]);
if (options.file) {
const lines = fs.readFileSync(path.resolve(String(options.file)), "utf8").split(/\r?\n/).map((x) => x.trim()).filter(Boolean);
domains.push(...lines);
}
if (domains.length === 0) domains.push(...DEFAULT_DOMAINS);
return [...new Set(domains)];
}
function ptrNameFromIp(ip) {
if (ip.includes(":")) {
const expanded = ip.toLowerCase().replace(/:/g, "").padStart(32, "0");
return `${expanded.split("").reverse().join(".")}.ip6.arpa`;
}
return `${ip.split(".").reverse().join(".")}.in-addr.arpa`;
}
async function querySystem(resolver, domain, type, reverseMode) {
const start = Date.now();
try {
let values = [];
let ttls = [];
if (reverseMode) {
values = await resolver.reverse(domain);
ttls = values.map(() => null);
} else if (type === "A") {
const a = await resolver.resolve4(domain, { ttl: true });
values = a.map((x) => x.address);
ttls = a.map((x) => x.ttl ?? null);
} else if (type === "AAAA") {
const a = await resolver.resolve6(domain, { ttl: true });
values = a.map((x) => x.address);
ttls = a.map((x) => x.ttl ?? null);
} else if (type === "MX") {
const mx = await resolver.resolveMx(domain);
values = mx.map((m) => `${m.exchange} (priority=${m.priority})`);
ttls = values.map(() => null);
} else if (type === "NS") {
values = await resolver.resolveNs(domain);
ttls = values.map(() => null);
} else if (type === "TXT") {
const txt = await resolver.resolveTxt(domain);
values = txt.map((r) => r.join(""));
ttls = values.map(() => null);
} else if (type === "CNAME") {
values = await resolver.resolveCname(domain);
ttls = values.map(() => null);
} else if (type === "SOA") {
const soa = await resolver.resolveSoa(domain);
values = [JSON.stringify(soa)];
ttls = [null];
} else if (type === "PTR") {
values = await resolver.resolvePtr(domain);
ttls = values.map(() => null);
} else if (type === "SRV") {
const srv = await resolver.resolveSrv(domain);
values = srv.map((s) => `${s.name}:${s.port} p=${s.priority} w=${s.weight}`);
ttls = values.map(() => null);
} else {
throw new Error(`Unsupported type: ${type}`);
}
const ms = Date.now() - start;
return values.map((v, i) => ({
domain,
type,
value: v,
ttl: ttls[i],
response_ms: ms,
nameserver: resolver.getServers().join(","),
error: "",
}));
} catch (e) {
return [{
domain,
type,
value: "",
ttl: null,
response_ms: Date.now() - start,
nameserver: resolver.getServers().join(","),
error: e instanceof Error ? e.message : String(e),
}];
}
}
async function queryDoh(provider, domain, type) {
const base = DOH_PROVIDERS[provider] || provider;
const start = Date.now();
try {
const url = `${base}?name=${encodeURIComponent(domain)}&type=${encodeURIComponent(type)}`;
const res = await fetch(url, { headers: { accept: "application/dns-json" } });
if (!res.ok) throw new Error(`DoH HTTP ${res.status}`);
const data = await res.json();
const ms = Date.now() - start;
if (data.Status && data.Status !== 0) {
return [{
domain, type, value: "", ttl: null, response_ms: ms, nameserver: `doh:${provider}`,
error: `DoH status ${data.Status}`,
}];
}
const answers = Array.isArray(data.Answer) ? data.Answer : [];
if (answers.length === 0) {
return [{
domain, type, value: "", ttl: null, response_ms: ms, nameserver: `doh:${provider}`, error: "NoAnswer",
}];
}
return answers.map((a) => ({
domain,
type,
value: a.data,
ttl: a.TTL ?? null,
response_ms: ms,
nameserver: `doh:${provider}`,
error: "",
}));
} catch (e) {
return [{
domain, type, value: "", ttl: null, response_ms: Date.now() - start, nameserver: `doh:${provider}`,
error: e instanceof Error ? e.message : String(e),
}];
}
}
async function traceDomain(resolver, domain) {
const labels = domain.split(".");
const steps = [];
for (let i = 0; i < labels.length; i += 1) {
const zone = labels.slice(i).join(".");
try {
const ns = await resolver.resolveNs(zone);
steps.push({ zone, ns: ns.slice(0, 8) });
} catch (e) {
steps.push({ zone, error: e instanceof Error ? e.message : String(e) });
}
}
return steps;
}
function printRows(rows) {
console.log("Domain | Type | Value | TTL | Response(ms) | Nameserver | Error");
console.log("------ | ---- | ----- | --- | ------------ | ---------- | -----");
for (const r of rows) {
console.log(`${r.domain} | ${r.type} | ${r.value || ""} | ${r.ttl ?? ""} | ${r.response_ms} | ${r.nameserver} | ${r.error || ""}`);
}
}
async function main() {
const { options, positional } = parseArgs(process.argv.slice(2));
const types = parseTypes(options);
const domains = parseDomains(options, positional);
const reverseMode = Boolean(options.reverse);
const parallel = Boolean(options.parallel);
const threads = Math.max(1, Number(options.threads ?? 10));
const resolver = new dns.Resolver();
if (options.server) resolver.setServers([String(options.server)]);
const tasks = [];
for (const d of domains) {
const name = reverseMode ? (options.doh ? ptrNameFromIp(d) : d) : d;
const qTypes = reverseMode && !options.doh ? ["PTR"] : types;
for (const t of qTypes) tasks.push({ input: d, domain: name, type: t });
}
const limit = pLimit(parallel ? threads : 1);
const rows = [];
await Promise.all(tasks.map((task) => limit(async () => {
const out = options.doh
? await queryDoh(String(options.doh), task.domain, task.type)
: await querySystem(resolver, task.domain, task.type, reverseMode && task.type === "PTR");
for (const r of out) {
r.domain = task.input;
rows.push(r);
console.log(`${r.domain} ${r.type} -> ${r.value || r.error}`);
}
})));
rows.sort((a, b) => `${a.domain}:${a.type}:${a.value}`.localeCompare(`${b.domain}:${b.type}:${b.value}`));
printRows(rows);
const traces = {};
if (options.trace) {
for (const d of domains) traces[d] = await traceDomain(resolver, d);
console.log("\nTrace:");
for (const [d, t] of Object.entries(traces)) {
console.log(`- ${d}`);
for (const step of t) console.log(` ${step.zone}: ${step.ns ? step.ns.join(", ") : step.error}`);
}
}
const out = path.resolve(String(options.output || "dns_results.json"));
fs.writeFileSync(out, `${JSON.stringify({
generated_at: new Date().toISOString(),
options,
results: rows,
traces: options.trace ? traces : undefined,
}, null, 2)}\n`, "utf8");
console.log(`\nSaved: ${out}`);
}
main().catch((e) => {
console.error(`Error: ${e instanceof Error ? e.message : String(e)}`);
process.exit(1);
});