<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Azure Private Endpoint Attack Surface on Brewed in the Cloud by Chris Hailes</title><link>https://blog.brewedinthecloud.com/tags/azure-private-endpoint-attack-surface/</link><description>Recent content in Azure Private Endpoint Attack Surface on Brewed in the Cloud by Chris Hailes</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Thu, 04 Jun 2026 00:00:00 +1000</lastBuildDate><atom:link href="https://blog.brewedinthecloud.com/tags/azure-private-endpoint-attack-surface/rss.xml" rel="self" type="application/rss+xml"/><item><title>Why “Private” Does Not Mean “Secure”</title><link>https://blog.brewedinthecloud.com/p/pe-attacks-private-does-not-mean-secure/</link><pubDate>Thu, 04 Jun 2026 00:00:00 +1000</pubDate><guid>https://blog.brewedinthecloud.com/p/pe-attacks-private-does-not-mean-secure/</guid><description>&lt;p&gt;Private Endpoint has a branding problem.&lt;/p&gt;
&lt;p&gt;The word &lt;em&gt;private&lt;/em&gt; lands in architecture discussions like a shortcut for &lt;em&gt;safe&lt;/em&gt;. Public access is removed, the service gets a private IP, and somewhere between design review and production rollout, reduced exposure gets mistaken for established trust.&lt;/p&gt;
&lt;p&gt;That is the mistake.&lt;/p&gt;
&lt;p&gt;A private endpoint is useful. Often very useful. But if your security posture improves mainly because you made something harder to reach from the internet, you have changed exposure, not proven safety. You have narrowed the path, not validated the caller, the dependency chain, or the operational control around it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Private Endpoint reduces exposure; it does not create trust.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;That is the lens for this post.&lt;/p&gt;
&lt;h2 id="the-mental-model"&gt;The Mental Model
&lt;/h2&gt;&lt;p&gt;The failure usually starts with a quiet assumption:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If a resource is reachable only over private connectivity, it is now a trusted internal service.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That assumption sounds reasonable because private addressing still carries a lot of inherited meaning. It feels contained. Managed. Ours.&lt;/p&gt;
&lt;p&gt;In Azure, that is a dangerous shortcut.&lt;/p&gt;
&lt;p&gt;Private Endpoint changes &lt;strong&gt;where traffic can come from&lt;/strong&gt;. It does not answer whether the source is legitimate, whether the network path is well governed, whether DNS is correct, or whether the service is being reached by something already compromised.&lt;/p&gt;
&lt;p&gt;The deeper problem is not technical misunderstanding. It is classification.&lt;/p&gt;
&lt;p&gt;When teams treat Private Endpoint as a &lt;strong&gt;security control in its own right&lt;/strong&gt;, they start making downstream design decisions as though network privateness is evidence of trust. That is where architecture drifts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;internal paths become loosely trusted&lt;/li&gt;
&lt;li&gt;segmentation becomes harder to justify&lt;/li&gt;
&lt;li&gt;DNS gets treated as plumbing instead of a security dependency&lt;/li&gt;
&lt;li&gt;control-plane permissions become more powerful than the design admits&lt;/li&gt;
&lt;li&gt;monitoring gets weaker because “private” has already been mentally filed under “safe”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is why this is more than semantics. Misclassifying the control changes the system built around it.&lt;/p&gt;
&lt;h2 id="how-it-really-works"&gt;How It Really Works
&lt;/h2&gt;&lt;p&gt;Private Endpoint gives an Azure service a private IP in your virtual network through Azure Private Link. That changes the &lt;strong&gt;reachability path&lt;/strong&gt; to the service.&lt;/p&gt;
&lt;p&gt;It does not make the service inherently trustworthy.
It does not validate the caller.
It does not harden the data path on its own.
It does not replace authentication, authorisation, encryption, governance, or operational verification.&lt;/p&gt;
&lt;p&gt;What it does do is narrow the set of places from which the service can be reached.&lt;/p&gt;
&lt;p&gt;That matters. Exposure reduction is real. Internet-wide scanning, casual probing, and broad unsolicited connectivity become less relevant when access is forced through private network paths. That is a legitimate security improvement.&lt;/p&gt;
&lt;p&gt;But it is still only one kind of improvement.&lt;/p&gt;
&lt;p&gt;The mistake is turning this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Fewer things can reach the service&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;into this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Things that can reach the service are now trustworthy&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Those are completely different claims.&lt;/p&gt;
&lt;p&gt;A more accurate model is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Private Endpoint is an exposure-reduction mechanism&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It is not a trust mechanism&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It is not a security boundary&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;It should not be treated as a compensating control for weak architecture elsewhere&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That last point matters most. The architectural mistake is not deploying Private Endpoint. The mistake is using it to justify trust decisions it was never designed to support.&lt;/p&gt;
&lt;h2 id="private-endpoint-as-part-of-the-attack-surface"&gt;Private Endpoint as Part of the Attack Surface
&lt;/h2&gt;&lt;p&gt;If you are threat modelling properly, a Private Endpoint should be treated as part of the &lt;strong&gt;internal attack surface&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;That means the question is not “is this service private now?”&lt;/p&gt;
&lt;p&gt;It is closer to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;which networks can route to it?&lt;/li&gt;
&lt;li&gt;which systems can resolve its name?&lt;/li&gt;
&lt;li&gt;which workloads can reach it after compromise?&lt;/li&gt;
&lt;li&gt;which teams or automation can create, approve, or modify the connection path?&lt;/li&gt;
&lt;li&gt;which changes to DNS or endpoint lifecycle would silently alter trust assumptions?&lt;/li&gt;
&lt;li&gt;which telemetry would tell us the endpoint is being used in a way we did not intend?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is a very different posture from “public access disabled, job done”.&lt;/p&gt;
&lt;h3 id="the-dependency-chain-is-the-story"&gt;The dependency chain is the story
&lt;/h3&gt;&lt;div class="mermaid"&gt;flowchart LR
A[Workload or User] --&gt; B[DNS Resolution]
B --&gt; C[Routing to Private IP]
C --&gt; D[Private Endpoint]
D --&gt; E[Private Link Mapping]
E --&gt; F[Azure Service]
G[Peering / Hybrid Connectivity] --&gt; C
H[RBAC / Policy / Approval Workflow] --&gt; D
I[Private DNS Zone Links / Forwarders] --&gt; B
J[Monitoring / Logs / Alerts] --&gt; D
style D fill:#d9edf7,stroke:#31708f,stroke-width:2px
style B fill:#fcf8e3,stroke:#8a6d3b,stroke-width:1px
style H fill:#f2dede,stroke:#a94442,stroke-width:1px
style I fill:#f2dede,stroke:#a94442,stroke-width:1px
&lt;/div&gt;
&lt;p&gt;Private Endpoint is only one component in a chain that includes name resolution, network pathing, control-plane permissions, and ongoing operational ownership.&lt;/p&gt;
&lt;p&gt;An attacker does not need to defeat Private Link itself. They need one viable path through the surrounding system.&lt;/p&gt;
&lt;p&gt;That is why calling Private Endpoint a security control is too generous. It encourages the wrong mental model about where assurance actually comes from.&lt;/p&gt;
&lt;h2 id="real-world-impact"&gt;Real-World Impact
&lt;/h2&gt;&lt;p&gt;This changes design and operations in some concrete ways.&lt;/p&gt;
&lt;h2 id="1-a-compromised-internal-workload-can-still-use-the-private-path"&gt;1. A compromised internal workload can still use the private path
&lt;/h2&gt;&lt;p&gt;A storage account or Key Vault behind a Private Endpoint is still reachable by any compromised workload that can route and resolve to it.&lt;/p&gt;
&lt;p&gt;If you mentally classified the endpoint as “secure because private”, you are more likely to have under-invested in segmentation, workload isolation, or internal traffic scrutiny. The attacker does not need public ingress. They just need to land somewhere that already sits inside the allowed path.&lt;/p&gt;
&lt;p&gt;This is the most common failure of the “private equals safe” assumption: the service is no longer internet-facing, but it is still entirely usable from the wrong place for the wrong reason.&lt;/p&gt;
&lt;p&gt;That should change how you design. A Private Endpoint should be treated as a &lt;strong&gt;sensitive internal destination&lt;/strong&gt;, not a trustworthy one.&lt;/p&gt;
&lt;h2 id="2-dns-becomes-a-security-dependency-not-just-a-networking-detail"&gt;2. DNS becomes a security dependency, not just a networking detail
&lt;/h2&gt;&lt;p&gt;Private Endpoint increases your reliance on private DNS zones, forwarding rules, resolver paths, and link governance.&lt;/p&gt;
&lt;p&gt;That is not background plumbing. It is part of the trust path.&lt;/p&gt;
&lt;p&gt;If DNS ownership is fragmented, forwarding is inconsistent, or zone links are changed without proper control, the architecture can drift without most teams noticing. The service still looks private. The assumptions around how it is resolved and reached may no longer be true.&lt;/p&gt;
&lt;p&gt;This should change how you operate. Name resolution for private services needs explicit ownership, change discipline, and verification. If your design depends on DNS but your operating model treats it as somebody else’s problem, you do not have a complete security design.&lt;/p&gt;
&lt;h2 id="3-control-plane-permissions-can-silently-reshape-trust"&gt;3. Control-plane permissions can silently reshape trust
&lt;/h2&gt;&lt;p&gt;The endpoint itself is a data-plane object, but the trust around it is heavily influenced by control-plane actions.&lt;/p&gt;
&lt;p&gt;Who can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create a private endpoint&lt;/li&gt;
&lt;li&gt;approve a connection&lt;/li&gt;
&lt;li&gt;link or unlink private DNS zones&lt;/li&gt;
&lt;li&gt;alter policy exemptions&lt;/li&gt;
&lt;li&gt;move workloads into reachable network segments&lt;/li&gt;
&lt;li&gt;change routing or forwarding behaviour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those permissions matter because they can alter who reaches what, and how, without changing the application code or the service itself.&lt;/p&gt;
&lt;p&gt;If Private Endpoint is treated as a security control, teams often stop short of asking who can mutate the control surface around it. That creates false assurance. The path is private, but the governance over the path may still be loose.&lt;/p&gt;
&lt;p&gt;This should change what you review in design governance. The security question is not just “does this use Private Endpoint?” but “who can change the path, resolution, and approval model around it?”&lt;/p&gt;
&lt;h2 id="how-would-this-change-something-i-design-deploy-or-operate"&gt;How would this change something I design, deploy, or operate?
&lt;/h2&gt;&lt;p&gt;It changes the classification.&lt;/p&gt;
&lt;p&gt;I would not treat Private Endpoint as a control that establishes trust. I would treat it as an &lt;strong&gt;exposure-reduction mechanism&lt;/strong&gt; that still sits inside a broader system of trust decisions.&lt;/p&gt;
&lt;p&gt;That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;designing internal reachability as something to constrain, not automatically trust&lt;/li&gt;
&lt;li&gt;treating private DNS as part of the security architecture&lt;/li&gt;
&lt;li&gt;reviewing control-plane permissions as part of endpoint risk&lt;/li&gt;
&lt;li&gt;monitoring private-only service access as potentially high-signal, not low-risk&lt;/li&gt;
&lt;li&gt;refusing to let “it’s private” close a design discussion that should still include governance and failure modes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the design review ends at “public access disabled”, it has ended too early.&lt;/p&gt;
&lt;h2 id="implementation-example-verify-the-dependency-surface-not-just-the-endpoint"&gt;Implementation Example: Verify the Dependency Surface, Not Just the Endpoint
&lt;/h2&gt;&lt;p&gt;The useful operational question is rarely “does a Private Endpoint exist?”&lt;/p&gt;
&lt;p&gt;It is more often “what trust and dependency surface now exists because it does?”&lt;/p&gt;
&lt;p&gt;A simple example is enumerating endpoint state and DNS relationships so they can be reviewed as part of operational governance rather than assumed to be correct.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List private endpoints in a subscription with key governance context&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;az network private-endpoint list &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --query &lt;span class="s2"&gt;&amp;#34;[].{
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; name:name,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; resourceGroup:resourceGroup,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; location:location,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; subnet:id,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; connections:privateLinkServiceConnections[].privateLinkServiceId,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; nics:networkInterfaces[].id,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; provisioningState:provisioningState
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt; }&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -o table
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# List Private DNS zone links for review&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;az network private-dns link vnet list &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --resource-group &amp;lt;dns-rg&amp;gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; --zone-name &amp;lt;private-zone-name&amp;gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="se"&gt;&lt;/span&gt; -o table
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is not presented as a deployment step. It is a reminder that the operational surface includes more than the endpoint object itself. If you cannot quickly identify which endpoints exist, which networks they live in, and how DNS is linked around them, you are relying on privateness more than you are governing it.&lt;/p&gt;
&lt;h2 id="gotchas--edge-cases"&gt;Gotchas &amp;amp; Edge Cases
&lt;/h2&gt;&lt;h3 id="private-only-can-reduce-visibility-if-teams-are-not-deliberate"&gt;Private-only can reduce visibility if teams are not deliberate
&lt;/h3&gt;&lt;p&gt;Some organisations monitor internet-facing services heavily and assume private paths are lower risk. That can create a blind spot where the more sensitive destination gets less scrutiny simply because it is no longer public.&lt;/p&gt;
&lt;h3 id="internal-often-spans-more-than-one-trust-domain"&gt;“Internal” often spans more than one trust domain
&lt;/h3&gt;&lt;p&gt;Peering, hub-and-spoke topologies, hybrid connectivity, and shared platform services can all widen effective reachability. If your architecture talks about “the internal network” as though it were one trust zone, you are already abstracting away the problem.&lt;/p&gt;
&lt;h3 id="exposure-reduction-can-still-be-the-right-call"&gt;Exposure reduction can still be the right call
&lt;/h3&gt;&lt;p&gt;None of this is an argument against Private Endpoint. Reducing public exposure is often sensible and worthwhile. The warning is about over-claiming what that decision buys you.&lt;/p&gt;
&lt;h2 id="best-practices"&gt;Best Practices
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Treat Private Endpoint as &lt;strong&gt;exposure reduction&lt;/strong&gt;, not trust establishment&lt;/li&gt;
&lt;li&gt;Model private DNS as a security dependency with explicit ownership&lt;/li&gt;
&lt;li&gt;Review which internal networks and workloads can actually reach private endpoints&lt;/li&gt;
&lt;li&gt;Include control-plane permissions and approval paths in the threat model&lt;/li&gt;
&lt;li&gt;Monitor access to private-only services as part of your internal attack surface&lt;/li&gt;
&lt;li&gt;Challenge any design language that treats “private” as equivalent to “trusted”&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="insight"&gt;
&lt;div class="insight-icon"&gt;🍺&lt;/div&gt;
&lt;div class="insight-content"&gt;
&lt;strong&gt;Brewed Insight:&lt;/strong&gt; Private Endpoint is valuable precisely because it reduces exposure. The trouble starts when that benefit gets inflated into a trust claim. Once “private” becomes shorthand for “safe”, the rest of the architecture starts inheriting confidence it never earned.
&lt;/div&gt;
&lt;/div&gt;
&lt;style&gt;
.insight {
display: flex;
align-items: center;
background-color: #0089e41c;
border-left: 10px solid #D69A2D;
padding: 10px;
margin: 20px 0;
border-radius: 4px;
}
.insight-icon {
font-size: 24px;
margin-right: 10px;
}
.insight-content {
flex: 1;
}
&lt;/style&gt;&lt;h2 id="learn-more"&gt;Learn More
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/private-link/private-endpoint-overview" target="_blank" rel="noopener"
&gt;What is Azure Private Endpoint?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/private-link/private-link-overview" target="_blank" rel="noopener"
&gt;What is Azure Private Link?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/dns/private-dns-overview" target="_blank" rel="noopener"
&gt;Azure Private DNS documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/azure/architecture/reference-architectures/hybrid-networking/hub-spoke" target="_blank" rel="noopener"
&gt;Azure architecture guidance for hub-spoke network topology&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>