crtsh_search
Search Certificate Transparency logs to discover subdomains and analyze SSL/TLS certificates for domain reconnaissance and attack surface mapping.
Instructions
Search Certificate Transparency logs via crt.sh. Returns unique subdomains and certificate details (issuer, validity, SANs).
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Domain to search CT logs for | |
| exclude_expired | No | Exclude expired certificates (default: false) |
Implementation Reference
- src/crtsh/index.ts:27-87 (handler)The core implementation of the crtsh_search tool. It queries crt.sh, processes the JSON response, deduplicates subdomains, handles expiration filtering, and caches results.
export async function crtshSearch(domain: string, excludeExpired = false): Promise<CrtshResult> { const cacheKey = `${domain}:${excludeExpired}`; const cached = cache.get(cacheKey); if (cached) return cached; await limiter.acquire(); const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 30000); try { const url = `https://crt.sh/?q=%25.${encodeURIComponent(domain)}&output=json`; const res = await fetch(url, { signal: controller.signal }); if (!res.ok) throw new Error(`crt.sh returned ${res.status}`); const data: any[] = await res.json(); const now = Date.now(); // Deduplicate subdomains const subdomainSet = new Set<string>(); const certificates: CrtshCert[] = []; for (const entry of data) { const nameValue: string = entry.name_value ?? ""; const notAfter = entry.not_after ? new Date(entry.not_after).getTime() : Infinity; if (excludeExpired && notAfter < now) continue; // name_value can contain multiple domains separated by \n const names = nameValue.split("\n").map((n: string) => n.trim().toLowerCase()).filter(Boolean); for (const name of names) { if (!name.startsWith("*")) subdomainSet.add(name); else subdomainSet.add(name); // Keep wildcards too } certificates.push({ issuer: entry.issuer_name ?? "", commonName: entry.common_name ?? "", nameValue, notBefore: entry.not_before ?? "", notAfter: entry.not_after ?? "", id: entry.id ?? 0, }); } // Sort subdomains and limit certificates shown const uniqueSubdomains = [...subdomainSet].sort(); const result: CrtshResult = { domain, totalCerts: data.length, uniqueSubdomains, certificates: certificates.slice(0, 50), // Limit to avoid huge responses }; cache.set(cacheKey, result); return result; } finally { clearTimeout(timeout); } } - src/protocol/tools.ts:112-121 (registration)Registration of the crtsh_search tool including its schema definition and invocation of the handler.
const crtshSearchTool: ToolDef = { name: "crtsh_search", description: "Search Certificate Transparency logs via crt.sh. Returns unique subdomains and certificate details (issuer, validity, SANs).", schema: { domain: z.string().describe("Domain to search CT logs for"), exclude_expired: z.boolean().optional().describe("Exclude expired certificates (default: false)"), }, execute: async (args) => json(await crtshSearch(args.domain as string, args.exclude_expired as boolean | undefined)), };