Cloud estates already have the enforcement points: a managed resolver with domain-list rules, an egress proxy every subnet routes through, a service mesh that terminates outbound traffic, and a log pipeline that sees every DNS answer. This page is about where a list of 390,000+ DNS-verified phishing hosts plugs into that architecture, when to use a bulk domain list instead of a per-request API call, and what the arithmetic looks like once your workload count is in four figures.
Six lures dominate, and they share one property: the credential they take is a control-plane credential, not a mailbox.
A phished mailbox is a bad day. A phished cloud console session is a different category of event, because the credential does not merely read data — it changes the configuration that decides who can read data. An identity with sufficient rights can create another identity, attach a policy to it, disable the trail that would record the change, and leave behind an access path that survives the password reset issued in response to the original incident. That is why the same lure, aimed at a cloud administrator instead of a finance clerk, is worth so much more to the sender.
The six shapes below are the ones that show up repeatedly in confirmed phishing infrastructure aimed at cloud and SaaS operators. Note how few of them involve a fake email server: most of the work happens on a web host that has to resolve in DNS before anything else can occur, which is exactly the property a resolver-layer control exploits.
A rebuilt sign-in page for a major provider's management console, usually with the account alias pre-filled so the page looks personalised. The convincing ones proxy the real login in the background so the multi-factor prompt genuinely arrives on the victim's phone.
The identity provider is the highest-value single target in a modern estate, because one successful capture opens every downstream application at once. These pages copy the tenant's branding, which the attacker can usually pull straight from the real portal without authenticating.
No password is stolen at all. The victim is walked to a genuine consent screen for an attacker-registered application and approves scopes that grant durable API access. Because the grant is legitimate, rotating the password changes nothing until the grant itself is revoked.
Aimed at engineers rather than administrators: a fake pipeline notification, a build-failure page, a registry login prompt. The prize is a long-lived token stored in a variable somewhere, which authenticates without a human present and therefore without a second factor.
A share notification from a file service, indistinguishable from the dozens a person receives legitimately. The landing page asks for the account credentials before the supposed document opens, and the pretext survives scrutiny because sharing links genuinely do sometimes require a sign-in.
Not the provider's login page but the administrative console of a tool your organisation runs — a billing portal, a CRM back office, a support desk. Administrative accounts on second-tier SaaS are protected far less carefully than the cloud console and often reuse the same identity.
Every step after the first is expensive to detect. The first step is a DNS query, which is cheap to inspect and cheap to stop.
Trace the sequence and the intervention points become obvious. A message reaches an engineer — through mail, through a chat channel, through a code-hosting notification, occasionally through a search result for a documentation page. It contains a link. The engineer clicks, and before a single byte of the page is fetched, the operating system asks a resolver where that hostname lives. That query is the earliest moment in the entire chain at which anything in your infrastructure has an opportunity to act, and it happens on equipment you configure regardless of whether the click originated in a browser, a terminal or a CI runner.
If nothing intervenes, the page loads and the sequence accelerates. A proxying sign-in clone forwards the credentials to the real provider, collects the session cookie that comes back after the genuine multi-factor challenge, and hands the victim through to the real console so nothing looks wrong. From the identity provider's perspective the authentication succeeded and the second factor was satisfied, because both of those things are true; the only anomaly is a session established from an address the attacker controls. Detecting that requires behavioural analytics, impossible-travel rules and an analyst who is awake, which is a materially more expensive control than refusing to resolve a hostname.
What happens next depends on the identity's rights, and in most estates those rights are broader than the owner believes. An access key gets created and attached to an existing role. A trust policy gains an extra principal. A logging destination quietly loses its subscription filter. None of this requires exotic technique; it requires only that the console session be real, which it now is. By the time a detection rule fires on unusual API activity, the persistence has been established and the incident has become an eviction exercise rather than a containment one.
The OAuth variant skips the credential entirely and is worth understanding separately, because the usual response does nothing. The victim approves an application that requests read access to mail, files or repositories, and the resulting token is issued by your own identity provider to an application the user genuinely consented to. Resetting the password does not revoke it. Rotating the second factor does not revoke it. Only enumerating and revoking the grants does, and most organisations do not have a routine for that until the first time they need one. The consent screen itself is legitimate; the only illegitimate component in the whole flow is the hostname the victim was sent to first.
This is the argument for spending effort at the resolver rather than further down. Everything after the DNS query is a detection problem with a false-positive rate, a tuning cost and a staffing implication. The DNS query is a comparison against a list. It is not a complete defence and nothing here suggests otherwise, but of all the places to put a cheap control, the one immediately before the page loads is the one that removes the most subsequent work.
The right placement is almost always the one that requires no new agent. Cloud estates are already full of enforcement points that see hostnames, and adding a list to one of them is a configuration change rather than a deployment project. The four cards below turn that into a decision you can make from what your network already does, rather than from a product comparison.
Load the list as a domain-list rule on the account's managed resolver. Covers every workload in the VPC with no agent, no sidecar and no code change. This is the default answer for most estates.
If outbound traffic is already funnelled for inspection, the list becomes another blocklist on a device you operate. Gives you a request-level log line rather than only a DNS answer.
For services that fetch attacker-supplied URLs. The sidecar calls the check endpoint before the fetch, so the verdict is per-request and the credit cost is proportional to genuinely untrusted input.
Join resolver and proxy logs against the same file to flag historical hits. Detection rather than prevention, but it is how you find the workload that resolved a phishing host three days before you deployed the block.
Most teams end up using three of the four: resolver policy for prevention, SIEM enrichment for detection, and a small number of per-request calls where untrusted URLs enter the system.
Start by asking what your workloads actually route through. One domain-list rule there covers containers, functions, managed databases and virtual machines identically, because all of them resolve names the same way — including the workloads nobody put on an inventory.
Where compliance already routes outbound traffic through a device that inspects hostnames, adding the list is a blocklist change on equipment you operate. You get a request-level log line rather than only a DNS answer, which is worth more during an investigation.
Sidecars and in-process checks are the exception rather than the rule. They make sense for a webhook receiver, a link previewer or a document ingestion service that needs a verdict about a hostname it is about to fetch — a per-request question with a real answer.
Enrichment costs nothing extra once you hold the file, and it turns a wall of resolver logs into a short list of workloads that asked for something they should not have. Prevention and detection then run from one artefact rather than two.
A workload in a private subnet does not talk to the public DNS root. It asks the resolver the VPC gave it, and that resolver applies whatever rules the account owner attached before it forwards anything upstream. That indirection is the whole opportunity: one policy object, evaluated on every query, for every workload in the network, with no client-side cooperation required.
A managed database, a serverless function, a container in a task definition and a bastion host are wildly different runtimes, but they all resolve names through the same path. A rule attached there applies to all of them at once.
A blocked query can return a sinkhole address that serves an internal explanation page, or it can simply fail. Sinkholing is usually better in cloud estates, because a failed resolution surfaces to an engineer as a confusing timeout whereas a sinkhole page tells them what happened and who to ask.
Choose by whether the question is "block everything on this list" or "tell me about this one hostname right now".
The daily feed is a file: the complete database as CSV, published on the same twenty-four hour cycle as the rebuild, accompanied by a changelog of what was added and what was removed. In cloud terms this is the object you want when your control is declarative — a resolver firewall domain list, a proxy blocklist, a security-group-adjacent DNS policy, a lookup table in a log pipeline. You pull it on a schedule, transform it into whatever format the control expects, and update the rule. Because the matching then happens inside your own network, there is no per-query cost, no external dependency in the resolution path, and no outbound call that can time out at the wrong moment.
| Design question | Bulk domain list (daily CSV) | Per-request lookup (API) |
|---|---|---|
| Where the match happens | Inside your own network, against a file you hold | At the check endpoint, one call per hostname |
| Cost at query time | None, however busy the estate gets | one lookup per API call |
| Freshness | As fresh as your most recent import | The database exactly as it stands right now |
| Dependency in the path | None — enforcement survives an outbound outage | An outbound call that can time out |
| Natural home | Resolver domain lists, proxy blocklists, SIEM lookup tables | Sidecars, investigation consoles, nightly log sweeps |
| What the bill tracks | Nothing — one file per rebuild | Distinct hostnames you deliberately choose to check |
GET /api/v1/check?domain=<host>&apikey=<key> returns a verdict for one hostname in typically under fifty milliseconds and consumes one credit. POST /api/v1/batch takes up to a hundred domains per request, one lookup each, which suits a scheduled sweep over the distinct hostnames in yesterday's proxy logs. Point lookups belong where a workload has genuinely untrusted input in front of it; they do not belong in the general resolution path of a busy estate, where you would be paying a credit for every repeat query to the same handful of hostnames.
Enforce with the file, because that is free at query time and fails safe if the network to the outside world is down. Investigate with the API, because that is where you want a fresh answer about a specific hostname somebody has just handed you. Enrich with the file again inside the SIEM, because you already have it. One subscription and a modest credit balance covers all three roles without any of them competing for the same budget line.
# Synchronous check before a workload fetches an untrusted URL
curl "https://phishingdetectionapi.com/api/v1/check?domain=login-portal-example.com&apikey=$PDA_KEY"
# Sweep distinct hostnames from yesterday's egress logs, 100 per request
curl -X POST https://phishingdetectionapi.com/api/v1/batch \
-H "Content-Type: application/json" \
-d '{"apikey":"'"$PDA_KEY"'","domains":["host-one.example","host-two.example"]}'
# Confirm the database size and last update before a scheduled feed import
curl "https://phishingdetectionapi.com/api/v1/stats"
The key is passed as a query parameter or in the POST body, so it belongs in your secrets manager and it must be read server-side. Never bake it into a client bundle, a mobile app, a browser extension or anything a user can inspect. For a sidecar, mount it from the secret store at task start and let the platform rotate it; for a scheduled job, read it from the environment the scheduler injects.
Deliberately incremental, and reversible at every point, because a resolver rule is a production change.
Schedule the daily download into object storage in the account that owns your network. Keep the changelog next to it and retain a rolling window of previous builds.
Join the list against thirty days of resolver and proxy logs before enforcing anything. You get a real hit rate for your own estate and a list of workloads to look at.
Attach the domain list to one non-production VPC with the action set to log rather than block. Two weeks of observation confirms nothing legitimate is caught.
Move to a sinkhole or refuse action, then roll account by account. Keep an allow list object in place from day one so an exception is a one-line change, not an emergency.
Wire the daily pull into the same pipeline that manages the rule, and alarm on a stale build rather than on individual matches.
Per-request lookups are cheap individually and expensive in aggregate. The difference decides the architecture.
Take a mid-sized estate: a few hundred workloads across several accounts, resolving somewhere between one and three million DNS queries a day once you include health checks, service discovery and the chatter of managed services talking to their own control planes. If you routed every one of those through a per-request API call you would be buying tens of millions of credits a month, which is neither sensible nor necessary. Almost all of that volume is repeated queries for a small number of internal and provider-owned names.
Now count distinct external hostnames instead. In most estates that collapses to somewhere between twenty and eighty thousand a day, and if you cache a verdict for the life of a build — which is exactly as long as the answer is guaranteed fresh — you are looking at perhaps 600,000 to 2.4 million lookups a month. At the Enterprise Plus tier that is Enterprise at $999/month for 750,000 lookups, or per lookup. Workable, but you are paying real money for something the file gives you at no marginal cost, and you have introduced an outbound dependency into your resolution path.
The version that actually gets deployed looks different. Enforcement comes from the daily file loaded into a resolver domain list, so the query-time cost is zero and there is no external call. Credits are then reserved for the two jobs a file cannot do: synchronous checks in front of workloads that fetch untrusted URLs, and interactive lookups during an investigation. For most teams that is a few hundred to a few thousand lookups a day. Five hundred a day is roughly 15,000 a month — the Growth package at Growth at $99/month for 25,000 lookupscovers it with headroom, and because lookups reset monthly a quiet month simply carries forward instead of expiring.
Size the credit balance from the workloads that genuinely need a synchronous answer, not from your total query volume. Getting that distinction right is usually the difference between a four-figure monthly line item and a two-figure one, and it costs nothing but the ten minutes it takes to count distinct hostnames in a day of logs.
| Package | Price | Credits | Per lookup | Fits |
|---|---|---|---|---|
| Starter | $59 | 10,000 | $0.0040 | A single sidecar, low request volume |
| Growth | $99 | 25,000 | $0.0040 | Investigation lookups plus one workload |
| Professional | $249 | 100,000 | $0.0025 | Several link-handling services |
| Business | $499 | 250,000 | $0.0020 | Nightly log sweeps at estate scale |
| Enterprise | $999 | 750,000 | $0.0013 | Multi-account sweeps and enrichment |
The file makes blocking free at query time and removes any external dependency from the resolution path. Credits then cover only the lookups that genuinely have to be synchronous. One subscription plus a modest credit balance is the shape almost every cloud team converges on, and it is dramatically cheaper than routing production DNS through a metered service.
Worth stating plainly, because a control described accurately survives contact with an incident review.
This is a known-bad list, which means it is a floor rather than a perimeter. It contains hosts that have been observed serving phishing and confirmed to resolve; it makes no claim about hosts it has never seen. A domain registered and weaponised inside the same day may not appear in a build until after the campaign has run, and infrastructure that rotates faster than the rebuild cycle will always lead it. That is the trade-off the daily verification buys: the entries you get are current rather than historical, at the cost of not being exhaustive.
Consent-grant phishing survives a password reset. Enumerate and revoke application grants as a routine, not only after an incident.
Force workloads to use the managed resolver, or the domain-list rule can simply be routed around by anything that ships its own DNS configuration.
The same file enriches historical logs. See SIEM integration and DNS filtering for those patterns.
Application and identity work is covered on our SaaS platforms, API security and identity protection pages.
Seven questions that come up before anyone approves a change to production DNS.
Not if you use the file. Loading the list into a resolver domain list means the comparison happens inside the resolver as part of evaluating rules it already evaluates, so there is no additional network hop and nothing to time out. That is the main architectural reason to prefer the bulk model for enforcement.
Check the specific limits for your provider and list type before planning, because they differ and they change. A database of this size may need splitting across multiple list objects, importing from object storage rather than inline upload, or trimming to the categories relevant to your estate.
/stats style endpoint reports current database size and last update timestamp, so you can plan against the real number rather than an estimate, and you can alarm if a scheduled import would exceed a threshold you have set.Create the allow-list object on day one, before you enforce anything, and give the on-call engineer documented permission to add an entry to it. An exception that requires a code review and a deployment will not happen at three in the morning; an exception that is one entry in a list already attached to the rule will.
Yes, and that is the strongest argument for the resolver placement. Functions, containers, managed databases and instances all resolve names through the network's resolver, so a rule attached there applies uniformly without an agent in any of those runtimes. It also applies to workloads that predate your current tooling standards.
Download once into a shared security account, then share the resulting rule object to member accounts through whatever resource-sharing mechanism your provider offers. That keeps one authoritative copy and one refresh pipeline, which matters because a list that is refreshed in eleven accounts and forgotten in the twelfth is worse than one refreshed nowhere — it looks deployed.
If you operate a platform where customers submit URLs — webhooks, link previews, document ingestion, outbound notification — then yes, a synchronous check before you fetch or render is a sensible control, and it is the case where per-request credits are clearly the right model. Size the credit balance from your untrusted-input volume.
Log the query, the verdict, the timestamp and the source workload identity — instance, task or function — because that tuple is what makes a hit actionable. If the enforcement point is a proxy rather than a resolver, you also get the full request path, which is more useful for investigation and correspondingly more sensitive.
One domain-list rule on the managed resolver covers every container, function and instance in the network, refreshes on a daily schedule, and costs nothing at query time. Credits then cover only the lookups that genuinely have to happen in-line.