lookup.disclose.io

How it works

Every vulnerability report stalls on the same two questions. lookup exists to answer them, in order, without guessing.

The premise

Two questions, in order

You found something. A misconfigured host, a leaking bucket, a vulnerable dependency, a bad browser extension. Now you want to tell someone — and you hit a wall that has nothing to do with security research:

Question 1

Whose thing is this?

An IP, a package, a container image, an FCC ID on the back of a router. None of them announce their owner. Ownership has to be resolved.

Question 2

Who do I contact about it?

Knowing the owner isn't enough. You need the channel they actually watch — and to know whether it's a published one or a guess.

These are not one question. They're two, and the second depends on the first. Almost every "I gave up on reporting it" story is a failure at one of these steps, not at finding the bug.

So lookup runs two-phase resolution. Phase one identifies the owner. Phase two finds that owner's reporting channels. Wherever possible the phases run in parallel, because your time is the scarce resource.

The organization is the hub. Every input type — a domain, a package, an app, a device — eventually resolves to an organization. That's the pivot. Once lookup knows who, it can unlock the most direct channels: bug bounty programs, PSIRT directories, the disclose.io directory, a published security.txt. The domain machinery is the mechanism; the org is the destination.
The people

Who is lookup for?

Anyone who has found something on an asset they don't own and needs to reach whoever does.

That started with security researchers, and they're still at the centre of it. But “whose thing is this, and who do I tell?” is the question the rest of the defensive world asks every day, usually by hand, usually at the worst moment. So lookup is built for:

Security researchers and bug hunters. You found the bug. Skip the afternoon spent hunting for a human who will read the report.

Incident responders and threat intel teams. The dump holds credentials for forty other companies. The attacker staged on someone else's server. Every one is a notification you now owe. Pipe the list in, get the contacts back.

SOC, MDR and abuse desks. A compromised host is brute-forcing you or hosting the phish. Get the owner and the provider's abuse route, ranked, without leaving the playbook.

CERTs, CSIRTs and coordinators. Mass notification lives or dies on turning IPs and ranges into organisations with real inboxes. You're in the graph too, as the backstop when nobody else has published a route.

Product security and AppSec teams. The bug is in a dependency, a partner's SDK, a container you didn't build. Follow it to the maintainer's actual security process, not the registry that hosts it. Run your SBOM through it before you need to.

CNAs and bug-bounty triage. The report landed in the wrong program. Send the researcher somewhere real.

Attack surface, third-party risk and compliance teams. Is this host ours, a subsidiary's, or a lookalike? Does this vendor publish a security.txt at all? Evidence-backed answers, confidence shown.

Anyone building automated or agentic tooling. There's no language model inside lookup, so it can't invent a contact. Call the API, CLI or MCP server and get the same deterministic answer every time.

And one more: your own security team. Look yourself up. If a stranger can't find you, neither can the person trying to warn you.

Free, open, and honest about what it doesn't know. Where the map is thin, tell us.

Question 1

Whose thing is this?

lookup accepts 16 input types and never asks you to tell it which one you're pasting. The pipeline:

  1. Classify the input. A domain, IPv4, IPv6, CIDR, ASN, URL, email, package, repository, container image, cloud resource, mobile app, hardware ID, browser extension, desktop app, or a bare organization name. Most are detected automatically; a few are disambiguated with an explicit prefix — npm:express, gh:org/repo, hw:Netgear RAX50, ext:uBlock Origin.
  2. Pick a strategy. Each input type is handled by a strategy — a named resolution plan that knows what's worth asking for that kind of thing. Asking WHOIS about an npm package is nonsense; asking a package registry about an IP address is too.
  3. Run its steps, in parallel. A strategy is an ordered set of steps. Each step queries exactly one source and returns what it found: an attribution, some contacts, and — critically — any new leads. Steps fire concurrently and degrade quietly; a source being down never fails the lookup.
  4. Follow the leads into other strategies. When a step surfaces a new asset — a package points at its repository, a repository names its organization, an organization resolves to a domain — that lead becomes a fresh input, handed to its own strategy. This is the part that makes the tool work.
The engine

Strategies and steps

A strategy declares which input types it handles and which steps to run. A step is a single source lookup with a confidence rating, and it returns three things: what it learned about the owner, any contacts it found, and any chain targets worth following.

StrategyHandlesRepresentative steps
Websitedomain, url, emailRFC 9116 security.txt at /.well-known/, then the root fallback; DNS security TXT at _security and apex; disclose.io directory, bug-bounty platforms, RDAP, TLS cert org, CAA/SPF, certificate transparency, web metadata, corporate structure
IP Addressipv4, ipv6, cidrFor an individual IP, live service identity and an associated operating company come first; RDAP holders and BGP/ASN operators are fallback context. Results show the likely user/service operator before registered holder, routing operator, and subscriber limitations. CIDR inputs retain network-operator semantics.
Packagenpm, PyPI, crates, Go, Maven, RubyGems, Composerregistry metadata — author, maintainers, repository, bugs URL
RepositoryGitHub, GitLab, BitbucketSECURITY.md, org .github fallback, private vulnerability reporting
Organizationcompany / product namebug-bounty platforms, FIRST.org PSIRT directory, corporate structure, VDP path probing
Containerimage referencesOCI manifest annotations, registry-operator contacts
Cloud Resourceprovider-hosted assetsprovider abuse channels (AWS, Azure, GCP, Firebase, Heroku)
Mobile Appapp:App Store metadata → the developer's canonical site
Hardwarehw:, FCC IDsFCC grantee code → manufacturer, then generic PSIRT-page discovery that only counts extracted security emails, reporting forms, or security.txt contacts
Extensionext:, store URLsstore listing → owning project or vendor
Desktop Appdesktop:vendor resolution → organization

These strategies try to establish the responsible entity, then use the strongest available path to its reporting channel. Observed routes retain their source. If no observed route exists, explicitly unverified convention addresses may appear as constructed leads rather than discoveries. Vetted reference snapshots supply routing context — for example, the official CVE CNA roster and origin-network ranges — while a browser extension still identifies its vendor and runs that vendor through the same security.txt / PSIRT / bug-bounty machinery used everywhere else.

The interesting part

Cross-strategy chaining

Chains, not dead ends. When a step finds a lead, the engine re-enters itself with that lead as a new input under a different strategy. Resolution walks the trail from the thing you have to the party who can fix it.

you type  npm:express
   
   ├─ Package strategy      → npm registry: repository = github.com/expressjs/express
   
   ├─ Repository strategy   → SECURITY.md, org profile, private vuln reporting
   
   ├─ Organization strategy → the owning org, its bounty program / PSIRT
   
   └─ Website strategy      → security.txt on the org's domain
                              
                        ranked contacts

Four sources, one question. You never asked about a repository or a domain — the engine worked out that it needed them.

The guardrails that keep it honest

Cycle detection. A visited set keyed on type:input means the engine never revisits the same asset, so a package that points at a repo that points back at the package can't loop.

Bounded depth. Chains stop at 3 levels. Depth is a budget, not an invitation — an unbounded crawl would drift away from the thing you actually asked about.

Deduplication. Contacts are keyed on type:value; when the same channel arrives from two sources, the higher-confidence one survives.

Hosting is not ownership. A store listing, a code host, a customer hostname under a shared SaaS namespace, or a load balancer's fingerprint identifies where something lives, never who owns it. Hosted tenant names keep their exact hostname and use tenant-safe policy checks instead of inheriting the provider apex's corporate identity. A Chrome extension whose homepage points at the Chrome Web Store does not become Google's problem. A package on GitHub is not Microsoft's.

Inference is the fallback, never the truth. Guessing a company's domain from its name is wrong more often than it looks (signal is signal.org, not signal.com). A curated corporate-structure registry is consulted first; lexical guessing is gated and only fires where it's earned.

Question 2

Who do I contact about it?

A lookup often surfaces several channels that are really different doors into the same building. Rather than dumping a flat list of peers, results are grouped by the party you'd actually be reporting to, and those groups are ordered by a published standard — so you know where to start, and why.

  1. Group by entity. Every channel is attributed to the party it reaches — the owner or maintainer, a hosting platform, a parent company, or a coordinator. This is derived from the resolution chain, not guessed.
  2. Start with applicability. The queried owner or its authorized reporting agent comes first, followed by responsible maintainers/operators, related parties, and inferred leads.
  3. Channel quality beats raw evidence certainty. A dedicated reporting path outranks a technically certain but generic contact; provenance breaks ties after route suitability.
  4. Coordinators are always available and always last. National/regional teams come before global CERT/CC, which can redirect when no local mapping exists.
  5. Asset type matters. For an IP or CIDR, the most-specific bootstrap RDAP assignment and its abuse role come before a different origin or transit operator. These are responsible network-operator routes, not proof of who owns the service at the address, so they remain partial. For an ordinary domain, an RDAP abuse contact is only a weaker network-operator fallback.
  6. Host platforms carry a scope note. GitHub's bug bounty covers GitHub's own products — not the third-party package it happens to host. Surfacing the note is what stops a package bug being misrouted to its host.

Owner-published channels are authoritative

One class of channel outranks everything else: a channel the queried asset published for itself. If the domain you looked up serves its own RFC 9116 security.txt or a dnssecuritytxt DNS TXT record, those contacts are marked authoritative and pinned ahead of every other contact — in the flat list and inside their group — regardless of channel priority. The owner telling you where to write is the strongest signal there is.

Authority is scoped to who declared a channel for which asset. Only the queried asset's own declaration qualifies: a security.txt reached by chaining out to a parent company, a hosting platform, or a subsidiary stays an ordinary contact. And a security.txt whose Expires: date has already passed is demoted out of authoritative status — the contact is still shown (an expired pointer is better than none), it simply no longer pins first.

That authority also resolves source conflicts. If a current first-party security.txt names a managed disclosure platform, a conflicting root-level platform link found only in a catalog is suppressed as stale. Every platform the owner explicitly names remains visible; a missing, expired, or custom-portal-only policy does not erase catalog evidence.

Absence is acknowledged too: when the engine probes for a security.txt and finds none, the response records found: false with the hosts it checked, and the results page says so explicitly — you can always tell "not found" apart from "not looked for".

Blocked requests, rate limits, HTTP errors, and connection problems produce an inconclusive check. Absence requires both paths to return content without a Contact field, or an explicit 404/410 response. A valid file on either path still resolves; an expired file remains visible, but loses its authoritative pin.

Answers lead with action

The result view is ordered for reporting: contacts first, then the attribution that explains who the asset belongs to, then the evidence and resolution chain. The explanation is still there when you need to audit the result, but it no longer sits between you and the reporting path.

How the order works

This is not one global ladder. lookup first asks which party is the right party for this asset, then orders that party's channels by purpose and evidence. An owner or authorized agent therefore stays ahead of a host, related party, inferred lead, or coordinator even when the latter has a technically certain record.

Within an equally applicable partyChannelWhat it means
1security.txt / DNS security TXTThe asset published the route for itself; current first-party declarations are authoritative
2Bug bounty / VDP / SECURITY.mdA dedicated, scope-matched disclosure route
3PSIRT / security-specific form or emailA product-security team or purpose-fit intake
4Generic web form / emailA discovered contact that may need internal forwarding
5Abuse contactA primary operator route for IP, ASN, CIDR, or cloud assets; a weaker forwarding route for an ordinary domain
6ConventionConstructed and unverified. When both exist, security@ comes before abuse@.
7CVE CNA routingAn official CVE coordinator for an exact organization or unresolved direct organization lookup; never an ownership claim
8CERTA national, regional, or global coordinator backstop; always last and able to redirect

Observed vs. constructed

A published security address and a constructed security@ address are not the same evidence. Published routes retain the source that actually supplied them and may be verified; convention addresses use type: convention, remain unverified, and appear only as leads. The order security@ before abuse@ applies only when those constructed guesses are otherwise equivalent.

A worked grouping

Looking up pypi:lnkfile can produce maintainer, parent-company, host-platform, and coordinator routes:

1. Package maintainer  [maintainer]   author email
2. Microsoft           [parent]       MSRC security.txt + bounty
3. GitHub              [host]         bug bounty + VDP + PSIRT
                                    scope: GitHub's own products
4. CERT/CC (VINCE)     [coordinator]  universal backstop — always last

Four doors, clearly labelled, in a defensible order — instead of four contacts in a heap.

The rules

What lookup will and won't tell you

Keep a path available for valid public assets. When no direct channel exists, a coordinator does — CERT/CC globally, and a national CERT for the asset's jurisdiction, across 44 countries. Invalid, private, and reserved inputs remain honest zero-contact results with a specific recovery explanation.

Construct without pretending to discover. If no observed route exists, lookup may offer security@ and then abuse@ as unverified convention leads. They never outrank an observed or owner-authorized route.

Show confidence. Every contact carries a confidence and a source, so you can decide where to start rather than trusting a ranking blindly.

Say when the answer is thin. The web result says Reporting route found, Fallback reporting route available, or No first-party reporting route found. API clients still receive the stable complete, partial, or failed status values. A CERT or CNA can still be a valid coordination route when the owner has not published one.

Be fast. Every check that can run in parallel does.

Why the honesty matters. A confidently wrong contact is worse than no contact. It routes your report into a void, or worse, to a third party who never asked to receive it. The partial label exists so a coverage gap looks like a coverage gap — and so we can find and close it.
Provenance

Where the answers come from

Every observed route traces to a live source or vetted official reference snapshot. Constructed convention addresses are the explicit exception: they are labelled unverified, ranked below observed routes, and never presented as discovered evidence.

Published security channelssecurity.txt (RFC 9116), DNS security TXT, the disclose.io directory, bug-bounty platform programs, the FIRST.org PSIRT directory.

Registration & network data — RDAP/WHOIS for domains and IPs, DNS records (SOA, PTR, SPF, CAA), ASN and abuse contacts.

Code & package ecosystems — npm, PyPI, crates.io, Go, Maven, RubyGems, Composer; SECURITY.md on GitHub, GitLab and Bitbucket.

Identity signals — TLS certificate organization fields, certificate transparency logs, structured web metadata, corporate parent/subsidiary structure.

CVE coordination — the official CVE CNA roster, used only for exact organization routing and clearly labelled as a coordinator rather than the asset owner.

Coordinators — CERT/CC as the universal backstop, plus national CERTs by jurisdiction.

Freshness checks — official CVE CNA and origin-network snapshots refresh weekly through a validation-gated pull request. They never deploy directly, so a malformed or unexpectedly shrunken upstream file cannot silently change production.

Surfaces

Four ways to ask

The same engine, the same answer, wherever you are:

The web app. Start with the exact affected asset: a domain, URL, package coordinate, repository, app ID, IP, or model number. If that does not resolve, try another identifier for the same target; use an organization name as a fallback.

The JSON API. POST /api/lookup. Free and anonymous; an optional key raises the rate limit. See the API docs and OpenAPI spec.

An MCP server. Connect lookup to Claude, Cursor, or any MCP-capable agent in one step. There's an llms.txt too.

Your existing tools. Official integrations put the same live answer inside recon pipelines, intercepting proxies, browsers, and scanners. They are thin clients: resolution and ranking stay on lookup.disclose.io, so an integration does not ship a stale copy of the resolver.

Official integrations

ToolWhere lookup fits
dio-lookup CLI / npmPipe newline-delimited assets from shell and recon workflows to JSONL results; install globally or run with bunx dio-lookup.
Caido pluginLook up the selected host from the context menu and keep disclosure routes in the sidebar.
Burp Suite extensionSend a host from Burp's right-click menu to the resolver through the Montoya extension.
OWASP ZAP add-onResolve a selected site or message host without leaving the open-source intercepting proxy.
Chrome extensionShow the disclosure posture and reporting information for the site in the current tab.
Nmap NSE scriptEnrich scanned hosts and addresses with responsible organizations and disclosure routes.
Nuclei templatesTurn scan targets into disclosure-contact results, or pipe Nuclei JSONL hosts through dio-lookup.
This page is maintained alongside the engine. Its source of truth is the project's resolution-strategies specification; when a strategy, step, or ordering rule changes, this page changes with it. Something here that doesn't match what you saw? That's a bug — tell us, or use the feedback control on any result.