<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: NTCTech</title>
    <description>The latest articles on DEV Community by NTCTech (@ntctech).</description>
    <link>https://dev.to/ntctech</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3784059%2Fc609d531-fdab-47ac-bb17-37fd1ecc3d71.jpg</url>
      <title>DEV Community: NTCTech</title>
      <link>https://dev.to/ntctech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ntctech"/>
    <language>en</language>
    <item>
      <title>Temporal Guardrails Move the Control Into the Event Log</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Wed, 14 Oct 2026 12:15:32 +0000</pubDate>
      <link>https://dev.to/ntctech/temporal-guardrails-move-the-control-into-the-event-log-3nb9</link>
      <guid>https://dev.to/ntctech/temporal-guardrails-move-the-control-into-the-event-log-3nb9</guid>
      <description>&lt;p&gt;Temporal guardrails change what an agent policy decides: not only whether this request is allowed, but whether it is allowed given everything the agent has already done. AWS's open-source &lt;a href="https://aws.amazon.com/blogs/opensource/introducing-the-dogwood-local-engine-temporal-governance-for-agent-actions/" rel="noopener noreferrer"&gt;Dogwood Local Engine&lt;/a&gt; documents its event handling and recovery model in enough operational detail to reason about the idea concretely. The language it enforces was introduced in the earlier &lt;a href="https://aws.amazon.com/blogs/opensource/introducing-dogwood-runtime-verification-for-ai-agents/" rel="noopener noreferrer"&gt;Dogwood runtime verification post&lt;/a&gt;. The part of temporal guardrails worth an architect's attention is the boundary around it, because a stateful verdict is only as trustworthy as the history it was computed from.&lt;/p&gt;

&lt;p&gt;This post is scoped to the open-source Local Engine and the language as AWS described it. It makes no claim about the managed AgentCore Policy integration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftetxhjdejkynvjrduzwb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftetxhjdejkynvjrduzwb.jpg" alt="temporal guardrails event stream feeding a policy engine with a gap marker at a clause update" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Stateless Policy Decides on the Request. Temporal Guardrails Decide on the History.
&lt;/h2&gt;

&lt;p&gt;Dogwood extends Cedar, and its temporal guardrails are built on that base. Any valid Cedar policy is a valid Dogwood policy, evaluation is deny-by-default, and a forbid overrides a permit. What Dogwood adds is a &lt;code&gt;when temporal { ... }&lt;/code&gt; clause with operators such as &lt;code&gt;formerly&lt;/code&gt;, &lt;code&gt;count_within&lt;/code&gt;, &lt;code&gt;count_distinct_within&lt;/code&gt;, &lt;code&gt;sum_within&lt;/code&gt; and &lt;code&gt;bind&lt;/code&gt;. With those, a policy can express prerequisites and ordering, rate limits, distinct-value limits and running totals.&lt;/p&gt;

&lt;p&gt;That changes the shape of the decision. A stateless policy is a function of the request and the policy text. A temporal clause makes the verdict a function of the request, the policy text, and an event history the engine accumulated before the request arrived. In &lt;a href="https://www.rack2cloud.com/ai-infrastructure-strategy-guide/" rel="noopener noreferrer"&gt;AI infrastructure architecture&lt;/a&gt; terms, the policy decision point stops being a pure function over a rule set. Once a rule can say "no more than five transfers in an hour" or "only after an approval event," the decision point also becomes a place where state lives, and state has an author, a lifecycle and a failure mode.&lt;/p&gt;

&lt;p&gt;The control pattern is not new in kind. A token-budget limit at a gateway, as in the authority model in &lt;a href="https://www.rack2cloud.com/nutanix-mcp-gateway-authority/" rel="noopener noreferrer"&gt;Nutanix Put MCP Behind a Gateway&lt;/a&gt;, already refuses a call because of what already happened. What temporal clauses do is make that "because of what already happened" expressible in the policy language itself rather than in gateway-specific counters.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvhogms0kazspjscz8ir.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvhogms0kazspjscz8ir.jpg" alt="Stateless versus temporal verdict" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Where the History Comes From
&lt;/h2&gt;

&lt;p&gt;The Local Engine is a library embedded in a harness. The harness intercepts each tool call, submits a request event to the engine, runs the tool only if the verdict is allow, and then submits a response event. The engine issues verdicts only for request events; response events record outcomes. On arrival, the engine linearizes events under a lock, timestamps them, and appends them to a durable log that is synced to disk before evaluation. It keeps in-memory summaries per temporal clause, takes periodic snapshots, and rebuilds state by loading a snapshot and replaying later events. Policy updates are logged in the same sequence as events, and recovery yields either the complete pre-update or the complete post-update policy set.&lt;/p&gt;

&lt;p&gt;AWS is explicit about who is responsible for what. The harness must provide event integrity. The event interface must be reachable only from the harness, and harness and engine state must not be manipulable by other processes or by the effects of tool calls. The library does not perform operating-system isolation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;th&gt;Where the post places it&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ordering and timestamping&lt;/td&gt;
&lt;td&gt;Engine (documented)&lt;/td&gt;
&lt;td&gt;Events linearized under a lock and timestamped on arrival&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence and recovery&lt;/td&gt;
&lt;td&gt;Engine (documented)&lt;/td&gt;
&lt;td&gt;Durable log synced before evaluation; snapshot plus replay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Evaluation&lt;/td&gt;
&lt;td&gt;Engine (documented)&lt;/td&gt;
&lt;td&gt;Verdicts for request events only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event accuracy and submitter identity&lt;/td&gt;
&lt;td&gt;Harness (documented)&lt;/td&gt;
&lt;td&gt;Event interface reachable only from the harness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Isolation of harness and engine state&lt;/td&gt;
&lt;td&gt;Harness (documented)&lt;/td&gt;
&lt;td&gt;Not performed by the library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Denied action does not run&lt;/td&gt;
&lt;td&gt;Harness (documented)&lt;/td&gt;
&lt;td&gt;Tool executes only on an allow verdict&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Authentication and key management&lt;/td&gt;
&lt;td&gt;Not stated&lt;/td&gt;
&lt;td&gt;The post does not describe it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavior on engine or log failure&lt;/td&gt;
&lt;td&gt;Not stated&lt;/td&gt;
&lt;td&gt;Fail-open versus fail-closed is not described&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Read that table the way you would read a shared-responsibility matrix. The two "not stated" rows are not criticisms; they are the questions your integration has to answer for itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architectural guidance (not AWS's):&lt;/strong&gt; treat the harness-to-engine event feed as an authenticated channel with one trusted submission path, because the engine will believe whatever it is told. A literal single-writer implementation is one way to get there; AWS's stated requirement is narrower, that the event interface be reachable only from the harness. An agent that can influence what the harness reports, or write to the same state through a tool side effect, is not being governed by the guardrail; it is authoring it. This is the same identity-isolation concern we raised in &lt;a href="https://www.rack2cloud.com/agentic-ai-control-plane-problem/" rel="noopener noreferrer"&gt;the agentic control plane problem&lt;/a&gt; and in the &lt;a href="https://www.rack2cloud.com/mcp-security-architecture/" rel="noopener noreferrer"&gt;MCP security architecture&lt;/a&gt; analysis of the Agentic Authority Boundary: the component enforcing the rule must not share a trust domain with the thing the rule constrains. The runtime-control stage of the &lt;a href="https://www.rack2cloud.com/ai-architecture-learning-path/governance-runtime-control/" rel="noopener noreferrer"&gt;Governance &amp;amp; Runtime Control learning path&lt;/a&gt; frames where that boundary sits.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Blind Window
&lt;/h2&gt;

&lt;p&gt;Here is the mechanism that defines the whole problem with temporal guardrails. AWS documents that a new or modified temporal clause counts only events that arrive after the update. Its history starts at the update, not at the beginning of the log.&lt;/p&gt;

&lt;p&gt;That is a reasonable design, and for temporal guardrails it is also a boundary you have to reason about. Whenever a clause is added or changed, there is a period in which it is evaluating a truncated view of the past. The agent's earlier behavior exists in the log, but the clause cannot see it.&lt;/p&gt;

&lt;p&gt;The two inferences below are mine, drawn from the documented behavior. AWS does not state them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ILLUSTRATION — CONSTRUCTED FOR THIS POST, NOT AN AWS EXAMPLE:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Permissive error&lt;/strong&gt; — An agent submits 40 transfers between 13:00 and 14:00. At 14:00 an operator adds a clause: forbid a transfer when five have already occurred in the trailing hour. Because the clause's history begins at 14:00, it counts none of those 40 at 14:01. Depending on whether the current request counts toward its own verdict, which the post does not state, it permits roughly the next five. A rule written to cap the burst is blind to the burst that motivated it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restrictive error&lt;/strong&gt; — At 09:00 an approval event is logged. At 14:00 an operator adds a clause: forbid release unless an approval occurred in the last 24 hours. The clause never saw the 09:00 approval, so it denies every release until a fresh approval arrives.
&lt;strong&gt;Inference one:&lt;/strong&gt; for a rolling window, the blind window is bounded by the clause's own window length, assuming the documented window semantics and the events' timestamps behave as described. Pre-update events stay outside the new clause's history until they would have aged out of the applicable window anyway. A one-hour clause stops being incomplete about an hour after the update; a 24-hour clause about a day after. Longer windows are not only costlier to evaluate, they stay unrepresentative for longer. This is a statement about when the clause matches the intended policy, not a guarantee about any specific verdict.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Inference two:&lt;/strong&gt; the direction of the error depends on how the rule is written. A "forbid when the count is reached" rule errs permissive during the window. A "forbid unless a prior event is present" rule errs restrictive. Neither error direction can be assumed acceptable without an explicit transition procedure, and the same update process produces both.&lt;/p&gt;

&lt;p&gt;This is where the evidence question sits. In &lt;a href="https://www.rack2cloud.com/ai-evidence-observability/" rel="noopener noreferrer"&gt;AI Systems Need Evidence, Not Just Observability&lt;/a&gt;, component 02 of the AI Evidence Artifact Layer is the policy state snapshot: the constraint that was active when execution occurred, immutable and verifiable without access to the current policy configuration. The claim here is narrow. A snapshot of the policy text alone is not sufficient to reconstruct a temporal verdict. To explain why a particular request was allowed or denied, you also need the clause's start point and the event history inside its window. Nothing prevents a snapshot from carrying those. A snapshot combined with the event log and the clause-start boundary provides the essential inputs for reconstructing the decision, provided the exact policy version, the event ordering and timestamps, and the evaluation context are also preserved. But a record that stores only "policy version 14 was active" will not tell an auditor why the same request was allowed at 14:01 and denied at 15:01.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnol04hi623tsuaqmjmye.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnol04hi623tsuaqmjmye.jpg" alt="Blind window after a clause update" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Windows Change Meaning When You Shorten Them
&lt;/h2&gt;

&lt;p&gt;The August post is direct that evaluation of temporal guardrails is stateful and that cost can depend on event-log length. The Local Engine post puts a number on it, with a context that matters: each benchmark point is the median of 200 evaluations on one server-class host, using simulated sessions generating 360 events per hour. At a twelve-hour session length, the 24-hour window took about six milliseconds per decision, while the 15-minute window stayed flat. Those figures describe that one host under those conditions. They are not a production-latency commitment, and they say nothing about your harness, your event volume, your storage or your concurrency.&lt;/p&gt;

&lt;p&gt;The same post notes that shortening a window is safe only if the shorter window still meets the requirement. That sentence deserves more weight than it gets. Shrinking a 24-hour clause to 15 minutes to recover latency on that single host is a change in what the control means, not a tuning step. A cumulative-spend ceiling over a day and a burst limit over a quarter hour are different controls that happen to share an operator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architectural guidance (not AWS's):&lt;/strong&gt; record each window together with the risk it was sized against. "Twenty-four hours because the daily settlement cycle is the exposure" survives a performance review. "Twenty-four hours" does not, and it will be the first number someone proposes to cut when the latency graph looks bad. The blind window compounds this when the change modifies the clause: a window-length edit is a clause modification, so it resets that clause's history boundary as described above.&lt;/p&gt;




&lt;h2&gt;
  
  
  What to Test in Your Own Temporal Guardrails Integration
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"When a temporal clause changes, which events does it count, who wrote them, and what would you read to prove it?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;These four checks for temporal guardrails are architectural guidance. They are not an AWS procedure, and they do not assume Dogwood supports any particular remediation such as back-filling history into a new clause. If it does not, the mitigation is operational: schedule clause changes, and compensate during the window. Run them in a controlled test harness, not against a production log device, and capture evidence for each: the attempted action, the observed result, and the event-log state afterward.&lt;/p&gt;

&lt;h3&gt;
  
  
  01 — FEED INTEGRITY
&lt;/h3&gt;

&lt;p&gt;Attempt to submit a forged event, and to alter engine or log state, from inside a tool call. The test passes only if the harness is the sole path in, tool side effects cannot reach the state, and the log is verifiably unchanged afterward. A forged event that merely fails to execute does not prove the log stayed intact.&lt;/p&gt;

&lt;h3&gt;
  
  
  02 — CLAUSE START POINT
&lt;/h3&gt;

&lt;p&gt;Add and modify a clause against a log with known prior events. Confirm the clause ignores them, then confirm your change procedure records the start boundary and the compensating control used during the window.&lt;/p&gt;

&lt;h3&gt;
  
  
  03 — WINDOW SIZING
&lt;/h3&gt;

&lt;p&gt;For every clause, write down the exposure the window length answers. Measure latency on your own harness and storage rather than importing the single-host benchmark figures.&lt;/p&gt;

&lt;h3&gt;
  
  
  04 — FAILURE MATRIX
&lt;/h3&gt;

&lt;p&gt;The post does not state fail-open or fail-closed behavior, and the states differ. Exercise each in a test harness: engine unavailable before a verdict; log persistence failure before evaluation completes; failure after a durable append but before a verdict returns; failure after an allow but during tool execution. Define the expected response per state before an incident does.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy9puv7j5qlsejg51ehvq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy9puv7j5qlsejg51ehvq.jpg" alt="Four integration checks for temporal guardrails" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Where This Stops
&lt;/h2&gt;

&lt;p&gt;This analysis covers the open-source Local Engine and the language as the August post describes it. It does not extend to the AgentCore Policy integration, whose deployment topology the sources do not state, so nothing here should be read as a finding about the managed service.&lt;/p&gt;

&lt;p&gt;It is also not a claim that Dogwood is unsafe. The blind window follows from a documented, defensible design choice, and the harness responsibilities are documented rather than hidden. Two limits from AWS's own description matter for how much weight your tests carry: temporal conditions do not currently support Cedar's automated reasoning tools, so you cannot lean on that analysis for them, and liveness properties and absolute wall-clock windows are listed as future work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;Temporal guardrails are a genuine improvement in what an agent policy can express. Rate limits, prerequisites and running totals belong in the policy layer, not in ad hoc gateway counters.&lt;/p&gt;

&lt;p&gt;Once temporal guardrails put the control in the log, three questions replace the old one. Who is allowed to write to it, which part of the past can a given clause actually see, and what proves the answer after the fact. AWS answers the first by assigning event integrity to the harness, and answers the second implicitly by starting each clause's history at its update. The third is left to you.&lt;/p&gt;

&lt;p&gt;In operation, that makes a clause change a controlled transition: a named start boundary, a compensating control for the window, and a record an auditor can use. Window length belongs to the control, not to performance tuning.&lt;/p&gt;

&lt;p&gt;A guardrail that remembers is only as sound as what it was allowed to remember, and from when.&lt;/p&gt;




&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/ai-infrastructure-strategy-guide/" rel="noopener noreferrer"&gt;AI Infrastructure Architecture&lt;/a&gt; — the pillar hub for AI infrastructure design decisions, including where runtime governance sits relative to compute, data and orchestration.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/ai-architecture-learning-path/governance-runtime-control/" rel="noopener noreferrer"&gt;Governance &amp;amp; Runtime Control&lt;/a&gt; — the learning-path stage covering enforcement points, authority boundaries and runtime control for agentic systems.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/mcp-security-architecture/" rel="noopener noreferrer"&gt;MCP, Tool Use, and the New Attack Surface Nobody Is Mapping&lt;/a&gt; — the Agentic Authority Boundary and the identity-isolation controls that govern what a harness must keep separate from tool context.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/agentic-ai-control-plane-problem/" rel="noopener noreferrer"&gt;Agentic AI Has a Control Plane Problem — Because It Became the Control Plane&lt;/a&gt; — why the component enforcing policy cannot share a trust domain with the agent it constrains.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/ai-evidence-observability/" rel="noopener noreferrer"&gt;AI Systems Need Evidence, Not Just Observability&lt;/a&gt; — the AI Evidence Artifact Layer and why a policy-state record has to be verifiable independently of current configuration.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/nutanix-mcp-gateway-authority/" rel="noopener noreferrer"&gt;Nutanix Put MCP Behind a Gateway. The Real Problem Is Authority.&lt;/a&gt; — a gateway-level control that refuses calls based on prior consumption, the counter-based precursor to temporal clauses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/blogs/opensource/introducing-the-dogwood-local-engine-temporal-governance-for-agent-actions/" rel="noopener noreferrer"&gt;Introducing the Dogwood Local Engine: Temporal Governance for Agent Actions&lt;/a&gt; — AWS Open Source Blog; the primary source for the harness model, event log, recovery and benchmark described here.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/blogs/opensource/introducing-dogwood-runtime-verification-for-ai-agents/" rel="noopener noreferrer"&gt;Introducing Dogwood: Runtime Verification for AI Agents&lt;/a&gt; — AWS Open Source Blog; the language description, operators and stated limits.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/temporal-guardrails-agent-event-history/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>infrastructure</category>
      <category>cloud</category>
    </item>
    <item>
      <title>GPU Passthrough Works. Can You Still Move the VM?</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Tue, 13 Oct 2026 12:15:01 +0000</pubDate>
      <link>https://dev.to/ntctech/gpu-passthrough-works-can-you-still-move-the-vm-51bb</link>
      <guid>https://dev.to/ntctech/gpu-passthrough-works-can-you-still-move-the-vm-51bb</guid>
      <description>&lt;p&gt;GPU passthrough gives a VM direct access to a physical accelerator, constraining which lifecycle operations the hypervisor can perform. Which operations remain available depends on the destination platform, its implementation of that access mode, and the documented conditions for the release. A VMware exit plan that validates a GPU workload by booting it on the destination and comparing throughput to the source has tested the device. It has not tested the VM.&lt;/p&gt;

&lt;p&gt;The two tests answer different questions. A workload that boots, loads its driver and matches the source host's numbers has shown that the device works. Whether that same VM can be live-migrated for host maintenance, snapshotted before a change, or restarted automatically after a host failure depends on how the device was attached and on what the destination documents for that attachment. Those are separate capabilities. A sourced statement about one says nothing about the others, and this post treats them that way throughout.&lt;/p&gt;

&lt;p&gt;The decision here is narrow. The device-access mode constrains the lifecycle operations available to the VM, so it has to be evaluated per workload, before the destination is committed and before a cutover date is fixed. This is not a hardware compatibility checklist, and it does not claim to cover every hypervisor. Where the documentation is silent, or this review did not reach it, the text says so instead of filling the gap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkcox767863wg7ltpvy5z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkcox767863wg7ltpvy5z.jpg" alt="GPU passthrough lifecycle: device attached and working, live migration and snapshot blocked, HA restart not established" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The device works. Which VM operations survive is a separate question.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Booting Is Not a Lifecycle Test
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://www.rack2cloud.com/virtualization-architecture/" rel="noopener noreferrer"&gt;virtualization architecture&lt;/a&gt;, a VM's lifecycle is the set of operations the platform performs on it without the workload's involvement. It moves for maintenance, it is captured before a change, and it comes back after a host fails. Migration validation checks that the workload runs. The lifecycle is what the operations team assumes the platform will keep doing for years afterward. Four operations are worth keeping apart.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live migration&lt;/strong&gt; — moving a running VM to another host with no interruption, normally for planned maintenance or rebalancing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshots and suspend/resume&lt;/strong&gt; — separate capabilities, grouped here because they are often evaluated together during change and migration planning. Snapshot support does not establish suspend/resume support, or vice versa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HA restart&lt;/strong&gt; — starting the VM on another host after an unplanned host failure. The VM restarts. It does not migrate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Placement and drain&lt;/strong&gt; — where the scheduler may start the VM, and what happens to it when a host is drained for maintenance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The distinction between live migration and HA restart matters most. A platform that restarts a VM on another node after a failure has provided recovery. It has not provided live migration, and a planned drain that restarts the VM is an interruption the maintenance window has to absorb. A runbook that says "migrate the VMs off the host before patching" assumes live migration. A recovery plan that says "the cluster will restart it" assumes HA restart. A VM can have one without the other, and the device-access mode is one of the things that decides which. GPU passthrough is where that dependency shows up first, because the device is attached directly to the guest.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"Which of these four operations does this workload's maintenance, backup and recovery plan actually assume, and does its device-access mode provide each one on the destination?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Direct Assignment, Mediated Access, and the Four Operations
&lt;/h2&gt;

&lt;p&gt;Two device-access modes matter for GPU workloads: GPU passthrough and mediated access. The rest of this post keeps them separate. In direct assignment, which is what GPU passthrough means, the guest is given the physical device. Platforms name this PCI passthrough, DirectPath I/O or Discrete Device Assignment. In mediated or partitioned access, a vendor driver or the hypervisor presents a slice of the device to the VM, and some vendor-supported combinations document live migration under stated conditions. Whether a given combination does is a vendor-matrix question, and this review did not answer it. Treating the two modes as interchangeable is the error this post exists to prevent.&lt;/p&gt;

&lt;p&gt;Other device types, such as NICs and SR-IOV functions, raise the same question. They are out of scope here and were not surveyed, and nothing below should be read as covering them.&lt;/p&gt;

&lt;p&gt;The table records what this review established for each destination and mode. A sourced cell names its source in the section that follows. A cell marked "Not established" means the review did not find or verify a primary source for it. It is not a statement that the operation is unsupported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2d0cyrlzxczbbwtdnvt7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2d0cyrlzxczbbwtdnvt7.jpg" alt="GPU passthrough evidence matrix: sourced and not-established cells across vSphere, Hyper-V, Proxmox and AHV" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;What the documentation establishes, and where it stops.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Destination and mode&lt;/th&gt;
&lt;th&gt;Live migration&lt;/th&gt;
&lt;th&gt;Snapshots / suspend-resume&lt;/th&gt;
&lt;th&gt;HA restart&lt;/th&gt;
&lt;th&gt;Placement and drain&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vSphere, DirectPath I/O&lt;/td&gt;
&lt;td&gt;Blocked (Broadcom)&lt;/td&gt;
&lt;td&gt;Blocked (Broadcom)&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hyper-V, DDA (Windows Server 2025)&lt;/td&gt;
&lt;td&gt;Not currently supported (Microsoft)&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Restarts where pool GPU resources exist (Microsoft)&lt;/td&gt;
&lt;td&gt;Drain restarts the VM on a node with pool resources (Microsoft)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox VE, PCI passthrough&lt;/td&gt;
&lt;td&gt;Blocked (Proxmox guide)&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hyper-V, GPU partitioning&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxmox VE, mediated devices&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nutanix AHV, any GPU mode&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vendor vGPU on any hypervisor&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;td&gt;Not established&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What the Documentation Establishes About GPU Passthrough
&lt;/h2&gt;

&lt;p&gt;Three destination-and-mode combinations have primary documentation behind them. Each is stated at the scope its source supports.&lt;/p&gt;

&lt;h3&gt;
  
  
  vSphere DirectPath I/O
&lt;/h3&gt;

&lt;p&gt;Broadcom's knowledge base article &lt;a href="https://knowledge.broadcom.com/external/article/401437" rel="noopener noreferrer"&gt;Virtual Machine vMotion is not supported on PCI vSphere Direct Path I/O devices at the VM level&lt;/a&gt; is direct. When a PCI DirectPath I/O device is assigned to a VM, the VM cannot be live migrated, and snapshots and suspend/resume are blocked. The documented remedy is to shut the VM down and remove the device, after which vMotion works again. The article does not state which vSphere versions it applies to, so the exact build in the source environment is something to check, not assume. It also says nothing about HA restart. That cell stays open, because a restriction on live migration is not evidence about what happens after a host failure. For a VMware exit, this is the source-side baseline for VMs using PCI DirectPath I/O under the conditions the KB describes: live migration, snapshots and suspend/resume are unavailable. Do not generalize it to other GPU-access modes, or assume it applies to every vSphere build without checking the source environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hyper-V Discrete Device Assignment
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/windows-server/virtualization/hyper-v/deploy/use-gpu-with-clustered-vm" rel="noopener noreferrer"&gt;Microsoft's guidance for GPUs in clustered VMs&lt;/a&gt; is explicit about the split. DDA is Hyper-V's form of GPU passthrough. Live migration of VMs using GPUs provided by DDA isn't currently supported, but the cluster can restart those VMs and place them where GPU resources are available after a failure. Draining a server restarts the VM on another node that has sufficient resources in the GPU pool. The guidance applies to Windows Server 2025 and Azure Local 2311.2 and later, and DDA with GPU pools in clustered VMs requires Windows Server 2025 Datacenter edition.&lt;/p&gt;

&lt;p&gt;For planned maintenance the consequence is concrete: the drain is a restart, so the maintenance window has to treat it as an interruption. Microsoft points to GPU partitioning as the alternative to investigate when live migration is required. The support conditions for that mode are covered separately and were not verified in this review, so no live-migration capability is claimed for the partitioning row.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxmox VE
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://pve.proxmox.com/pve-docs/chapter-qm.html" rel="noopener noreferrer"&gt;Proxmox VE administration guide&lt;/a&gt; states it plainly: PCI or USB devices that are passed through currently block live-migration. For GPU passthrough on Proxmox, that sentence is the sourced finding. The copy retrieved for this review was labeled version 9.2.13 and dated 24 September 2026, so confirm the version your destination runs. Proxmox also supports cluster-level resource mappings, which its PCI passthrough documentation says exist so mapped devices can be properly used with HA. That is a statement of design intent. It does not establish that a VM with a mapped GPU restarts cleanly after a node failure, and snapshot behavior for passthrough VMs was not established either.&lt;/p&gt;

&lt;p&gt;This is also where Proxmox's operating assumptions diverge from vSphere's. &lt;a href="https://www.rack2cloud.com/proxmox-migration-assumptions/" rel="noopener noreferrer"&gt;Proxmox Isn't Replacing VMware. It's Replacing Assumptions.&lt;/a&gt; treats vMotion, snapshot semantics and HA clustering as VMware implementations of infrastructure primitives rather than primitives themselves. A passthrough VM is a case where the destination's implementation differs from the source's for a reason unrelated to the hypervisor's general design. The reason is the device-access mode.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;Do Not Generalize:&lt;/strong&gt; These findings apply to direct assignment. A restriction on GPU passthrough is not a restriction on GPUs, and a destination that blocks live migration for a passed-through device says nothing about its mediated or partitioned modes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Where the Evidence Stops
&lt;/h2&gt;

&lt;p&gt;Four items remain open for this review. None of them should be read as a negative finding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nutanix AHV.&lt;/strong&gt; No primary AHV source was retrieved for this review, for either GPU passthrough or vGPU. The rolling-maintenance model described in &lt;a href="https://www.rack2cloud.com/upgrade-physics-rolling-maintenance-ahv/" rel="noopener noreferrer"&gt;Upgrade Physics: Designing for Rolling Maintenance Without Stopping Production&lt;/a&gt; relies on evacuating workloads before a host is maintained. Whether an AHV GPU workload can participate in that evacuation under its actual access mode is not established here. That determines whether it can follow the normal maintenance procedure or needs a separately validated one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Proxmox mediated devices.&lt;/strong&gt; Proxmox documents mediated devices, including vGPU, as devices created when the VM starts and removed when it stops. That describes lifecycle at the device level. The documentation read for this review does not say whether a VM with a mediated device can live-migrate, so no claim is made either way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vendor vGPU matrices.&lt;/strong&gt; Any vGPU migration claim depends on the GPU vendor's current compatibility matrix and on the destination vendor's own documentation. Neither was retrieved for this review, so the post makes no vGPU migration claim for any destination.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hyper-V GPU partitioning.&lt;/strong&gt; Microsoft names it as the option when live migration is required. The supporting conditions were not verified, so the table leaves the row open.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration-Gating Decision Model
&lt;/h2&gt;

&lt;p&gt;The model has four steps, applied per workload, in order. It gates the cutover commitment. It is not a post-cutover validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  01 — REQUIRED OPERATIONS
&lt;/h3&gt;

&lt;p&gt;For each GPU workload, state which of the four operations its maintenance, backup and recovery plans require. Take this from the runbooks as written, not from what the platform is assumed to provide.&lt;/p&gt;

&lt;h3&gt;
  
  
  02 — ACTUAL ACCESS MODE
&lt;/h3&gt;

&lt;p&gt;Record whether each VM uses GPU passthrough, a mediated mode or a partitioned mode in production today, from the hypervisor configuration and not from the procurement record.&lt;/p&gt;

&lt;h3&gt;
  
  
  03 — DESTINATION EVIDENCE
&lt;/h3&gt;

&lt;p&gt;For that mode and each required operation, find the destination vendor's documentation for the exact release. Mark each cell sourced or not established. A cell that is not established is not a pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  04 — DISPOSITION
&lt;/h3&gt;

&lt;p&gt;Pass. Change the access mode. Substitute an operational procedure, such as a planned downtime window or restart-based recovery. Or leave it unresolved, which holds the workload out of the cutover commitment.&lt;/p&gt;

&lt;p&gt;The fourth step is the one that changes plans. A workload whose required operation is not established on the preferred destination does not pass by default. It is held out of the cutover commitment until the evidence is in, and the plan carries a date for getting it. The gate sits ahead of the destination commitment for the same reason. If a required operation fails on the preferred destination for the workload's current mode, the answer might be a different mode, a different destination for that workload, or an operational substitute. All three are cheaper to choose before the target is fixed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpslqxkc1mmwh7q7hleyl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpslqxkc1mmwh7q7hleyl.jpg" alt="Migration-gating decision model for GPU passthrough: required operations, access mode, destination evidence, disposition" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Four steps per workload, applied before the destination is committed.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is a migration-planning gate, in the same family as the other pre-cutover work in the &lt;a href="https://www.rack2cloud.com/modern-virtualization-learning-path/vmware-migration-strategy/" rel="noopener noreferrer"&gt;VMware Migration Strategy&lt;/a&gt; stage of the Virtualization Architecture Path. It belongs in the plan alongside that work.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Changes Before Target Selection
&lt;/h2&gt;

&lt;p&gt;Two neighboring problems should not be confused with this one. &lt;a href="https://www.rack2cloud.com/virtualization-operating-model-migration/" rel="noopener noreferrer"&gt;The Hypervisor Is Not the Migration Target — The Operating Model Is&lt;/a&gt; covers governance, authority and policy that fail to transfer to a new platform. That gap exists whatever the workloads are doing. Device-access mode is a property of the individual workload that constrains what the platform can do for it, with governance fully in place. And &lt;a href="https://www.rack2cloud.com/vmware-exit-plan-dependency/" rel="noopener noreferrer"&gt;Your VMware Exit Plan Assumed a Tool You Didn't Control&lt;/a&gt; covers an exit plan failing on access to the migration tooling itself. The shared lesson is that an exit plan's assumptions include things outside the destination's feature list. The device-access mode is one of them, and it lives in the workload.&lt;/p&gt;

&lt;p&gt;The GPU workloads in an estate can be listed. The useful output of the model is a per-workload disposition: which move with the main wave, which move later behind the evidence, which move in a different mode, and which move with a planned interruption written into the cutover plan. That list exists before any destination is chosen, and it should shape the shortlist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;GPU passthrough that works on the destination has passed a performance test. It has not passed a lifecycle test, and different things decide the two. The device-access mode constrains which lifecycle operations the VM can keep, and the destination's documentation for that mode and release determines whether each one is available.&lt;/p&gt;

&lt;p&gt;The real problem is that migration validation measures the device and skips the operations. Live migration, snapshots, HA restart and drain are four separate capabilities, and sourced evidence about one is not evidence about the others. Where the evidence is missing, the honest status is not established. It is not "unsupported" and it is not "assumed."&lt;/p&gt;

&lt;p&gt;Choose the access mode against the lifecycle the workload requires, before the destination is committed. Hold any workload whose required operation is not established out of the cutover commitment until it is. A VM that boots proves the device. It does not prove the lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/gpu-passthrough-vm-migration/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>virtualization</category>
      <category>vmware</category>
      <category>gpu</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>The Root KSK Rollover Is Done. Did Your Resolver's Trust Anchor Change?</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Mon, 12 Oct 2026 12:09:39 +0000</pubDate>
      <link>https://dev.to/ntctech/the-root-ksk-rollover-is-done-did-your-resolvers-trust-anchor-change-488b</link>
      <guid>https://dev.to/ntctech/the-root-ksk-rollover-is-done-did-your-resolvers-trust-anchor-change-488b</guid>
      <description>&lt;p&gt;The root KSK rollover swapped the key at the top of the DNSSEC chain, and what matters now is whether each of your validating resolvers swapped with it. &lt;a href="https://www.iana.org/dnssec/files" rel="noopener noreferrer"&gt;IANA's Trust Anchors and Rollovers page&lt;/a&gt; lists KSK-2024 (key tag 38696) as signing since 2026-10-11, with KSK-2017 (key tag 20326) no longer signing the root zone.&lt;/p&gt;

&lt;p&gt;IANA's &lt;a href="https://www.iana.org/news/2026/root-zone-begins-using-new-ksk-2026" rel="noopener noreferrer"&gt;announcement of 11 October&lt;/a&gt; states that the root zone began using a new KSK on that date, key tag 38696, replacing the previous key. That is IANA's statement of the event, not a query of my own.&lt;/p&gt;

&lt;p&gt;That is the scheduled state. Whether it is your state is a separate fact, and for most estates nobody has recorded it. Verisign's July data, as &lt;a href="https://blog.apnic.net/2026/10/09/rolling-the-root-key-2/" rel="noopener noreferrer"&gt;APNIC reports it&lt;/a&gt;, put roughly 90% of reporting resolvers at KSK-2024, while APNIC's own early-October measurement found about 70% of RFC 8509-capable test results reporting it trusted, with several ISPs under 10%. Those are different populations measured different ways, and neither describes your resolvers. This post is a method for producing that description: three kinds of evidence per resolver, kept on one worksheet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30br6pysg7yvgoow4e0k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30br6pysg7yvgoow4e0k.jpg" alt="root KSK rollover trust chain — a resolver anchored to KSK-2017 cannot validate a root DNSKEY RRset signed by KSK-2024" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How a Root KSK Rollover Breaks Validation
&lt;/h2&gt;

&lt;p&gt;A validating resolver does not discover trust; it is configured with it. The trust anchor is the one input DNSSEC cannot supply for itself. Everything beneath it is derived: the KSK signs the root DNSKEY RRset, that RRset publishes the zone-signing key, the ZSK signs the DS records for the TLDs, and each TLD vouches for the zones below it. A resolver validates an answer by walking that chain upward until it reaches a key it was told to trust.&lt;/p&gt;

&lt;p&gt;KSK-2024 has been published in the root DNSKEY RRset since January 2025. What the root KSK rollover changed on 11 October is the signer. The RRset is now signed by KSK-2024, and IANA lists KSK-2017 as no longer signing. A resolver whose trust anchors contain only KSK-2017 now receives a DNSKEY RRset signed by a key it was never told to trust. It cannot complete the chain, treats the data as bogus, and returns SERVFAIL. The algorithm did not change, so this is trust-anchor state and nothing else.&lt;/p&gt;

&lt;p&gt;The failure is not limited to signed domains. To answer for an unsigned name, a validating resolver must still prove that no DS record exists at the parent, and that proof rests on the same chain. The expected symptom is broad SERVFAIL for that resolver's clients, signed and unsigned names alike.&lt;/p&gt;

&lt;p&gt;Timing is where operators get misled. A resolver caches the DNSKEY RRset and its signature, and answers validated against the old signature stay usable until that cached data expires. The symptom therefore reaches different resolvers at different moments and can trail the switch-over. The size of the window is not a constant to quote. It is in the root's response, as the TTL on the DNSKEY RRset and the validity period of its RRSIG.&lt;/p&gt;

&lt;p&gt;I am not reporting an outage. This is what a validating resolver without KSK-2024 is expected to do. Whether any resolver you run is in that state is what the rest of this post establishes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the Trust Anchor Doesn't Update Itself
&lt;/h2&gt;

&lt;p&gt;RFC 5011 is why most resolvers needed no operator during the root KSK rollover. A resolver that supports it watches the root DNSKEY RRset, sees a new KSK appear, holds it for at least 30 days, and then adds it to its trust anchors without human action. KSK-2024 has had far longer than that, so a resolver running continuously, with state it can write and persist, has trusted it since early 2025.&lt;/p&gt;

&lt;p&gt;The exposure is every resolver that doesn't meet those conditions. That is an inventory problem, not a DNS problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resolvers that don't self-update:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pinned anchors&lt;/strong&gt; — a static anchor file or configuration statement carrying only KSK-2017, never touched because it never had to be&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restored and cloned images&lt;/strong&gt; — a resolver recovered from a snapshot returns with the trust state it had when the snapshot was taken, and one that was off or restored before it finished adopting KSK-2024 can no longer validate the RRset it would need to learn the key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Appliances and embedded resolvers&lt;/strong&gt; — firmware that ships a fixed anchor, where the update path is a firmware release&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless containers&lt;/strong&gt; — a resolver that can run RFC 5011 but discards its managed state on restart returns to whatever the image shipped, every time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forwarding chains&lt;/strong&gt; — a forwarder that trusts the AD bit from an upstream validator inherits that upstream's anchor state, so a failure at a resolver you don't run still lands in your tickets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resolvers built from images and modules inherit whatever trust state the image carried. That makes this as much a &lt;a href="https://www.rack2cloud.com/modern-infrastructure-iac-strategy-guide/" rel="noopener noreferrer"&gt;modern infrastructure and IaC&lt;/a&gt; problem as a DNS one: the stale anchor is a baked artifact, and drift detection rarely tracks it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;Common mistake:&lt;/strong&gt; Reading the anchor file as the resolver's state. A file on disk records what the resolver was configured to load. It does not prove what the running process loaded, and a file edited after the last restart proves nothing at all.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The scheduled revocation of KSK-2017 on 11 January 2027, and its removal on 22 March 2027, are the second half of the exposure. Both are IANA schedule dates, not yet events. A resolver following RFC 5011 learns of the revocation by watching the root. A pinned anchor never does and keeps trusting a retired key. That is revocation scoped at the trust root, and it carries the property the &lt;a href="https://www.rack2cloud.com/revocation-unit-credential-rotation/" rel="noopener noreferrer"&gt;revocation unit&lt;/a&gt; argument describes: it reaches only the verifiers that are still watching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three Results, Not One: Configured, Runtime, Behavioral
&lt;/h2&gt;

&lt;p&gt;Marking the root KSK rollover done because the date passed is the closure error &lt;a href="https://www.rack2cloud.com/architecture-of-premature-closure/" rel="noopener noreferrer"&gt;the architecture of premature closure&lt;/a&gt; names. This is not another row in that table: the change is external, you ran no remediation, and the question is whether your resolvers absorbed it.&lt;/p&gt;

&lt;p&gt;Record three results per resolver. Each answers a different question and none substitutes for the others.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Evidence&lt;/th&gt;
&lt;th&gt;What it can't prove&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Configured&lt;/td&gt;
&lt;td&gt;Is KSK-2024 (tag 38696) in the trust-anchor source?&lt;/td&gt;
&lt;td&gt;The anchor file or configuration for your software: BIND &lt;code&gt;bind.keys&lt;/code&gt; (&lt;code&gt;initial-ds 38696&lt;/code&gt;) or a &lt;code&gt;trust-anchors&lt;/code&gt; statement, Unbound's &lt;code&gt;auto-trust-anchor-file&lt;/code&gt;, Knot Resolver's &lt;code&gt;root.keys&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;That the running process loaded it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Has the running resolver loaded it?&lt;/td&gt;
&lt;td&gt;BIND &lt;code&gt;rndc managed-keys status&lt;/code&gt;; PowerDNS Recursor &lt;code&gt;rec_control get-tas&lt;/code&gt;; where no command lists anchors (Unbound 1.19 has none), compare process start or reload time to the anchor file's modification time&lt;/td&gt;
&lt;td&gt;Anything about validation behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavioral&lt;/td&gt;
&lt;td&gt;Does the resolver validate using it?&lt;/td&gt;
&lt;td&gt;The RFC 8509 sentinel test; a known-signed name returned with the &lt;code&gt;ad&lt;/code&gt; flag set&lt;/td&gt;
&lt;td&gt;Which anchor produced the result, or whether a forwarder answered instead&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feuhcyyxprp9fhf3wfrqx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feuhcyyxprp9fhf3wfrqx.jpg" alt="Configured, runtime and behavioral evidence for a resolver's root trust anchor" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.rfc-editor.org/rfc/rfc8509" rel="noopener noreferrer"&gt;RFC 8509&lt;/a&gt; sentinel test is the behavioral check, and it is a three-query test. A client queries a deliberately bogus name, then two names built from the key tag, &lt;code&gt;root-key-sentinel-is-ta-38696&lt;/code&gt; and &lt;code&gt;root-key-sentinel-not-ta-38696&lt;/code&gt;, as the leftmost label under a DNSSEC-signed test zone. A sentinel-aware validating resolver that trusts key 38696 answers the is-ta name and returns SERVFAIL for the not-ta name. One that does not trust it does the reverse. The bogus name must SERVFAIL; if it answers, something in the path is not validating. Some combinations, such as SERVFAIL on the bogus name and an answer on not-ta, are indeterminate when several resolvers sit behind one address. RFC 8509 §4.3 treats those as unreliable. Record them as indeterminate, not as a pass or a fail.&lt;/p&gt;

&lt;p&gt;Three cautions apply. Sentinel support is not universal, so a non-answer can mean unsupported rather than untrusted. A forwarder in front changes which resolver you tested. And a pass is evidence for the path that carried the query, not for every resolver you run.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"Which key does this resolver trust right now, and what did it do to prove it?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Telling a Trust-Anchor Failure From Ordinary SERVFAIL
&lt;/h2&gt;

&lt;p&gt;A root trust-anchor failure looks like every other SERVFAIL until you change one variable. Run the failing query against the suspect resolver with checking disabled (&lt;code&gt;dig +cd&lt;/code&gt;). If it answers with &lt;code&gt;+cd&lt;/code&gt; and fails without it, validation is failing, not reachability. Then query an unsigned name. Broad failure across signed and unsigned names with &lt;code&gt;+cd&lt;/code&gt; succeeding points to the top of the chain, since an expired signature or DS mismatch normally fails one zone. Neither test proves a root trust-anchor failure on its own. The stronger diagnosis comes from the sentinel result, the direct anchor evidence from the table above, and a comparison against a second validating resolver known to hold KSK-2024. Read the Extended DNS Error (RFC 8914) where your resolver returns one.&lt;/p&gt;

&lt;p&gt;Layered triage, such as the five phases in &lt;a href="https://www.rack2cloud.com/kubernetes-ingress-502-debug-mtu-dns/" rel="noopener noreferrer"&gt;It's Not DNS (It's MTU)&lt;/a&gt;, localizes a failure by path. A root-anchor failure isn't a location in that stack: every network-layer test can pass while the resolver still returns SERVFAIL, so the order of checks above is a trust test, not another triage ladder. The same separation holds for failover. A test that measures when traffic actually moves, the question &lt;a href="https://www.rack2cloud.com/dns-failover-testing/" rel="noopener noreferrer"&gt;DNS failover testing&lt;/a&gt; works through, is a caching question. This one is a trust question, and a resolver can pass the first while failing the second.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Resolver Evidence Worksheet
&lt;/h2&gt;

&lt;p&gt;The root KSK rollover leaves one row per validating endpoint, forwarders included. The columns are the record you will want to hand someone later:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What goes in it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Endpoint&lt;/td&gt;
&lt;td&gt;Resolver or forwarder address, and what depends on it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Software and version&lt;/td&gt;
&lt;td&gt;Needed to interpret the commands and sentinel behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation location&lt;/td&gt;
&lt;td&gt;This host, or an upstream&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Anchor management&lt;/td&gt;
&lt;td&gt;RFC 5011 managed, static file, firmware-embedded, image-baked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Configured / Runtime / Behavioral&lt;/td&gt;
&lt;td&gt;Three separate results, each with its evidence and query path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timestamp and owner&lt;/td&gt;
&lt;td&gt;When it was checked and who is accountable for the row&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Score each row PASS only when all three results are recorded. Anything unchecked is a FAIL until evidenced. Re-run the worksheet at the KSK-2017 revocation and removal dates, because those are the points at which pinned anchors diverge from managed ones.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6gvuo9ztl593hyh5bw9j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6gvuo9ztl593hyh5bw9j.jpg" alt="Resolver evidence worksheet preview" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download the Root KSK Rollover Resolver Evidence Worksheet: &lt;a href="https://rack2cloud.com/downloads/checklists/root-ksk-rollover-resolver-evidence-worksheet-v1.xlsx" rel="noopener noreferrer"&gt;spreadsheet&lt;/a&gt; or &lt;a href="https://rack2cloud.com/downloads/checklists/root-ksk-rollover-resolver-evidence-worksheet-v1.pdf" rel="noopener noreferrer"&gt;PDF&lt;/a&gt; — the per-resolver record used in this post, with a command reference by software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;A root KSK rollover is scheduled, announced and documented, which is why it fails quietly. Nobody opens an incident for an event that went to plan, and the plan was never what needed to succeed. The root signed with the new key. Whether your resolvers trust it is a separate fact, held in places that are not treated as configuration.&lt;/p&gt;

&lt;p&gt;The real problem is where resolver trust state lives. It sits in images, firmware, a state directory that may not persist, and a forwarder chain owned by someone else. None of those appear in an inventory under the name trust anchor, so the question of which key a resolver trusts has no owner until the day it matters.&lt;/p&gt;

&lt;p&gt;A rollover is finished when each resolver can show which key it trusts and a test that proves it. Everything before that is a calendar entry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/modern-infrastructure-iac-strategy-guide/" rel="noopener noreferrer"&gt;Modern Infrastructure &amp;amp; IaC Architecture&lt;/a&gt; — the pillar hub for image- and module-built estates, where stale resolver trust state gets baked in and goes untracked.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/revocation-unit-credential-rotation/" rel="noopener noreferrer"&gt;Rotating Credentials Is Not Revoking Them. The Revocation Unit Decides Whether You Can.&lt;/a&gt; — trust-root revocation reaches only the verifiers still watching, the property the scheduled KSK-2017 revocation shares.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/architecture-of-premature-closure/" rel="noopener noreferrer"&gt;The Architecture of Premature Closure&lt;/a&gt; — the signal-fired, state-unverified pattern; this post differs because the change is external and no remediation of yours ran.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/kubernetes-ingress-502-debug-mtu-dns/" rel="noopener noreferrer"&gt;It's Not DNS (It's MTU): Debugging Kubernetes Ingress&lt;/a&gt; — layered path triage that localizes failures by network location, the contrast case for a trust-state failure.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/dns-failover-testing/" rel="noopener noreferrer"&gt;Why Your DNS Failover Didn't Actually Fail Over&lt;/a&gt; — traffic-movement timing across caching layers, a different question from resolver trust.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.iana.org/dnssec/files" rel="noopener noreferrer"&gt;IANA: Trust Anchors and Rollovers&lt;/a&gt; and &lt;a href="https://www.iana.org/news/2026/root-zone-begins-using-new-ksk-2026" rel="noopener noreferrer"&gt;IANA's 11 October announcement&lt;/a&gt; — the signing-since date for KSK-2024, the announcement that the root zone began using it, and the scheduled KSK-2017 revocation and removal dates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/root-ksk-rollover-resolver-trust-anchor/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dns</category>
      <category>security</category>
      <category>devops</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>DKM ACL Hardening Is Scheduled. The Evidence It Worked Is Not.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Sun, 11 Oct 2026 14:41:09 +0000</pubDate>
      <link>https://dev.to/ntctech/dkm-acl-hardening-is-scheduled-the-evidence-it-worked-is-not-5g49</link>
      <guid>https://dev.to/ntctech/dkm-acl-hardening-is-scheduled-the-evidence-it-worked-is-not-5g49</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fupwwfcawzkyxmdy4sabc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fupwwfcawzkyxmdy4sabc.jpg" alt="Field Notes — Engineering Notes from the Complexity Gap | Rack2Cloud" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DKM ACL hardening for AD FS moves from audit to enforcement with the October 2026 update. Microsoft's page, &lt;a href="https://support.microsoft.com/en-us/servicing/os/windows/docs/2026/07/kb5121391-cve-2026-56155-ad-fs-dkm-container-acl-hardening" rel="noopener noreferrer"&gt;KB5121391&lt;/a&gt;, first published July 14, 2026, says that on Windows Server 2016 and later the update "will automatically remediate insecure ACLs" by October 13, 2026 unless the registry value says otherwise. Windows Server 2012 and 2012 R2 are different: enforcement auto-remediation does not apply, and the work is manual.&lt;/p&gt;

&lt;p&gt;That is a schedule. It is not evidence. This note is about what proves the ACL ended up in the expected state, who can read that proof, and how long it exists.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwzvsw7c2yzpsn8aurpe9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwzvsw7c2yzpsn8aurpe9.jpg" alt="DKM ACL hardening diagram: Server 2016+ AD FS nodes auto-remediate the AD container ACL while the 2012 R2 path stops at a manual ACE gate" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the DKM ACL Hardening Schedule Actually Promises
&lt;/h2&gt;

&lt;p&gt;AD FS relies on the Distributed Key Manager container to store the symmetric keys that protect the private keys of its token-signing and token-encryption certificates. Microsoft's stated risk: if the container's ACL is overly permissive, an attacker with read access to the DKM key material can decrypt the token-signing private keys. The page frames this as an elevation of privilege, CVE-2026-56155. It does not report exploitation, and neither does this note. The control sits in the governance layer of &lt;a href="https://www.rack2cloud.com/modern-infrastructure-iac-strategy-guide/" rel="noopener noreferrer"&gt;modern infrastructure architecture&lt;/a&gt;: state declared by a vendor, held by something else.&lt;/p&gt;

&lt;p&gt;The mechanics, as the page documents them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Audit, from the July 14 update&lt;/strong&gt; — Detection runs one minute after the AD FS service starts, then every 24 hours. No changes are made to the ACL. A mismatch logs event 1132.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Opt-in remediation&lt;/strong&gt; — Set &lt;code&gt;RemediateDkmAcl&lt;/code&gt; (DWORD) to &lt;code&gt;1&lt;/code&gt; under &lt;code&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ADFS&lt;/code&gt; on any one AD FS server in the farm. Remediation runs at the next detection cycle, or on a service restart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enforcement, from the October 2026 update&lt;/strong&gt; — Remediation "runs by default without requiring the registry key," equivalent to &lt;code&gt;RemediateDkmAcl = 1&lt;/code&gt;. Setting the value to &lt;code&gt;0&lt;/code&gt; opts out, and the page is blunt that opting out "leaves your DKM container vulnerable."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The page also says further hardening will follow in future updates. Microsoft published the dates in July, so there is no confirmation lag to manage; &lt;a href="https://www.rack2cloud.com/patch-visibility-debt/" rel="noopener noreferrer"&gt;Patch Visibility Debt&lt;/a&gt; covers the opposite problem, where confirmation lags the event. An announced date does not establish that the October update is deployed everywhere, or what the ACL looks like afterward. That is what the announcement leaves open.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Closure Signal Is an Update. The State Is One AD Object.
&lt;/h2&gt;

&lt;p&gt;Analysis, mine and not Microsoft's: in most change records the closure signal for this item will read "October update installed." &lt;a href="https://www.rack2cloud.com/architecture-of-premature-closure/" rel="noopener noreferrer"&gt;The Architecture of Premature Closure&lt;/a&gt; names that shape: a closure signal fires on execution, not on the verified state it was meant to represent. DKM ACL hardening is one more instance of it, not a new pattern.&lt;/p&gt;

&lt;p&gt;What makes the instance specific is where the state lives. The ACL is not on an AD FS server. Every event the page defines carries a single "Container DN," and the page tells you to "Ensure the AD FS service account has access to the DKM group container in Active Directory." AD FS servers run the detection and one of them performs the change, but the thing changed is a permission on an Active Directory object.&lt;/p&gt;

&lt;p&gt;In many organizations that splits ownership: the AD team owns the container's ACL and the AD FS team owns the service and the event log. Your actual owners have to be identified, not assumed. Remediation is an AD FS service action that rewrites a permission the AD team may believe is theirs, and the evidence of it lands in a log the AD team may never read. Who is accountable for the declared state of that ACL is the question &lt;a href="https://www.rack2cloud.com/configuration-drift-ownership/" rel="noopener noreferrer"&gt;configuration drift ownership&lt;/a&gt; addresses in general; DKM supplies a specific container to ask it about, and the &lt;a href="https://www.rack2cloud.com/modern-infrastructure-iac-learning-path/governance-drift/" rel="noopener noreferrer"&gt;governance and drift stage of the Modern Infrastructure learning path&lt;/a&gt; maps where that question sits.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Each Event Proves, and What It Cannot
&lt;/h2&gt;

&lt;p&gt;All five DKM ACL hardening events are written to the AD FS/Admin log on the AD FS server that logged them. What each one establishes is narrower than the label suggests.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Proves&lt;/th&gt;
&lt;th&gt;Cannot prove&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1132 (Warning)&lt;/td&gt;
&lt;td&gt;At check time the ACL did not match the expected secure state. Carries the container DN, an inheritance flag, and the current ACL as SDDL.&lt;/td&gt;
&lt;td&gt;Who changed it, or that anyone reviewed it. In audit mode, nothing was changed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1133 (Information)&lt;/td&gt;
&lt;td&gt;At check time the ACL matched the expected state. Carries only the container DN.&lt;/td&gt;
&lt;td&gt;That remediation ever ran, or that the previous ACL was preserved.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1134 (Error)&lt;/td&gt;
&lt;td&gt;The detection task failed, for example on LDAP connectivity.&lt;/td&gt;
&lt;td&gt;Anything about the ACL, in either direction.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1135 (Information)&lt;/td&gt;
&lt;td&gt;Remediation succeeded and the previous ACL is recorded as SDDL.&lt;/td&gt;
&lt;td&gt;That the SDDL still exists tomorrow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1136 (Error)&lt;/td&gt;
&lt;td&gt;Remediation was attempted and failed. Carries the current SDDL and the exception. The service retries within 24 hours.&lt;/td&gt;
&lt;td&gt;That the failure is resolved. The page points to manual hardening with ADSI Edit or PowerShell if it persists.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkwrdol4adsgxpwwcyeer.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkwrdol4adsgxpwwcyeer.jpg" alt="Event ladder from 1132 to 1135 showing the previous SDDL stored only in a rolling AD FS Admin log, with the overwritten slot empty" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The row that matters operationally is 1135. It records the previous ACL in SDDL as part of the success event, so its retention is the operational risk: Microsoft's own note says that event logs can roll over due to size limits and that an overwritten event means the previous SDDL "will be permanently lost." The page's recommendation is to save the message immediately on the AD FS server, using &lt;code&gt;Get-WinEvent -FilterHashtable @{LogName='AD FS/Admin'; Id=1135} -MaxEvents 1&lt;/code&gt; and writing &lt;code&gt;$event.Message&lt;/code&gt; to a file. Microsoft frames this as a recommended precaution, not a requirement. Treat it as the change evidence.&lt;/p&gt;

&lt;p&gt;A caution on the page itself. As of October 10, its sample commands carry transcription defects: the property name in the 2012 steps is cut off after "CertificateSharingContaine," the save command's output string is missing its closing quote, and the restore block mixes straight and curly quotes. This note describes the sequence; it is not a runbook. Copy from Microsoft's page, lint, and test in a lab before running anything.&lt;/p&gt;

&lt;p&gt;One inference, labeled as such: the 1135 text notes that auto-remediation will not run again while the ACL matches the baseline. If the ACL drifts later and remediation runs again, a second 1135 would record the drifted ACL as "previous." Keep the first one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Server 2012 and 2012 R2 Path
&lt;/h2&gt;

&lt;p&gt;For these platforms DKM ACL hardening is a manual sequence, per the page, run on any one AD FS server in the farm before the registry value is enabled: identify the DKM container DN, identify the AD FS service account, and grant that account explicit Allow ACEs for WriteOwner and WriteDacl on the container. Then set &lt;code&gt;RemediateDkmAcl&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;, creating the &lt;code&gt;ADFS&lt;/code&gt; key first if it is absent. Skip the grant and the page says remediation attempts will fail, which would surface as event 1136, retried every 24 hours. Microsoft's &lt;a href="https://support.microsoft.com/en-us/servicing/os/server-2012/2026/07/july-14-2026-kb5099445-monthly-rollup" rel="noopener noreferrer"&gt;KB5099445&lt;/a&gt;, the July 14 Windows Server 2012 ESU monthly rollup, carries the same DKM item: detection plus an opt-in remediation mechanism. The same page gives October 13, 2026 as the final date for Windows Server 2012 ESUs. That date is stated for Server 2012 on that page, and this note does not extend it to 2012 R2. Analysis: for a 2012 farm, the manual path and the end of the ESU stream share a date.&lt;/p&gt;

&lt;p&gt;For Server 2012 and 2012 R2, the October enforcement mode does not automatically enable remediation. Administrators must follow the platform-specific procedure: grant the required permissions to the AD FS service account, then explicitly opt in to remediation. The page does not describe how a farm containing both generations behaves, and this note makes no claim about it. Analysis: that is the case where "update installed" is most reliably true and the ACL is most likely unchanged. These are ESU platforms; &lt;a href="https://www.rack2cloud.com/lifecycle-support-boundary/" rel="noopener noreferrer"&gt;Compatibility Is Not The Same Thing As Support&lt;/a&gt; is the argument that "still receives updates" and "still has an owner" are separate facts.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Hardened ACL Removes
&lt;/h2&gt;

&lt;p&gt;After DKM ACL hardening completes, per the page, only these principals have access to the container:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Principal&lt;/th&gt;
&lt;th&gt;Access rights&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Domain Admins&lt;/td&gt;
&lt;td&gt;Generic All (Full Control)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enterprise Admins&lt;/td&gt;
&lt;td&gt;Generic All (Full Control)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;System&lt;/td&gt;
&lt;td&gt;Generic All (Full Control)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AD FS Service Account&lt;/td&gt;
&lt;td&gt;Read, Write, Create Child, Write Owner, Delete Tree&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Inheritance is disabled and all inherited ACEs are discarded. Any other explicit Allow ACE not in that list is removed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb0wsw4paltinmdc0pcut.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb0wsw4paltinmdc0pcut.jpg" alt="Before and after view of the AD FS DKM container ACL: four principals retained, unnamed other explicit Allow entries struck through" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The page does not say who might be on the "other" side of that line. Analysis: any non-standard principal on the container, whether older service accounts, delegated groups or third-party tooling, loses access without the page naming it, and the inventory of who they were is the SDDL in event 1132 or in the previous-ACL field of 1135. If neither was captured, nobody can answer the question afterward.&lt;/p&gt;

&lt;p&gt;A second inference, labeled the same way: the page describes tightening access going forward. It makes no statement about key material that was readable before the change, and this note makes none either. Whether that question applies to your farm is a review for you to run; &lt;a href="https://www.rack2cloud.com/revocation-unit-credential-rotation/" rel="noopener noreferrer"&gt;Rotating Credentials Is Not Revoking Them&lt;/a&gt; covers why rotating and revoking are different operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before DKM ACL Hardening Enforces
&lt;/h2&gt;

&lt;h3&gt;
  
  
  01 — Name the owners
&lt;/h3&gt;

&lt;p&gt;Name the owner of the DKM container ACL and the owner of the AD FS/Admin log. If they are different teams, put both on the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  02 — Read 1132, 1133 and 1134
&lt;/h3&gt;

&lt;p&gt;Check every AD FS server for 1132, 1133 and 1134 now. If 1132 is present, export its text: it carries the current ACL, which is your baseline.&lt;/p&gt;

&lt;h3&gt;
  
  
  03 — Remediate or opt out, deliberately
&lt;/h3&gt;

&lt;p&gt;Decide deliberately between remediating now and opting out. Microsoft frames opt-out as for a specific compatibility requirement with a plan to harden manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  04 — Server 2012 and 2012 R2
&lt;/h3&gt;

&lt;p&gt;On 2012 and 2012 R2, grant the ACEs, set the value, and expect 1135. Watch for 1136.&lt;/p&gt;

&lt;h3&gt;
  
  
  05 — Preserve the 1135 text
&lt;/h3&gt;

&lt;p&gt;When 1135 appears, save the full message off the server immediately and forward the AD FS/Admin log somewhere a size limit cannot erase.&lt;/p&gt;

&lt;h3&gt;
  
  
  06 — Record the evidence
&lt;/h3&gt;

&lt;p&gt;Record the 1135 text as the change evidence. Treat 1133 as a status, because it carries only the DN.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;A hardening deadline is a closure signal. DKM ACL hardening shows what sits behind one: state in an Active Directory object, evidence in a rolling event log, and ownership split between the team that holds the container and the team that runs the service.&lt;/p&gt;

&lt;p&gt;The control is not the weak part. Microsoft's sequence is detailed, phased and announced months ahead. The weak part is the habit of recording "update installed" as "ACL hardened," and the risk that the previous ACL survives only in evidence nobody preserved outside a rolling event log.&lt;/p&gt;

&lt;p&gt;The update closes the ticket. Only the event text closes the question.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/dkm-acl-hardening/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>windows</category>
      <category>activedirectory</category>
      <category>identity</category>
    </item>
    <item>
      <title>The Vendor Retention Window Wasn't a Recovery Control</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Sat, 10 Oct 2026 12:19:08 +0000</pubDate>
      <link>https://dev.to/ntctech/the-vendor-retention-window-wasnt-a-recovery-control-2njl</link>
      <guid>https://dev.to/ntctech/the-vendor-retention-window-wasnt-a-recovery-control-2njl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5rq06txjbpw9gj9b4ld.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5rq06txjbpw9gj9b4ld.jpg" alt="Field Notes — Engineering Notes from the Complexity Gap | Rack2Cloud" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A vendor retention window is a lifecycle schedule, not a recovery control, and the Microsoft 365 deletion reported on September 28 is a clean example of the distance between the two. If the only copy of a tenant's data sits inside the engine that enforces the schedule, a failure in that engine can become a failure of the recovery plan.&lt;/p&gt;

&lt;p&gt;What Microsoft has confirmed is narrow. A spokesperson told &lt;a href="https://www.theregister.com/a/5299433" rel="noopener noreferrer"&gt;The Register&lt;/a&gt; that an error resulted in remaining data, if any, being deleted before the retention period ended. The affected content was tied to expired Microsoft 365 Business Premium subscriptions held by nonprofit customers. Microsoft emailed one customer that it had investigated recovery options and that the data cannot be recovered. That is the confirmed record, and this post stays inside it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yiv4xwo84v0lki9o9fh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yiv4xwo84v0lki9o9fh.jpg" alt="vendor retention window — a vendor-controlled retention schedule beside an empty customer-controlled independent copy slot" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Microsoft Has and Hasn't Said
&lt;/h2&gt;

&lt;p&gt;The table separates Microsoft's attributed statements from what the public record leaves open. Nothing in the right column is a claim about Microsoft. It is the list of things a reader cannot currently know.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stated by Microsoft (via The Register, 2026-09-28)&lt;/th&gt;
&lt;th&gt;Not disclosed in the reporting&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;An error resulted in remaining data, if any, being deleted before the retention period ended&lt;/td&gt;
&lt;td&gt;The cause of the error&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The affected content was tied to expired Microsoft 365 Business Premium subscriptions&lt;/td&gt;
&lt;td&gt;The number of affected organizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Recovery options were investigated and the data cannot be recovered (email to one customer)&lt;/td&gt;
&lt;td&gt;The deletion date, or how early the deletion ran&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft is unable to list what was deleted, or whether any data was deleted&lt;/td&gt;
&lt;td&gt;The retention period that applied to the affected tenants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;The offer to customers is a free session to set up a new environment&lt;/td&gt;
&lt;td&gt;The reason recovery is not possible&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Counts circulating in secondary coverage rest on a single unconfirmed support-staff account and are not used here.&lt;/p&gt;

&lt;p&gt;One row deserves more weight than its length suggests. The party that deleted the data is also the party best placed to say what it held, and it says it cannot. For a customer without an independent copy or inventory, the vendor's inability to identify what was deleted leaves no reliable vendor-side account of the loss. Whatever the customer retained independently becomes critical to reconstructing what existed and what may be missing.&lt;/p&gt;

&lt;p&gt;The unknowns matter because they decide what a customer can reconstruct. Without a deletion date, a scope or an inventory from the vendor, an affected team cannot size its own loss from the vendor side. The burden of knowing what existed shifts to whatever records the customer kept independently, and a team that kept none is left asking the custodian a question the custodian has said it cannot answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Vendor Retention Window Is a Schedule, Not a Control
&lt;/h2&gt;

&lt;p&gt;Microsoft's published lifecycle for Microsoft 365 business subscriptions describes three stages: Expired, Disabled, Deleted. In the standard case, the headline durations are 30 days and 90 days for the first two, with different timings for enterprise and volume agreements, and CSP subscriptions follow a separate Partner Center reference. That is general product guidance. It is not evidence of the contractual or operational window that applied to the affected tenants, and nothing here assigns it to them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg45p3ry9vpoozwxe7p49.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg45p3ry9vpoozwxe7p49.jpg" alt="documented subscription lifecycle stages Expired, Disabled and Deleted, shown as general guidance with timings that vary by offer and agreement" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The schedule is legitimate, documented product behavior, and nothing in the record says it routinely fails. It is also a statement about what the vendor's engine will do. It says nothing about what a customer can do if the engine does something else. The same documentation recommends backing up before deletion, and states that a deleted subscription cannot be reactivated and that buying a new subscription does not restore the data. Microsoft's own &lt;a href="https://learn.microsoft.com/microsoft-365/commerce/subscriptions/what-if-my-subscription-expires" rel="noopener noreferrer"&gt;lifecycle documentation&lt;/a&gt; treats the lifecycle as the thing you back up around, not as the backup.&lt;/p&gt;

&lt;p&gt;A vendor retention window answers one question: how long does the custodian intend to hold the data. An independent copy answers a different one: if the custodian's hold fails for any reason, is there a copy it cannot touch. The first is a property of the vendor's lifecycle engine. The second is a property of your &lt;a href="https://www.rack2cloud.com/data-protection-architecture-strategy-guide/" rel="noopener noreferrer"&gt;data protection architecture&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Microsoft's documentation also distinguishes expiration from explicit deletion. An explicit deletion can bypass the Expired and Disabled stages, with SharePoint Online and OneDrive data deleted immediately. That is a different lifecycle path, not an explanation of the nonprofit incident. The architectural point is narrower: documented lifecycle stages describe expected vendor behavior, and they do not provide an independent recovery copy. A vendor retention window describes the vendor's process, and your recovery requirement has to be met by something you control.&lt;/p&gt;

&lt;p&gt;Whether the affected customers held an independent copy is not in the public record, and the argument does not depend on it. A hold enforced by the same engine that can delete is one failure domain, not two.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Is Not
&lt;/h2&gt;

&lt;p&gt;This is not an argument that SaaS vendors delete data when relationships end, and it is not a claim about how Microsoft's lifecycle normally behaves. Two neighboring problems are different decisions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rack2cloud.com/data-still-exists-cant-reach-it/" rel="noopener noreferrer"&gt;The Data Still Exists. You Just Can't Reach It.&lt;/a&gt; covers data you still hold that the identity, network and tooling around it make unreachable. Here the question is earlier: whether a copy exists at all outside the custodian's deletion boundary. &lt;a href="https://www.rack2cloud.com/retention-conflict-architecture/" rel="noopener noreferrer"&gt;The Retention Conflict Backup Architecture Wasn't Built to Arbitrate&lt;/a&gt; covers two legitimate obligations competing over one record. Nothing competes in this incident. One schedule is reported to have run before its own window closed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Check
&lt;/h2&gt;

&lt;p&gt;Applied to any consequential SaaS tenant, the test for whether a vendor retention window is doing any recovery work has three parts. A yes on the first does not carry the other two.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"Independence: does a copy exist outside the SaaS vendor's lifecycle and deletion boundary?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"Custody: who controls that copy, its credentials, and its retention policy?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"Recovery evidence: when was a representative restore last completed and verified?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxzb9kxipw57x4kpeonv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxzb9kxipw57x4kpeonv.jpg" alt="independent copy check — independence, custody and recovery evidence as three tests outside a vendor lifecycle boundary" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Independence.&lt;/strong&gt; A second tenant at the same vendor under the same admin plane is not outside the boundary. Neither is an export folder inside the tenant it protects. The copy has to survive the vendor deleting, expiring or disabling the original, and the test is whether you can name where it lives, whatever the vendor retention window says.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custody.&lt;/strong&gt; Who holds the credentials, and who sets the retention? If access to the copy depends on the identity provider or admin account of the tenant it protects, the two share a fate. If the copy's retention is governed by another vendor default that you cannot independently verify or control, you may have recreated the same dependency at another layer. Establish who controls retention, what deletion events can affect the copy, and what evidence demonstrates that the copy survives them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recovery evidence.&lt;/strong&gt; A copy outside the engine establishes a separate preservation boundary. It does not establish that the copy is complete, usable or restorable. The only evidence is a representative restore, with a date, a scope and a record of what failed. The &lt;a href="https://www.rack2cloud.com/data-protection-resiliency-learning-path/governance-recovery-assurance/" rel="noopener noreferrer"&gt;Governance &amp;amp; Recovery Assurance&lt;/a&gt; stage covers how that evidence is kept honest.&lt;/p&gt;

&lt;p&gt;A representative restore means more than opening one file. Sample each workload type the tenant holds, such as mailboxes, document libraries and the permissions that govern them. Restore into a clean location the original tenant does not control, verify contents against a known reference, and time it. If the restore needed the original tenant to be healthy, the copy was never independent.&lt;/p&gt;

&lt;p&gt;Run the check before the next lifecycle event, not after it. A subscription lapse, a license reassignment, a program change or an offboarding is the event that starts the vendor's clock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;A vendor retention window is a statement about the vendor's intent and the vendor's engine. It is not a recovery control, and the Microsoft 365 report does not change that so much as make it visible.&lt;/p&gt;

&lt;p&gt;The underlying problem is a single failure domain. When the custodian, the deletion schedule and the only copy sit inside the same failure domain, the customer has no independent copy to fall back on if the lifecycle process fails. In this case, Microsoft also said it could not identify what may have been deleted. The three-part check is the answer: a copy outside the boundary, controlled by you, with a restore you have completed and verified.&lt;/p&gt;

&lt;p&gt;The window is the vendor's schedule. The restore is yours.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/vendor-retention-window/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>devops</category>
      <category>backup</category>
      <category>security</category>
    </item>
    <item>
      <title>BYOC Isn't a Deployment Decision. It's a Control-Plane Delegation Nobody Scoped.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Fri, 09 Oct 2026 12:07:55 +0000</pubDate>
      <link>https://dev.to/ntctech/byoc-isnt-a-deployment-decision-its-a-control-plane-delegation-nobody-scoped-3p7h</link>
      <guid>https://dev.to/ntctech/byoc-isnt-a-deployment-decision-its-a-control-plane-delegation-nobody-scoped-3p7h</guid>
      <description>&lt;p&gt;BYOC delegation is the part of a bring-your-own-cloud decision that the deployment review never scopes. The review asks where the data plane runs, hears "your account," and files the question as answered. The question it skips is who receives authority over that account when you install the thing. In the offerings reviewed here, those two answers are not the same answer.&lt;/p&gt;

&lt;p&gt;This post reads the BYOC documentation for Redpanda, Databricks and Aiven, and treats WarpStream as a vendor claim at the far end of the range. The set is narrow: four data and analytics platforms, and the pages I read are weighted toward AWS. Every empirical statement below is tied to a page I read. "Not stated" means the pages I read do not state it, not that the vendor lacks it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkaqdetkxr62hq1pgjvlp.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkaqdetkxr62hq1pgjvlp.jpg" alt="BYOC delegation: the data plane sits in the customer account while vendor authority over it goes unscoped" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Question the Review Asks, and the One It Skips
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://www.rack2cloud.com/cloud-strategy/" rel="noopener noreferrer"&gt;cloud architecture strategy&lt;/a&gt;, a BYOC review that stops at residency asks one question: where does the data plane run? The documentation answers it the same way each time. &lt;a href="https://docs.redpanda.com/cloud-data-platform/get-started/byoc-arch/" rel="noopener noreferrer"&gt;Redpanda&lt;/a&gt; states that you deploy the data plane in your own VPC and that customer data never leaves it. &lt;a href="https://docs.databricks.com/aws/en/admin/cloud-configurations/aws/permissions" rel="noopener noreferrer"&gt;Databricks&lt;/a&gt; operates and manages clusters through a cross-account IAM role in the customer's AWS account. &lt;a href="https://aiven.io/docs/platform/howto/byoc/create-cloud/create-aws-custom-cloud" rel="noopener noreferrer"&gt;Aiven&lt;/a&gt; creates a VPC in the customer's account.&lt;/p&gt;

&lt;p&gt;The residency answer looks like the authority answer. It is not.&lt;/p&gt;

&lt;p&gt;The authority question is BYOC delegation: who receives permission over my environment when I install this. In Redpanda, Databricks and Aiven, the deployment process establishes that authority through IAM: a bootstrap step, cross-account role, or template the buyer applies. The residency review never reads it, because nothing in the residency question points there.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "Your Account" Means in BYOC
&lt;/h2&gt;

&lt;p&gt;Start with what the documentation establishes.&lt;/p&gt;

&lt;p&gt;In standard Redpanda BYOC, you bootstrap a VM in your VPC with &lt;code&gt;rpk cloud byoc apply&lt;/code&gt;. That VM launches the agent. Redpanda then assigns the IAM policies and creates dedicated roles per workload, which it describes as fine-grained and least privilege. The agent pulls cluster specifications from the control plane, and its IAM permissions let it call the cloud provider API to create and manage cluster resources, including VPC peering networks. The control plane handles provisioning, Kubernetes version upgrades and infrastructure maintenance.&lt;/p&gt;

&lt;p&gt;In Aiven's AWS custom cloud, you generate a Terraform template in the Aiven console, apply it in your account, and hand the resulting Role ARN back to Aiven. Aiven assumes that role to run operations such as creating the VMs for service nodes, and the documentation describes the grant as permission to create resources and manage them onward. The VPC is one Aiven creates in your account, within a CIDR range you choose.&lt;/p&gt;

&lt;p&gt;Then the constraint, stated precisely. Redpanda documents that it does not support customer access to or modification of internal data plane resources, and gives its reason: Redpanda manages configuration changes internally to support a 99.99% SLA for BYOC clusters. That is a specific, documented limit on what the customer can do inside the account. It is not a general claim that the customer has no control, and this post does not make one.&lt;/p&gt;

&lt;p&gt;"Runs in your account" therefore establishes where the resources live. It does not establish who can create, change or remove them. Who owns a control plane once the architecture splits is the question the &lt;a href="https://www.rack2cloud.com/cloud-architecture-learning-path/control-plane-architecture/" rel="noopener noreferrer"&gt;Control Plane Architecture&lt;/a&gt; stage of the learning path takes up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same Location, Different Authority
&lt;/h2&gt;

&lt;p&gt;BYOC delegation varies even when location does not, and Redpanda provides the cleanest control: one vendor, one data plane location, two variants.&lt;/p&gt;

&lt;p&gt;In standard BYOC, Redpanda manages the networking lifecycle and assigns the IAM policies. In BYOVPC, you supply the VPC and the IAM role the agent assumes. You create the networking and security resources in advance, and Redpanda states that the agent does not create or change them. The agent still deploys and operates the cluster, using the role you supply with only the permissions you grant. Redpanda says BYOVPC requires fewer permissions than standard BYOC.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4w0vf9f3k88jup5mndba.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4w0vf9f3k88jup5mndba.jpg" alt="Redpanda BYOC versus BYOVPC: same data plane location, different authority over IAM roles and networking" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Databricks shows this is not a Redpanda naming quirk. The cross-account role for a Databricks-managed VPC carries permissions to create and delete the VPC, subnets, route tables, NAT and internet gateways and VPC endpoints, plus launch and terminate instances. For a customer-managed VPC the documented set is smaller: the VPC, subnet, route and NAT creation and deletion permissions do not appear in that table, and the documentation states the set can be scoped down further with custom resource restrictions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dimension&lt;/th&gt;
&lt;th&gt;Vendor-managed BYOC&lt;/th&gt;
&lt;th&gt;Customer-managed variant&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Data-plane location&lt;/td&gt;
&lt;td&gt;Customer account (Redpanda, Databricks)&lt;/td&gt;
&lt;td&gt;Customer account (Redpanda, Databricks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IAM authority&lt;/td&gt;
&lt;td&gt;Redpanda assigns the policies and creates the roles&lt;/td&gt;
&lt;td&gt;Redpanda BYOVPC: customer supplies the role, and the agent is limited to what it grants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delegated permissions&lt;/td&gt;
&lt;td&gt;Databricks: full VPC and network lifecycle set&lt;/td&gt;
&lt;td&gt;Databricks: smaller set, scopable further&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network resources&lt;/td&gt;
&lt;td&gt;Redpanda manages the networking lifecycle&lt;/td&gt;
&lt;td&gt;Customer creates them in advance (Redpanda) or provisions the VPC (Databricks)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational burden&lt;/td&gt;
&lt;td&gt;Not stated in the pages read&lt;/td&gt;
&lt;td&gt;Not stated in the pages read&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The location row is identical in both columns. The authority rows are not. Same location is not same authority.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Decision Is Made at Deployment, and Reduced Authority Can Be a Product Boundary
&lt;/h2&gt;

&lt;p&gt;Two further facts from the same pages change how to read the table. Redpanda states that existing clusters cannot be converted to BYOVPC and that a BYOVPC cluster cannot change VPCs after creation. BYOVPC is an add-on that requires Premium support. On the Databricks side, the customer-managed VPC variant requires the Premium plan or above.&lt;/p&gt;

&lt;p&gt;This is not a pricing argument. The architectural point is that BYOC delegation is a design decision, not an implementation detail. In these two offerings, narrower vendor authority is a variant you select and a tier you qualify for, not a setting you adjust later. For Redpanda the variant is fixed at creation. The Databricks page I read does not state whether a workspace can move between VPC types.&lt;/p&gt;

&lt;p&gt;The far end of the range is a vendor claim, and it should be read as one. In a June 2024 &lt;a href="https://www.warpstream.com/blog/secure-by-default-how-warpstreams-byoc-deployment-model-secures-the-most-sensitive-workloads" rel="noopener noreferrer"&gt;blog post&lt;/a&gt;, WarpStream says its agents need only access to an object storage bucket and an outbound connection to its control plane, that no IAM roles or permissive security policies are required, and that the customer is responsible for running the stateless compute. I have not independently verified any of that, and it does not appear as a row in the inventory below. It shows what the variable looks like when a vendor chooses to remove the grant instead of reducing it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7yu3502ym6hhbqvgdnq7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7yu3502ym6hhbqvgdnq7.jpg" alt="BYOC delegation inventory across five Redpanda, Databricks and Aiven configurations, with not-stated cells left as empty slots" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The BYOC Delegation Inventory
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"What can this vendor's control plane actually do inside my account, and what do the vendor's own documents say about it?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A review of BYOC delegation should produce an inventory, not a residency statement. Here is the inventory for the offerings reviewed, with four columns. The fourth is validation, not a control: it records what the documentation says happens to the deployed data plane if the vendor control plane is unreachable, and it is evidence-dependent. Where a page I read does not state something, the cell says NS.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Offering (variant)&lt;/th&gt;
&lt;th&gt;Install-time grant&lt;/th&gt;
&lt;th&gt;Resource scope&lt;/th&gt;
&lt;th&gt;Customer-side constraint&lt;/th&gt;
&lt;th&gt;Control-plane-loss behavior (validation, not a control)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Redpanda BYOC&lt;/strong&gt; (standard)&lt;/td&gt;
&lt;td&gt;Customer bootstraps a VM in their VPC that launches the agent. Redpanda then assigns the IAM policies and creates dedicated per-workload roles. The agent uses them to call the cloud provider API.&lt;/td&gt;
&lt;td&gt;Cluster resources, Kubernetes version upgrades and infrastructure maintenance, VPC peering, and the networking lifecycle.&lt;/td&gt;
&lt;td&gt;None stated for scoping the grant. Customers cannot access or modify internal data plane resources.&lt;/td&gt;
&lt;td&gt;Stated: clusters remain available if the connection to the control plane is lost. Management during the outage: NS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Redpanda BYOVPC&lt;/strong&gt; (add-on, Premium support)&lt;/td&gt;
&lt;td&gt;Customer supplies the VPC and the IAM role (instance profile) the agent assumes. The agent operates with only the permissions the customer grants.&lt;/td&gt;
&lt;td&gt;Customer pre-creates networking and security resources, and the agent does not create or change them. It still deploys and operates the cluster infrastructure.&lt;/td&gt;
&lt;td&gt;Customer grants the permissions. The example module restricts the IAM it grants to tagged resources and the cluster definition references a permissions boundary policy. Provisioning checks that the roles meet a minimum permission set, so there is a floor as well as a ceiling.&lt;/td&gt;
&lt;td&gt;NS on this page. The page states the cluster needs outbound access to send telemetry to the control plane.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Databricks&lt;/strong&gt; (Databricks-managed VPC)&lt;/td&gt;
&lt;td&gt;Cross-account IAM role in the customer's AWS account. The documented purposes include creating and deleting the VPC, subnets, route tables, NAT and internet gateways and VPC endpoints, plus launching and terminating instances.&lt;/td&gt;
&lt;td&gt;EC2 and VPC resources for the workspace.&lt;/td&gt;
&lt;td&gt;Organization-level SCPs that deny AssumeRole or EC2/VPC access can break the role setup, so customer-side policy can constrain it.&lt;/td&gt;
&lt;td&gt;NS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Databricks&lt;/strong&gt; (customer-managed VPC, Premium or above)&lt;/td&gt;
&lt;td&gt;Same role mechanism, smaller permission set. The VPC, subnet, route and NAT create and delete permissions do not appear in this table. Instance launch and terminate, volumes, fleets and launch templates remain.&lt;/td&gt;
&lt;td&gt;Narrower, because the customer provisions the VPC.&lt;/td&gt;
&lt;td&gt;The documentation states the set can be scoped down further with custom resource restrictions.&lt;/td&gt;
&lt;td&gt;NS.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Aiven&lt;/strong&gt; (AWS custom cloud)&lt;/td&gt;
&lt;td&gt;Customer applies a generated Terraform template that yields a Role ARN. Aiven assumes that role to run operations such as creating node VMs. The documentation describes it as permission to create resources and manage them onward.&lt;/td&gt;
&lt;td&gt;A VPC Aiven creates in the customer account (customer-chosen CIDR, /16 to /24), node VMs, and an S3 bucket if object storage is enabled. The customer selects which Aiven projects or units may use the cloud.&lt;/td&gt;
&lt;td&gt;The template can be viewed, downloaded and modified before it is applied. How the role's permissions can be scoped: NS.&lt;/td&gt;
&lt;td&gt;NS.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three readings follow, and none of them goes beyond the cells.&lt;/p&gt;

&lt;p&gt;First, the density of NS. The control-plane-loss column is populated for one of the three vendors, and even there it states availability, not whether management continues. The constraint column is documented for Redpanda BYOVPC and Databricks, and partial for Aiven.&lt;/p&gt;

&lt;p&gt;Second, a pointer on Aiven. The IAM permissions JSON on the Aiven page belongs to the user who deploys the template, not to the role Aiven assumes. The Aiven documentation I reviewed does not state how that role's permissions can be scoped. It does show the template can be viewed before you apply it, which is the place to start reading the grant.&lt;/p&gt;

&lt;p&gt;Third, an inversion. In standard Redpanda BYOC, the documented constraint binds the customer, not the vendor: the customer cannot access or modify internal data plane resources in the account the customer owns.&lt;/p&gt;

&lt;p&gt;Unknown is a result. If a vendor's documentation establishes where the workload runs but does not establish what happens when its control plane disappears, the architecture review should record that gap, not infer an answer. Same location plus documented BYOC delegation is still not an understood architecture. It is an architecture with a populated inventory and a list of questions to put to the vendor.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Post Does Not Argue
&lt;/h2&gt;

&lt;p&gt;Four adjacent arguments already have homes, and this post cites them instead of repeating them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/third-party-cloud-access/" rel="noopener noreferrer"&gt;Your Cloud Isn't Compromised. Your Vendor Is. Now What?&lt;/a&gt; covers why third-party authority persists after the trust behind it fails.&lt;/li&gt;
&lt;li&gt;That SaaS integrations accumulate authority over time belongs to &lt;a href="https://www.rack2cloud.com/saas-control-plane/" rel="noopener noreferrer"&gt;The SaaS Control Plane Problem&lt;/a&gt;. The BYOC delegation examined here is the authority granted at deployment, not what builds up afterward.&lt;/li&gt;
&lt;li&gt;The delegation object and its schema are covered by &lt;a href="https://www.rack2cloud.com/delegation-governance/" rel="noopener noreferrer"&gt;Enterprise Architecture Has Identity Governance. It Doesn't Have Delegation Governance.&lt;/a&gt; The inventory above is a BYOC-specific fill-in, not a competing model.&lt;/li&gt;
&lt;li&gt;How a delegation is revoked belongs to &lt;a href="https://www.rack2cloud.com/revocation-unit-credential-rotation/" rel="noopener noreferrer"&gt;Rotating Credentials Is Not Revoking Them&lt;/a&gt;. This post does not teach the mechanism, and the inventory has no removal-path column.
Two scope limits apply. The empirical claims cover the BYOC offerings reviewed here and no others. And the inventory has no column for whether a vendor can change the grant over time, because none of the pages I read state it. That row is under investigation, not claimed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;BYOC is a control-plane delegation decision disguised as a deployment-location decision. The residency answer is real and the documentation supports it. It is also the less informative of the two answers a review needs.&lt;/p&gt;

&lt;p&gt;The underlying problem is that the install step establishes the BYOC delegation while the review records the location. In the offerings reviewed here, the vendor-created roles, the resources a customer may not touch, and the narrower variants gated behind a tier are all visible in public documentation. They go unscoped because the review has no artifact that asks for them.&lt;/p&gt;

&lt;p&gt;The BYOC delegation inventory is that artifact, and its empty cells are part of its output. Where the documentation is silent, you have found a question for the vendor, not a reason to assume the answer you were hoping for.&lt;/p&gt;

&lt;p&gt;Residency tells you where the data sits. Only the inventory tells you who can act on it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/cloud-strategy/" rel="noopener noreferrer"&gt;Cloud Architecture Strategy&lt;/a&gt; — the pillar hub covering placement, ownership and exit decisions across cloud architecture.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/cloud-architecture-learning-path/control-plane-architecture/" rel="noopener noreferrer"&gt;Control Plane Architecture&lt;/a&gt; — the learning path stage on who owns the control plane once responsibility splits across vendor and customer.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/third-party-cloud-access/" rel="noopener noreferrer"&gt;Your Cloud Isn't Compromised. Your Vendor Is. Now What?&lt;/a&gt; — what happens to standing third-party authority once the trust behind it fails.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/saas-control-plane/" rel="noopener noreferrer"&gt;The SaaS Control Plane Problem&lt;/a&gt; — how authority accumulates through SaaS integrations, the layer after the install-time grant covered here.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/delegation-governance/" rel="noopener noreferrer"&gt;Enterprise Architecture Has Identity Governance. It Doesn't Have Delegation Governance.&lt;/a&gt; — the delegation object this post's inventory fills in for BYOC.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.redpanda.com/cloud-data-platform/get-started/byoc-arch/" rel="noopener noreferrer"&gt;Redpanda BYOC Architecture&lt;/a&gt; — vendor documentation for the standard BYOC control plane and agent model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/byoc-delegation/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>byoc</category>
      <category>cloud</category>
      <category>iam</category>
      <category>architecture</category>
    </item>
    <item>
      <title>KMS Circular Dependency: The Cluster Came Back. The Keys Didn't.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Thu, 08 Oct 2026 12:27:57 +0000</pubDate>
      <link>https://dev.to/ntctech/kms-circular-dependency-the-cluster-came-back-the-keys-didnt-327h</link>
      <guid>https://dev.to/ntctech/kms-circular-dependency-the-cluster-came-back-the-keys-didnt-327h</guid>
      <description>&lt;p&gt;A KMS circular dependency turns an online cluster into an unreadable one: the data needs a key, and the service that holds the key lives on the data. Hosts can be running, membership can be intact, and the storage can still be unable to complete the unlock path.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo32m49uvazmzwu3gww81.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo32m49uvazmzwu3gww81.jpg" alt="KMS circular dependency — key service hosted on the encrypted datastore it unlocks, with the unlock path blocked" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What "Available" Hides
&lt;/h2&gt;

&lt;p&gt;Availability and readability are different properties. In &lt;a href="https://www.rack2cloud.com/virtualization-architecture/" rel="noopener noreferrer"&gt;virtualization architecture&lt;/a&gt;, "available" usually describes the coordination layer: hosts joined, quorum held, services running. "Readable" describes something narrower: the cluster can obtain the key material it needs to decrypt the data it is holding. A cluster can have the first and lack the second.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rack2cloud.com/two-node-edge-deployment/" rel="noopener noreferrer"&gt;The two-node edge deployment argument&lt;/a&gt; separates availability from capacity the same way: quorum says the cluster is up and says nothing about what that state costs. The gap here opens on a different axis. An encrypted cluster can be up and unable to read its own disks.&lt;/p&gt;

&lt;p&gt;The scope is narrow, and it sits at the edge of an earlier comparison. &lt;a href="https://www.rack2cloud.com/nutanix-vs-vmware-availability-authority/" rel="noopener noreferrer"&gt;Availability vs Authority&lt;/a&gt; scopes its Nutanix outcomes to clusters that don't depend on a key manager outside the cluster. This post covers the ones that do. The claim is that storage survivability is configuration-dependent, and that one function, unlock, shows it with vendor primary documentation behind it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2cr3kor0wszzka95sqc9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2cr3kor0wszzka95sqc9.jpg" alt="Cluster online versus dataset readable — two states of an encrypted storage cluster after a full restart" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Five Storage Functions, One Populated Row
&lt;/h2&gt;

&lt;p&gt;Between power-on and a usable datastore, a storage platform performs more than one function, and each function has its own dependency path. Five are worth separating.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Dependency question&lt;/th&gt;
&lt;th&gt;Status in this post&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Unlock&lt;/td&gt;
&lt;td&gt;Does the key service stay reachable when the storage is cold?&lt;/td&gt;
&lt;td&gt;Worked below&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mount&lt;/td&gt;
&lt;td&gt;What must be present before the unlocked volume presents to hosts?&lt;/td&gt;
&lt;td&gt;Under investigation, not claimed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Discover&lt;/td&gt;
&lt;td&gt;What must resolve before hosts and VMs find the datastore?&lt;/td&gt;
&lt;td&gt;Under investigation, not claimed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replicate&lt;/td&gt;
&lt;td&gt;What must be reachable for a replication link to authenticate and move data?&lt;/td&gt;
&lt;td&gt;Under investigation, not claimed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validate&lt;/td&gt;
&lt;td&gt;What must be reachable before a restored state can be checked as usable?&lt;/td&gt;
&lt;td&gt;Under investigation, not claimed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only the first row carries evidence here: unlock, where the KMS circular dependency lives. The other four are the same question asked of different functions. None is shown to fail the same way, and nothing below implies it.&lt;/p&gt;

&lt;p&gt;This sits beside the &lt;a href="https://www.rack2cloud.com/modern-virtualization-learning-path/storage-architecture/" rel="noopener noreferrer"&gt;Storage Survivability Boundary&lt;/a&gt;, Framework #109: the point where a storage architecture can no longer absorb component failure, rebuild activity, or locality loss without breaking its performance or availability assumptions. A cluster can sit well inside that boundary and still be unreadable, because the unlock dependency isn't part of the arithmetic the boundary models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdu0s9b3wcyzpq7phycqf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdu0s9b3wcyzpq7phycqf.jpg" alt="Five storage functions with unlock populated by evidence and mount, discover, replicate and validate marked not claimed" width="799" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The KMS Circular Dependency: Unlock and Decrypt, Worked
&lt;/h2&gt;

&lt;p&gt;The evidence standard for this section has three rungs: the dependency a vendor documents, the consequence it documents, and the mechanism it documents. Where the vendor stops, this post stops.&lt;/p&gt;

&lt;h3&gt;
  
  
  vSAN: The Circular Case Is Documented
&lt;/h3&gt;

&lt;p&gt;Broadcom's KB 453198 (vSAN 8.x and 9.x) names the KMS circular dependency directly. It occurs when the KMS virtual machines sit on the same encrypted vSAN datastore they are responsible for unlocking. While the cluster is online and the keys are cached in host memory, Broadcom notes, the configuration appears functional. A full power outage or a host reboot clears that cache. At startup the ESXi hosts cannot mount the encrypted disk groups without a network connection to the KMS. The KMS virtual machines cannot power on, because the datastore underneath them is locked. Each side waits on the other.&lt;/p&gt;

&lt;p&gt;The guidance for a KMS circular dependency follows from the mechanism: never locate the KMS on the datastore it unlocks. A new KMS installation that holds none of the original keys will not decrypt existing data, so recovery means restoring the original KMS or its keys, with restoring the KMS to non-encrypted storage as the preferred path. Without external backups of the KMS appliances or exported keys, the data is permanently inaccessible.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;Do not reboot your way out:&lt;/strong&gt; Broadcom's guidance is explicit: do not reboot hosts while key access is unavailable. Keys can remain cached in memory after a KMS outage, and a reboot destroys that cache and removes the remaining ability to access the data. Do not recreate disk groups or disable encryption to bypass the lock. Recreating disk groups can destroy the remaining possibility of recovering the data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two variants appear in Broadcom's vSAN 8.0 administration guide, which documents the baseline the same way: a rebooting host does not mount its disk groups until it receives the key-encryption key from the KMS. From vSAN 7.0 Update 3, key persistence lets hosts retain their keys across a reboot, in a TPM where one is present, so encryption operations can continue while the key server is unavailable. Native Key Provider, supported from vSAN 7.0 Update 2, needs no external KMS: vCenter Server generates the key material and pushes it to the hosts, which then generate the data encryption keys. KB 453198 describes the cached-key case and does not mention either variant. This post does not claim how they interact with the KMS circular dependency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nutanix: The Warning Is Documented, the Cycle Isn't
&lt;/h3&gt;

&lt;p&gt;The AOS Security 7.6 Security Guide is the governing source for the Nutanix claims here. The relevant language is unchanged from AOS Security 6.8. The guide separates two encryption modes, and the evidence differs by mode.&lt;/p&gt;

&lt;p&gt;For self-encrypting drives using an external KMS, the key service is outside the cluster and the Controller VM uses KMIP to upload and retrieve the drive keys. One KMS is required, several are recommended so the KMS is not a single point of failure, and the guide advises clustering them (p. 149). After a full power-off and power-on with protection enabled, the Controller VM retrieves the drive keys from the KMS to unlock the drives. If it cannot get the correct keys, it cannot access the data (p. 149).&lt;/p&gt;

&lt;p&gt;Software-only encryption does not inherit that sentence. The guide gives it an access-condition list instead. The system accesses the external KMS when a cluster starts, when a key is regenerated, when the KMS type is switched, and when the NCC heartbeat checks that the KMS is alive. For software-only encryption specifically, it also accesses the KMS when a service starts or restarts and when AOS is upgraded (pp. 149–150).&lt;/p&gt;

&lt;p&gt;For an external KMS in both modes, the guide carries an explicit caution: do not host a key management server VM on the encrypted cluster that is using it, because a problem with that VM could result in complete data loss (pp. 149, 164). That is a topology prohibition and a stated consequence. The guide does not describe the startup sequence that produces the loss.&lt;/p&gt;

&lt;p&gt;Native KMS removes the external KMS dependency by design, within conditions. Native KMS (local) is software-only and needs at least three nodes. One- and two-node clusters are not supported for it (pp. 147, 160). Its keys must be backed up (p. 147). Native KMS (remote), meant for one- and two-node remote-office clusters, is available only when the cluster is registered to Prism Central (p. 160), and the guide notes that the root key is retained on Prism Central if the cluster is destroyed while still registered (p. 167). That documents a dependency on Prism Central registration. It does not document how or when keys are retrieved, and this post does not claim it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Each Vendor Documents, and Where It Stops
&lt;/h3&gt;

&lt;p&gt;Both vendors warn against placing the key-management function on the encrypted storage it is responsible for unlocking. The documentation differs in how much of the failure it exposes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rung&lt;/th&gt;
&lt;th&gt;Broadcom (vSAN 8.x, 9.x)&lt;/th&gt;
&lt;th&gt;Nutanix (AOS Security 7.6)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dependency documented&lt;/td&gt;
&lt;td&gt;Hosts need the KMS to mount encrypted disk groups at startup&lt;/td&gt;
&lt;td&gt;The CVM retrieves keys from an external KMS; access conditions listed by mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consequence documented&lt;/td&gt;
&lt;td&gt;Locked datastore; a new KMS without the original keys cannot decrypt; no external backups means permanent inaccessibility&lt;/td&gt;
&lt;td&gt;SED: the CVM cannot access data without the correct keys. Hosted KMS VM: complete data loss warning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mechanism documented&lt;/td&gt;
&lt;td&gt;Yes: hosts cannot mount without the KMS, and the KMS VMs cannot power on from the locked datastore&lt;/td&gt;
&lt;td&gt;Not for a hosted KMS VM, and not for Native KMS (remote) retrieval&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;No ranking follows. A vendor that documents less of a failure has not been shown to fail differently, and a vendor that documents the whole cycle has not been shown to be more exposed to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rack2cloud.com/disaster-recovery-dependencies/" rel="noopener noreferrer"&gt;The Dependencies Recovery Plans Forget&lt;/a&gt; names four dependency objects that recovery plans treat as assumptions: identity, DNS, certificates, and network. A key manager is not on that list, and the circular case is the version where the dependency is not only forgotten. It cannot start until the storage it unlocks is already readable. &lt;a href="https://www.rack2cloud.com/recovery-boundary-dependency-failure/" rel="noopener noreferrer"&gt;The System Recovered. Your Recovery Boundary Didn't.&lt;/a&gt; argues that recovery boundaries get drawn around what the organization owns instead of what the service depends on, which is a question about dependencies left outside the boundary. This one can sit inside the boundary and still fail, because of ordering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Preconditions
&lt;/h2&gt;

&lt;p&gt;Survivability here depends on a configuration state: where the key service runs relative to the storage it unlocks. Eight configurations follow, graded by what the evidence supports. The grade labels the evidence class. It does not mean recommended. One row establishes the external placement condition; another creates the KMS circular dependency outright. The remaining rows set the conditions around it.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Configuration&lt;/th&gt;
&lt;th&gt;Cold-start / access dependency&lt;/th&gt;
&lt;th&gt;Evidence / Scope&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;vSAN&lt;/td&gt;
&lt;td&gt;External KMS, off the encrypted datastore&lt;/td&gt;
&lt;td&gt;Hosts need a network connection to the KMS to mount encrypted disk groups at startup&lt;/td&gt;
&lt;td&gt;PRIMARY — KB 453198 — vSAN 8.x, 9.x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vSAN&lt;/td&gt;
&lt;td&gt;KMS VM on the encrypted datastore it unlocks&lt;/td&gt;
&lt;td&gt;Creates the KMS circular dependency: unlock requires the KMS the datastore hosts&lt;/td&gt;
&lt;td&gt;PRIMARY — KB 453198 — vSAN 8.x, 9.x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vSAN&lt;/td&gt;
&lt;td&gt;Host key persistence with a TPM&lt;/td&gt;
&lt;td&gt;Hosts retain keys across a reboot and encryption operations continue while the key server is unavailable (vSAN 7.0 U3+); whether it eliminates or changes the circular failure path is not established here&lt;/td&gt;
&lt;td&gt;PRIMARY — vSAN 8.0 ADMIN GUIDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vSAN&lt;/td&gt;
&lt;td&gt;Native Key Provider&lt;/td&gt;
&lt;td&gt;No external KMS: vCenter Server generates the key material and pushes it to the hosts (vSAN 7.0 U2+); whether it eliminates or changes the circular failure path is not established here&lt;/td&gt;
&lt;td&gt;PRIMARY — vSAN 8.0 ADMIN GUIDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nutanix&lt;/td&gt;
&lt;td&gt;External KMS, SED&lt;/td&gt;
&lt;td&gt;After a full power-off and power-on, the CVM retrieves drive keys from the KMS; without the correct keys it cannot access the data&lt;/td&gt;
&lt;td&gt;PRIMARY — SED — 7.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nutanix&lt;/td&gt;
&lt;td&gt;External KMS, software-only&lt;/td&gt;
&lt;td&gt;Guide lists KMS access at cluster start, key regeneration, KMS type switch and NCC heartbeat, plus service start/restart and AOS upgrade&lt;/td&gt;
&lt;td&gt;PRIMARY — SOFTWARE — 7.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nutanix&lt;/td&gt;
&lt;td&gt;Native KMS, local&lt;/td&gt;
&lt;td&gt;Software-only; minimum 3 nodes, 1- and 2-node clusters not supported; keys must be backed up&lt;/td&gt;
&lt;td&gt;PRIMARY — 3-NODE — 7.6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nutanix&lt;/td&gt;
&lt;td&gt;Native KMS, remote&lt;/td&gt;
&lt;td&gt;Available only when the cluster is registered to Prism Central; retrieval mechanism not documented here&lt;/td&gt;
&lt;td&gt;PRIMARY — PRISM CENTRAL — 7.6&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;AOS 7.5+ also documents Prism Central-managed external KMIP for software-only encryption. After association, the cluster communicates directly with the KMS and Prism Central is not in the cluster-to-KMS data path (AOS Security 7.6, pp. 103–104). This is distinct from Native KMS (remote) and is not included as a separate configuration row here.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"If every host in this cluster powered off at once, which service has to answer before the first datastore mounts, and where does that service run?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What This Post Does Not Claim
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The SED power-cycle sentence is not generalized to software-only encryption. Software-only is covered by its own access-condition list.&lt;/li&gt;
&lt;li&gt;The Native KMS (remote) retrieval mechanism is not established. Prism Central registration is the documented dependency.&lt;/li&gt;
&lt;li&gt;Cloud KMS, which the 7.6 guide documents for Azure Key Vault only (p. 108), is not treated as equivalent to a KMS VM hosted on the cluster, and is not worked here.&lt;/li&gt;
&lt;li&gt;AOS 7.5+ Prism Central-managed external KMIP is distinct from Native KMS (remote).&lt;/li&gt;
&lt;li&gt;Whether a KMS circular dependency forms in a software-only Nutanix cluster is not claimed. The guide states the prohibition and the consequence only.&lt;/li&gt;
&lt;li&gt;vCenter-offline behavior on vSAN is not claimed.&lt;/li&gt;
&lt;li&gt;Whether TPM key persistence or Native Key Provider eliminates or changes the circular failure path is not claimed.&lt;/li&gt;
&lt;li&gt;Mount, discover, replicate, and validate are not claimed.&lt;/li&gt;
&lt;li&gt;No platform is ranked, and nothing here extends beyond the documented versions and configurations: vSAN 8.x and 9.x per Broadcom KB 453198, and Nutanix AOS Security 7.6 per the Nutanix Security Guide. The relevant Nutanix language is unchanged from the 6.8 guide.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://www.rack2cloud.com/audits/recovery-readiness-assessment/" rel="noopener noreferrer"&gt;Recovery Readiness Assessment&lt;/a&gt; — test your own recovery path against this failure mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;Online and readable are different states, and encrypted storage is where confusing them costs the most. Both vendors' primary documentation says the same thing about the key service: it does not belong on the storage it unlocks.&lt;/p&gt;

&lt;p&gt;The failure is not encryption by itself. It is a dependency nobody drew. In the configuration where a KMS circular dependency forms, the cluster that most needs the key service is the one that cannot start it. Broadcom documents that wait step by step. Nutanix documents the prohibition and the consequence and leaves the sequence unstated. A vendor that documents less has not been shown to fail differently.&lt;/p&gt;

&lt;p&gt;Configuration decides the outcome. Same platform, same encryption, one placement decision apart, and one cluster restarts while the other waits on itself. The review question is not whether encryption is enabled. It is where the key service runs when everything is off, who can restore it, and from what.&lt;/p&gt;

&lt;p&gt;A cluster that has come back has not recovered until it can read what it came back with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/virtualization-architecture/" rel="noopener noreferrer"&gt;Virtualization Architecture&lt;/a&gt; — the pillar hub for the hypervisor, control-plane, and storage platform decisions this unlock dependency sits inside&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/nutanix-vs-vmware-availability-authority/" rel="noopener noreferrer"&gt;Nutanix vs VMware: Availability vs Authority in the Post-Broadcom Datacenter (2026)&lt;/a&gt; — the earlier comparison whose Nutanix outcomes assume no key manager outside the cluster&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/two-node-edge-deployment/" rel="noopener noreferrer"&gt;Two Nodes Can Preserve Availability. They Can't Preserve N+1 Capacity.&lt;/a&gt; — the same availability-versus-capacity separation, applied to failure capacity instead of readability&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.vmware.com/en/VMware-vSphere/8.0/vsan-administration/GUID-37F9636A-7481-4486-AAA9-E0A1A49343A1.html" rel="noopener noreferrer"&gt;VMware vSAN 8.0 Administration Guide: data-at-rest encryption&lt;/a&gt; — the administration guide's encryption section: restart behavior, key persistence from vSAN 7.0 Update 3, and Native Key Provider&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://knowledge.broadcom.com/external/article/453198/recovering-encrypted-vsan-datastores-fro.html" rel="noopener noreferrer"&gt;Recovering Encrypted vSAN Datastores from KMS Circular Dependencies (Broadcom KB 453198)&lt;/a&gt; — the primary source for the vSAN circular mechanism and recovery constraints&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://portal.nutanix.com/page/documents/details?targetId=Nutanix-Security-Guide-v7_6:portal-full-page-view-html" rel="noopener noreferrer"&gt;Nutanix AOS Security 7.6 Security Guide&lt;/a&gt; — the primary source for the Nutanix external-KMS, Native KMS, and access-condition claims; page cites in this post follow the PDF edition&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/kms-circular-dependency-encrypted-storage/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>virtualization</category>
      <category>encryption</category>
      <category>nutanix</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Kubernetes Swap Turns an OOMKill Into a Latency Problem</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Wed, 07 Oct 2026 12:05:31 +0000</pubDate>
      <link>https://dev.to/ntctech/kubernetes-swap-turns-an-oomkill-into-a-latency-problem-1khn</link>
      <guid>https://dev.to/ntctech/kubernetes-swap-turns-an-oomkill-into-a-latency-problem-1khn</guid>
      <description>&lt;p&gt;Kubernetes swap changes what memory pressure does to a pod: a workload that would have been OOMKilled can remain alive and run slowly instead. That sounds like a pure improvement until you look at what decides which pods get that treatment. Under &lt;code&gt;LimitedSwap&lt;/code&gt;, the kubelet and container runtime use the container's memory request when determining its swap allowance. The scheduler uses the same field for placement and does not account for swap.&lt;/p&gt;

&lt;p&gt;This post covers one configuration and stays inside it: cgroup v2 nodes running &lt;code&gt;LimitedSwap&lt;/code&gt;, and the pods that mode allows to use swap. It extends the model in &lt;a href="https://www.rack2cloud.com/kubernetes-resource-requests-vs-limits/" rel="noopener noreferrer"&gt;Kubernetes Requests vs Limits&lt;/a&gt; rather than replacing it. That model still describes the default node. This is what changes when you turn swap on.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07q7w7afkaibrxdhzn6y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07q7w7afkaibrxdhzn6y.jpg" alt="kubernetes swap memory request forks into scheduler placement and a swap allowance on the container cgroup" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;One number, two jobs: the memory request places the pod and sizes its swap allowance.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes Swap Is Off by Default, and Opt-In Per Node
&lt;/h2&gt;

&lt;p&gt;On a default Kubernetes node, workloads cannot use swap. The kubelet refuses to start on a node with swap enabled unless you set &lt;code&gt;failSwapOn: false&lt;/code&gt;, and even then it tells the container runtime to allocate zero swap to workloads. Letting pods use it is a separate, explicit choice: set &lt;code&gt;memorySwap.swapBehavior&lt;/code&gt; to &lt;code&gt;LimitedSwap&lt;/code&gt; in the kubelet configuration, as described in the &lt;a href="https://kubernetes.io/docs/concepts/cluster-administration/swap-memory-management/" rel="noopener noreferrer"&gt;Kubernetes swap documentation&lt;/a&gt;. Different nodes can use different behaviors, which makes this a node pool decision, and each node reports its swap capacity in its status, so you can see which pools have swap provisioned. It sits in the platform layer of &lt;a href="https://www.rack2cloud.com/modern-infrastructure-iac-strategy-guide/" rel="noopener noreferrer"&gt;modern infrastructure architecture&lt;/a&gt; and is felt by every team whose pods land there.&lt;/p&gt;

&lt;p&gt;The mechanics matter for what follows. The kubelet does not enforce swap itself. It directs the container runtime to apply the setting, and on cgroup v2 that setting is &lt;code&gt;memory.swap.max&lt;/code&gt; on the container's cgroup. On cgroup v1, Kubernetes workloads are not allowed to use swap at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scope of this post:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Covered:&lt;/strong&gt; cgroup v2 nodes running LimitedSwap, non-high-priority Burstable pods, the request-derived swap allowance, and the shift from OOMKill to latency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not covered:&lt;/strong&gt; eviction interaction, swap-aware scheduling, benchmark or density numbers, and which release moved the feature to which stage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Basis:&lt;/strong&gt; behavior as documented on kubernetes.io and in KEP-2400. Nothing here was measured.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Memory Request Becomes the Swap Entitlement
&lt;/h2&gt;

&lt;p&gt;The requests-vs-limits model treats the memory request as a scheduling signal. The scheduler adds it to a node's accounting ledger and places the pod. Under &lt;code&gt;LimitedSwap&lt;/code&gt; the same number gets a second job. The amount of swap a container may use is proportional to its memory request, the node's physical memory, and the total swap available to pods on that node. Raise the request and the allowance grows with it. Lower it and the allowance shrinks.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Consumer&lt;/th&gt;
&lt;th&gt;What it does with the memory request&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;kube-scheduler&lt;/td&gt;
&lt;td&gt;Places the pod on a node with enough unreserved memory in its accounting. Does not account for swap.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;kubelet and container runtime&lt;/td&gt;
&lt;td&gt;Derive the container's swap allowance from the request and apply it to the container's cgroup.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Per the Kubernetes documentation, the scheduler does not currently account for swap usage, and the docs name that as a factor that heightens noisy-neighbor risk. A node can be packed on requests alone while its pods compete for the same swap device. Kubernetes swap gives the same request a second runtime consequence: where a pod lands is still one decision, but the request also helps determine how much swap the container may use when memory runs short.&lt;/p&gt;

&lt;h2&gt;
  
  
  An OOMKill Is Loud. Swap Is Quiet.
&lt;/h2&gt;

&lt;p&gt;On a default node, a container that hits its memory limit is killed by the OOM killer, the pod reports OOMKilled, and the restart counter moves. It is an event, and most monitoring is built around events.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcruqwotx3fcp0iu6rvry.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcruqwotx3fcp0iu6rvry.jpg" alt="Two failure paths from memory pressure on a Kubernetes node: OOMKill on a default node, possibly slow but running with swap" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;An OOMKill is an event. Swap pressure can leave a pod running with no event attached.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Swap changes the ending. The Kubernetes documentation says swap can help prevent pods from being terminated during memory pressure spikes. The same page says that having swap available reduces predictability, that swapping data back into memory can be slower by many orders of magnitude, and that swap changes a system's behavior under memory pressure. Both statements describe one mechanism. The pod that survives may now be waiting on a much slower storage path.&lt;/p&gt;

&lt;p&gt;How slow depends on the storage behind the swap. The docs state that performance on a node with swap depends on the underlying physical storage, and is significantly worse in an IOPS-constrained environment, such as a cloud VM with I/O throttling, than on SSD or NVMe. The pod is the same either way. The outcome depends on a device it has no say in.&lt;/p&gt;

&lt;p&gt;Swap also changes who pays. The docs warn that enabling it increases noisy-neighbor risk, because pods that use their RAM frequently can cause other pods to swap. Kubernetes swap can turn a pod-level memory-pressure event into contention for a shared node storage resource.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;A silent failure mode:&lt;/strong&gt; A pod that would have been OOMKilled may now be alive and slow. If your alerting keys on OOMKilled status and restart counts, swap removes the signal without removing the problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The signals move to places most dashboards do not look. The kubelet exposes &lt;code&gt;container_swap_usage_bytes&lt;/code&gt; and &lt;code&gt;container_swap_limit_bytes&lt;/code&gt; on its resource metrics endpoint, and &lt;code&gt;kubectl top pod --show-swap&lt;/code&gt; reports per-pod swap use. None of that appears in pod status the way an OOMKill does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Gets Swap, and How Much
&lt;/h2&gt;

&lt;p&gt;Eligibility for Kubernetes swap is narrower than "pods on a swap-enabled node." Under &lt;code&gt;LimitedSwap&lt;/code&gt;, only non-high-priority pods in the Burstable QoS class may use swap, and BestEffort and Guaranteed pods are prohibited, according to the &lt;a href="https://kubernetes.io/blog/2025/03/25/swap-linux-improvements/" rel="noopener noreferrer"&gt;Kubernetes 1.32 swap post&lt;/a&gt;. KEP-2400 scopes the feature to Burstable pods.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pod class&lt;/th&gt;
&lt;th&gt;Swap under LimitedSwap&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Guaranteed&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BestEffort&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Burstable, high priority&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Burstable, other&lt;/td&gt;
&lt;td&gt;Proportional to the memory request&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffv5ueb67ullccmnt3o3h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffv5ueb67ullccmnt3o3h.jpg" alt="LimitedSwap eligibility by pod class: Guaranteed, BestEffort and high-priority Burstable pods get no swap" width="800" height="447"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Eligibility under LimitedSwap is narrower than pods on a swap-enabled node.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The documentation decides what counts as high priority, so check it for the version you run. There is also a built-in opt-out: a container in a Burstable pod whose memory request equals its memory limit gets no swap. Request sizing is now a swap decision as well as a scheduling decision.&lt;/p&gt;

&lt;p&gt;That creates a tension the default requests-vs-limits model does not capture. Sizing requests from steady-state usage is sound for placement. Under &lt;code&gt;LimitedSwap&lt;/code&gt; it also means a container with a modest request gets a modest allowance, however spiky its peaks. Anything that sets the memory request is now also setting the potential swap allowance, whether that request comes from a chart default or an autoscaler's recommendation covered in &lt;a href="https://www.rack2cloud.com/vpa-vs-hpa-kubernetes/" rel="noopener noreferrer"&gt;VPA vs HPA&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Enable It: One Question and Four Checks
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Diagnostic:&lt;/strong&gt; &lt;em&gt;"For this workload, is a slowdown on a device I am not monitoring better than a restart I would have seen?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is yes for a class of workload, swap is a reasonable tool for it. If the answer is no, setting the request equal to the limit opts the container out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before enabling LimitedSwap:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Confirm the node pool runs cgroup v2.&lt;/strong&gt; On cgroup v1, workloads cannot use swap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decide which workloads may page.&lt;/strong&gt; The request sets the allowance, high-priority pods are excluded, and request equal to limit opts a container out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Move alerting beyond OOMKilled.&lt;/strong&gt; Watch container swap usage against its limit, and per-pod swap in kubectl top.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check what backs the swap.&lt;/strong&gt; The docs tie performance to the storage underneath, single out IOPS-constrained environments as the worst case, and strongly encourage encrypting the swap space.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing here argues against swap. Kubernetes swap is a reasonable tool when the trade is chosen deliberately. What it argues against is enabling it as a node setting and leaving requests and alerts exactly where they were. The scheduler will keep placing pods using requests, while the kubelet and container runtime apply the swap allowances derived from those requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;Kubernetes swap does not soften a memory limit. It changes the failure path available to a memory-pressured pod, and the memory request helps determine how much swap the container may use.&lt;/p&gt;

&lt;p&gt;The real problem is that two long-standing habits stop lining up. Teams commonly size requests for the scheduler and alert on the OOMKill. Under &lt;code&gt;LimitedSwap&lt;/code&gt; the request also helps set a swap allowance that the scheduler does not account for, and the kill can become a slowdown that no restart counter records. Neither change is a bug. Both are documented. The risk is enabling swap as a node setting without revisiting what requests mean and what alerts watch.&lt;/p&gt;

&lt;p&gt;An OOMKill announces itself. Swap fails quietly, and only the teams that chose to measure it will notice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/modern-infrastructure-iac-strategy-guide/" rel="noopener noreferrer"&gt;Modern Infrastructure &amp;amp; IaC Architecture&lt;/a&gt; — the pillar hub for platform-layer decisions like node configuration and runtime behavior&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/kubernetes-resource-requests-vs-limits/" rel="noopener noreferrer"&gt;Kubernetes Requests vs Limits&lt;/a&gt; — the scheduler-and-kernel model this post extends, including QoS classes and default OOM behavior&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/vpa-vs-hpa-kubernetes/" rel="noopener noreferrer"&gt;VPA vs HPA: Why Most Teams Choose the Wrong Autoscaler&lt;/a&gt; — how autoscalers change requests, which now also change swap allowances&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/docs/concepts/cluster-administration/swap-memory-management/" rel="noopener noreferrer"&gt;Kubernetes Documentation: Swap memory management&lt;/a&gt; — official reference for NoSwap, LimitedSwap, metrics and the documented risks&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://kubernetes.io/blog/2025/03/25/swap-linux-improvements/" rel="noopener noreferrer"&gt;Kubernetes 1.32: Fresh Swap Features for Linux Users&lt;/a&gt; — eligibility rules, the request-proportional allowance and the request-equals-limit opt-out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/kubernetes-swap-memory-request/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>A Completeness Gate Is Only as Complete as Its Required Set. Don't Let the Model Write It.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Mon, 05 Oct 2026 12:13:51 +0000</pubDate>
      <link>https://dev.to/ntctech/a-completeness-gate-is-only-as-complete-as-its-required-set-dont-let-the-model-write-it-3186</link>
      <guid>https://dev.to/ntctech/a-completeness-gate-is-only-as-complete-as-its-required-set-dont-let-the-model-write-it-3186</guid>
      <description>&lt;p&gt;A completeness gate has two different problems: determining what must exist, and determining whether it exists. We keep treating them as one.&lt;/p&gt;

&lt;p&gt;One common design hands both to the same model. A generated change plan, policy bundle or control mapping goes in, the model is asked whether anything required is missing, and it answers against its own idea of what "required" means. If it reports nothing missing, the gate passes. Nothing alerts, because nothing failed. The check ran correctly against a list that was already short.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxuqulaq1nekxwfkzs0tk.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxuqulaq1nekxwfkzs0tk.jpg" alt="completeness gate — required set enumerated by code versus listed by a model" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Every Completeness Gate Solves Two Problems
&lt;/h2&gt;

&lt;p&gt;The first problem is enumeration: which elements must be present? The second is comparison: is each of them present in this artifact? Any gate that checks a deployment plan against a control catalogue, or a generated policy against the clauses a standard requires, does both, whether or not the design separates them. Wherever model-generated plans, policies or change requests pass through a gate like this, it belongs to &lt;a href="https://www.rack2cloud.com/ai-infrastructure-strategy-guide/" rel="noopener noreferrer"&gt;AI infrastructure architecture&lt;/a&gt; as much as to the pipeline that hosts it.&lt;/p&gt;

&lt;p&gt;Comparison is a membership question, and it can only report on elements the required set contains. Enumeration decides the ceiling. A flawless comparison against an incomplete set returns a clean result for an incomplete artifact.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Job&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;How it fails&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Enumerate the required set&lt;/td&gt;
&lt;td&gt;What must exist?&lt;/td&gt;
&lt;td&gt;Required elements are missing from the set, so the gate under-rejects. Requirements the specification never states are added, so it over-rejects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compare artifact to set&lt;/td&gt;
&lt;td&gt;Is each required element present?&lt;/td&gt;
&lt;td&gt;A required element is in the set and absent from the artifact, and the comparison does not report it.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The two enumeration failures behave differently under review. An invented requirement is written down, so a reviewer can challenge it. A missing requirement is an absence, and finding it is the same problem the author failed to solve. The research below argues this asymmetry, and it is why a model-written list can survive inspection and still be short.&lt;/p&gt;

&lt;p&gt;A check that reports success while the objective went unmet already has a name on this site, &lt;a href="https://www.rack2cloud.com/ai-placement-latency-cost-tradeoff/" rel="noopener noreferrer"&gt;False Completion (#82)&lt;/a&gt;, and the cost of continuing to verify automated output is the subject of the &lt;a href="https://www.rack2cloud.com/automation-validation-tax/" rel="noopener noreferrer"&gt;Automation Validation Tax (#172)&lt;/a&gt;. This post is narrower than either: it is about how the set a gate checks against gets built. How an approval step decays into a rubber stamp is covered in &lt;a href="https://www.rack2cloud.com/ai-approval-integrity/" rel="noopener noreferrer"&gt;GhostApproval&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Evidence Shows, and Where It Stops
&lt;/h2&gt;

&lt;p&gt;Two pieces of research bear on how a completeness gate should be built, and neither is about infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://arxiv.org/abs/2506.11440" rel="noopener noreferrer"&gt;AbsenceBench&lt;/a&gt; gives a model an original document and an edited copy and asks which elements were removed. On its GitHub pull-request portion, 14 models scored between 17.3 and 40.0 percent F1 across their configurations, with the best at 40.0, even though the authors note that a simple program solves the task in linear time. The models are mid-2025 generation, the omissions are literal deleted lines, and the paper reports no error bars.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://arxiv.org/abs/2608.01000" rel="noopener noreferrer"&gt;Judging Is Not Enumerating&lt;/a&gt; measures models as authors of the sets that other systems check against: test suites, answer keys, rubrics. It tests four separate reference constructions, and in each the models judged whether a candidate belongs far better than they authored the set itself. The size of the gap depends on the construction. On the paper's algorithmic construction it was about 0.29 to 0.34 F1 and did not close across a 24-fold range of model sizes. On executable code, models that judged at F1 0.74 to 0.90 wrote test suites that admitted only 19 to 42 percent of the correct solutions. In a separate test, planted over-inclusions were detected six to seven times more often than planted omissions. A control then located the deficit: asked to emit the predicate rather than list its members, the same models reached an F1 of about 0.99. In that control the rule was already in the prompt, so the model was restating a rule, not deriving one.&lt;/p&gt;

&lt;p&gt;The authors scope the finding to one-shot authoring without test-time reasoning. Enabling reasoning on two closed frontier models closed or nearly closed the gap on the simplest, rule-based construction. It did not reliably repair test-suite authoring, where the expected behavior has to be derived from prose. The paper's one production observation is a K-12 assessment pipeline of 43,227 scored items, where errors in model-authored answer keys were omissions rather than inclusions by about ten to one, as graded by a commercial evaluator.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠ &lt;strong&gt;What this evidence does not show:&lt;/strong&gt; It does not show that current models cannot do this: reasoning narrowed or closed the gap where a rule could be executed. It does not test semantic absence, because AbsenceBench removes literal lines. And it contains no infrastructure incident. Applying it to plans, policies and change requests is an architectural extrapolation from benchmark and research results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fps0bml43dc6aeup43e5i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fps0bml43dc6aeup43e5i.jpg" alt="three interfaces to the same model — judge one item, write the rule, list the whole set — with the list interface drawn truncated" width="799" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Restate the Rule. Enumerate in Code.
&lt;/h2&gt;

&lt;p&gt;The completeness gate architecture that follows separates the two jobs and gives each to the component that does it reliably. The model may translate a rule that has already been specified into an executable predicate. Code then runs that predicate against an authoritative, machine-readable source to enumerate the required set. A deterministic diff compares the artifact to that set, and the gate reports the missing elements by name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn31sbwsn072saotqfow0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn31sbwsn072saotqfow0.jpg" alt="completeness gate pipeline — model proposes the predicate, code enumerates from the source, a diff names the gaps, and the model-to-required-set path is blocked" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Who does it&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Specify the rule&lt;/td&gt;
&lt;td&gt;A person or a standard&lt;/td&gt;
&lt;td&gt;The rule exists before the gate does&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Translate it to a predicate&lt;/td&gt;
&lt;td&gt;The model, with the result reviewed&lt;/td&gt;
&lt;td&gt;Restating a given rule is the task the research control shows models doing well&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enumerate the required set&lt;/td&gt;
&lt;td&gt;Code, from the source&lt;/td&gt;
&lt;td&gt;The result is reproducible and adds no probabilistic step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compare artifact to set&lt;/td&gt;
&lt;td&gt;A deterministic diff&lt;/td&gt;
&lt;td&gt;Set difference is a mechanical operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Report&lt;/td&gt;
&lt;td&gt;The gate&lt;/td&gt;
&lt;td&gt;Each missing element is named&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Specify, translate, enumerate, diff: the model touches only the second step. It participates in expressing the rule. It does not become the database of what must exist.&lt;/p&gt;

&lt;p&gt;When the predicate and the source are correct, deterministic enumeration gives a reproducible result without introducing another probabilistic judgment step. That is the whole argument, and it is about cost and verifiability, not about what models are capable of. A model can still propose predicates, and a reasoning model may enumerate acceptably in simple cases. The design should not make model enumeration the authoritative source of the required set when the set can be derived deterministically from an authoritative machine-readable source. Infrastructure already uses versions of this separation: &lt;a href="https://www.rack2cloud.com/deterministic-iac-terraform-policy-as-code/" rel="noopener noreferrer"&gt;policy-as-code evaluates machine-readable Terraform plans&lt;/a&gt; against explicit rules rather than asking a model to invent the required checks at evaluation time.&lt;/p&gt;

&lt;p&gt;Four design properties keep the split intact in any completeness gate.&lt;/p&gt;

&lt;h3&gt;
  
  
  01 — Source-derivable set
&lt;/h3&gt;

&lt;p&gt;The required set must be computable from something that exists outside the model: an inventory, a schema, a control catalogue, a plan diff. If no such source exists, there is nothing for code to enumerate, and the gate cannot claim completeness.&lt;/p&gt;

&lt;h3&gt;
  
  
  02 — Reviewable predicate
&lt;/h3&gt;

&lt;p&gt;The model's output is a predicate a person can read, test and version. A wrong predicate is visible text, while an omission from a model-written list is not. That visibility is this post's inference from the research finding that over-inclusions are easier to catch than omissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  03 — Deterministic enumeration
&lt;/h3&gt;

&lt;p&gt;Enumeration runs as code against the source and produces the same set on every run. Where a reasoning model enumerates instead, treat its output as a proposal to diff against the code-derived set, not as the set itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  04 — Over-rejection control
&lt;/h3&gt;

&lt;p&gt;A predicate that encodes a requirement the specification never stated blocks valid work. Trace every predicate to a clause in the specification, and review rejections as seriously as passes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Stops Working
&lt;/h2&gt;

&lt;p&gt;A completeness gate built this way works where the required set can be derived from a machine-readable source. Plenty of requirements cannot be derived that way. "The runbook should cover failure of the identity provider" and "the change should consider downstream consumers" have no computable predicate, and nothing here says how to gate them. Nor does the evidence: AbsenceBench removes literal lines, and the research controls use rules a model was given. For requirements stated only in prose, a model-derived set may be the only practical option. In that case the gate is no longer proving completeness against a deterministic required set. It is performing a model-mediated review, its omissions stay hard to see, and its output should say so, so that a pass is read as weaker evidence.&lt;/p&gt;

&lt;p&gt;Two neighboring questions are out of scope here. Who is entitled to reject a gate's conclusion is a separate authority question, covered for recovery claims in &lt;a href="https://www.rack2cloud.com/recovery-evidence-boundary/" rel="noopener noreferrer"&gt;Recovery Evidence Boundary&lt;/a&gt; and for AI platform evidence in &lt;a href="https://www.rack2cloud.com/ai-evidence-verification/" rel="noopener noreferrer"&gt;AI evidence verification&lt;/a&gt;; it does not depend on how the required set was built. And a probe reports on what it probes, which is the limit &lt;a href="https://www.rack2cloud.com/kubernetes-health-checks-actually-guarantee/" rel="noopener noreferrer"&gt;What Kubernetes Health Checks Actually Guarantee&lt;/a&gt; covers for readiness and liveness checks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the Gate, Not Just the Artifact
&lt;/h2&gt;

&lt;p&gt;A completeness gate is itself a system that can be wrong, so test it with artifacts whose contents you already know. Run a known-complete artifact through and confirm it passes. Run one with a deliberately removed element and confirm the gate names it. If the gate cannot find a planted omission, its clean results carry no information. A fixed answer set defined before the run is the same move &lt;a href="https://www.rack2cloud.com/ai-workload-rpo/" rel="noopener noreferrer"&gt;AI workload RPO&lt;/a&gt; makes for restore tests.&lt;/p&gt;

&lt;p&gt;The research points the same direction. Its one mitigation that worked for authored code test suites was discarding any suite that rejected a known-correct probe, which cut false rejection from 58 to 92 percent down to 5 percent or less, at the cost of keeping only 5 to 39 percent of suites. A planted-omission test is the mirror image, and it is cheap to run on every change to the predicate or the source.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;A completeness gate can only report on what its required set contains. If a model wrote that set in one pass, the gate inherits the model's omissions and returns clean results for incomplete artifacts.&lt;/p&gt;

&lt;p&gt;The mistake is treating enumeration and comparison as one job. The research shows that judging membership and enumerating requirements are different tasks, and that model performance can diverge sharply between them. Where a rule exists, let the model translate the rule and let code do the listing. Reasoning narrows the gap in simple cases and does not reliably close it elsewhere, so the design should not depend on it.&lt;/p&gt;

&lt;p&gt;Where the required set can be derived from an authoritative source, derive it. Where it cannot, say that the gate checked a model-derived list. Either way, a gate that has never found a planted omission has not shown it can find a real one.&lt;/p&gt;

&lt;p&gt;A completeness gate is only as complete as the set it checks against.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/completeness-gate-required-set/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>infrastructure</category>
      <category>cloud</category>
    </item>
    <item>
      <title>The Ransomware Takedown Closed the Actor's Infrastructure. It Didn't Close Your Exposure.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Sat, 03 Oct 2026 12:07:15 +0000</pubDate>
      <link>https://dev.to/ntctech/the-ransomware-takedown-closed-the-actors-infrastructure-it-didnt-close-your-exposure-1mcp</link>
      <guid>https://dev.to/ntctech/the-ransomware-takedown-closed-the-actors-infrastructure-it-didnt-close-your-exposure-1mcp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5r194oynejlcxqiuo1og.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5r194oynejlcxqiuo1og.jpg" alt="Field Notes — Engineering Notes from the Complexity Gap | Rack2Cloud" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A ransomware takedown changes what an attacker can do next; it does not tell a victim what was taken, who holds copies, or whether its exposure is closed.&lt;/p&gt;

&lt;p&gt;On 30 September 2026, law enforcement took control of the KillSec leak site and secured at least 110 terabytes of stolen data against further unauthorised access, &lt;a href="https://www.europol.europa.eu/media-press/newsroom/news/teenager-suspected-of-leading-killsec-ransomware-group-law-enforcement-seizes-servers-and-leak-site" rel="noopener noreferrer"&gt;according to Europol&lt;/a&gt;. &lt;a href="https://www.eurojust.europa.eu/news/teenagers-suspected-leading-ransomware-group-arrested-during-international-operation" rel="noopener noreferrer"&gt;Eurojust&lt;/a&gt; coordinated authorities from nine countries and reports three arrests, eight house searches, and five seized servers the group used to store victim data. It describes a group responsible for almost 1,000 attacks. That is a real result. It is also a result about the actor.&lt;/p&gt;

&lt;p&gt;This note is about the other side of that sentence: what a victim can establish afterward, and what no press release can establish for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu200bndwmu6cca8xabfz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu200bndwmu6cca8xabfz.jpg" alt="ransomware takedown — seized actor infrastructure on one side, unevidenced victim exposure on the other" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Ransomware Takedown Changes, and What It Doesn't
&lt;/h2&gt;

&lt;p&gt;A ransomware takedown that seizes a leak site and the servers behind it does real work. The actor can no longer publish through that site, at least 110 terabytes of stolen data has been secured, and investigators have evidence to analyse. Those are changes in the actor's capability and in the investigators' position. None of them touches the victim's state: what was taken, how much, where copies sit, who has seen them. Those facts were set by what happened before the seizure, and the seizure does not reach back to them.&lt;/p&gt;

&lt;p&gt;Recovery closure already has a model, the &lt;a href="https://www.rack2cloud.com/incident-recovery-process/" rel="noopener noreferrer"&gt;incident recovery process&lt;/a&gt;, and this note does not revisit it. That model asks whether the restored environment can be trusted again. It does not ask what left the environment first, and that question arrives with neither the restore nor the seizure notice. A victim can hold a clean closure record for the environment and an open, unevidenced question about the data, in the same incident.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://www.rack2cloud.com/data-protection-architecture-strategy-guide/" rel="noopener noreferrer"&gt;data protection architecture&lt;/a&gt;, the unit of concern is the data and where it went, not the actor's current operating status. Treat a ransomware takedown as an intelligence event on your side of the incident. It is new information about the actor. It is not a state change in your exposure record. Treating it as one substitutes the actor's status for evidence about your own data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Non-Payer Path Was Already Open
&lt;/h2&gt;

&lt;p&gt;Eurojust's account of the group's method is specific. KillSec got into organisations through poorly secured access points, particularly those linked to cloud storage, and copied the data to infrastructure it controlled. It then threatened to publish. Victims were sent samples as proof of possession. If a victim did not pay, the files were made available for free download. In some cases the group received substantial payments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yh19gzzb9bermxzhwju.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1yh19gzzb9bermxzhwju.jpg" alt="ransomware takedown sequence — files made available for download before the seizure, copies unknown" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read that as a sequence and the seizure sits at the end of it. For organisations that refused, release was the group's standard practice before 30 September. The seizure removes the leak site. It does not recall a file that was already downloadable, and neither the Eurojust release nor Europol's headline says anything about copies that left the group's infrastructure. Whether a particular victim's files were released, or downloaded by anyone, is not something either source states.&lt;/p&gt;

&lt;p&gt;One artifact from that sequence does sit with the victim: the proof-of-possession samples. If your incident record holds them, they are direct evidence that the actor held specific files, which makes them the firmest anchor for scope you will have. They bound the scope from below, not from above. A sample shows that something was taken. It does not show that nothing else was.&lt;/p&gt;

&lt;p&gt;Whether to pay is a separate decision with its own constraints, covered in &lt;a href="https://www.rack2cloud.com/ransom-payment-ban-recovery-dependency/" rel="noopener noreferrer"&gt;the payment-ban dependency post&lt;/a&gt;. The point here is narrower. Whatever a payer was promised came from the actor, and whatever a refuser faced was the actor's publication practice. Neither is evidence the victim holds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Victim List Is Still Being Written
&lt;/h2&gt;

&lt;p&gt;Eurojust says the next phase is examining the seized devices and data and tracing the financial proceeds, and that this evidence may help identify other victims, attacks and people involved. That sentence cuts two ways. The investigators' victim list is not complete. And the evidence that completes it is the same corpus a victim would want answers from.&lt;/p&gt;

&lt;p&gt;An organisation can therefore be a KillSec victim today without knowing it, and learn so later from an authority rather than from its own telemetry. The Eurojust release does not describe how victims get told. Plan for a notification that arrives after your own incident record was closed, from outside your own timeline. The size figure is a floor on what investigators secured, not a measurement of what any individual victim lost.&lt;/p&gt;

&lt;p&gt;The entry point matters here. Eurojust describes access through poorly secured access points, particularly those linked to cloud storage. If that describes your environment, the records that show what was read or copied may sit with the storage platform rather than on your network, and how long they are retained is a setting chosen long before the incident. By the time an authority makes contact after a ransomware takedown, the evidence that would have answered the question may already have aged out.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fihg1zn02y3g8v6pfzici.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fihg1zn02y3g8v6pfzici.jpg" alt="evidence a victim can establish after a ransomware takedown versus facts outside its reach" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a Victim Can and Cannot Verify After a Ransomware Takedown
&lt;/h2&gt;

&lt;p&gt;The question after a takedown is practical: what can this organisation put evidence behind? Two short lists.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can establish:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;External communications&lt;/strong&gt; — which systems communicated externally during the intrusion window, from flow or egress records held outside anything the intruder could write to&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reachable data stores&lt;/strong&gt; — which repositories held data the compromised access could reach, from your own data-store inventory checked against that access scope&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identification as a victim&lt;/strong&gt; — whether law enforcement or the actor has identified your organisation as a victim&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defined scope&lt;/strong&gt; — whether the evidence you hold supports a defined exfiltration scope, or only fails to rule one out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cannot establish:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Downloads&lt;/strong&gt; — who else downloaded copies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Affiliate copies&lt;/strong&gt; — whether affiliates retained copies of the data they helped take&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redistribution&lt;/strong&gt; — whether files released before the seizure were redistributed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seizure completeness&lt;/strong&gt; — whether the data secured in the seizure is all of what was taken&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fourth item on the first list carries the most weight, and it is the easiest to get wrong. Evidence that supports a defined scope is positive: records showing what left and where it went. Records that merely fail to show a transfer rule nothing out unless you know the logging would have captured it. A gap in the logs is not a finding of no exfiltration.&lt;/p&gt;

&lt;p&gt;The first list depends on evidence collected before and during the incident, and on whether that evidence can be trusted. Records written by infrastructure an intruder could reach are weak proof of anything; &lt;a href="https://www.rack2cloud.com/evidence-layer-trust-boundary/" rel="noopener noreferrer"&gt;the evidence-layer trust boundary&lt;/a&gt; covers why a copy of evidence counts as independent only if the attacker cannot exercise the same authority over the original and the copy. The second list cannot be built from anything the victim holds. It sits with the actor, the affiliates, and whoever downloaded. Some of it may narrow if investigators later share what the seized systems show. Nothing in the Eurojust release says they will.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;The ransomware takedown closed the actor's infrastructure. It did not close the victim's exposure, and it is not evidence about it. Two different things came out in the same press release.&lt;/p&gt;

&lt;p&gt;What a takedown leaves behind is a verification problem. Exposure closure requires exfiltration-scope evidence, not attacker status. A victim holding that evidence can establish a scope. The rest of the question, who holds copies, was outside what any victim could verify before the seizure and remains outside it after.&lt;/p&gt;

&lt;p&gt;Do not read an actor's defeat as your own closure. The actor's status is public record. Your exposure is whatever your evidence can account for.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/ransomware-takedown-data-exposure/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>cybersecurity</category>
      <category>ransomware</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Rotating Credentials Is Not Revoking Them. The Revocation Unit Decides Whether You Can.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:03:12 +0000</pubDate>
      <link>https://dev.to/ntctech/rotating-credentials-is-not-revoking-them-the-revocation-unit-decides-whether-you-can-1c5o</link>
      <guid>https://dev.to/ntctech/rotating-credentials-is-not-revoking-them-the-revocation-unit-decides-whether-you-can-1c5o</guid>
      <description>&lt;p&gt;The revocation unit decides whether credential rotation can ever be atomic. It is the scope one revoke action removes: a token, an identity, or a trust root. Most teams treat rotation and revocation as one operation. They aren't. Rotation issues new secrets. Revocation removes the authority of everything that could have used the old ones, and it works only if the architecture can name that set and remove it in a single step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvkaewc6rg18zrjq5y9y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvkaewc6rg18zrjq5y9y.jpg" alt="revocation unit nested boundary diagram — token, identity and trust root scopes with a surviving credential still reaching a replacement secret" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rack2cloud.com/persistent-access-survives-fix/" rel="noopener noreferrer"&gt;The Server Was Fixed. Persistent Access Wasn't.&lt;/a&gt; covered what survives when remediation never reaches the layer where persistence lives. This post covers a layer remediation did reach: the credential layer itself, where a rotation can complete on schedule and still leave a surviving credential able to read whatever replaced the old one. The decision question is different. It is not which layers recovery has to validate, but what unit revocation acts on.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Revocation Unit Is an Architecture Decision
&lt;/h2&gt;

&lt;p&gt;Before any incident, the architecture has already answered a question, usually by default: when you revoke, what exactly are you revoking?&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Revocation unit&lt;/th&gt;
&lt;th&gt;One revoke action removes&lt;/th&gt;
&lt;th&gt;What may remain outside the unit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Token&lt;/td&gt;
&lt;td&gt;A single bearer credential&lt;/td&gt;
&lt;td&gt;Other tokens the same identity can mint, and any secret that token could read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Identity&lt;/td&gt;
&lt;td&gt;Every credential issued to one principal&lt;/td&gt;
&lt;td&gt;Static secrets that principal already read and copied elsewhere&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust root&lt;/td&gt;
&lt;td&gt;Everything that chains to one issuer or signing key&lt;/td&gt;
&lt;td&gt;Any credential that was never issued through that root&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That answer belongs in &lt;a href="https://www.rack2cloud.com/data-protection-architecture-strategy-guide/" rel="noopener noreferrer"&gt;data protection architecture&lt;/a&gt;, not in the incident runbook. A runbook can only sequence actions the architecture permits, and the revocation unit fixes what any single action is capable of removing before anyone is in the room.&lt;/p&gt;

&lt;p&gt;A token-level unit is precise and narrow. An identity-level unit is wider but stops at the principal's boundary. A trust-root unit can be the broadest, if the affected authority chains through that root, and it only reaches what was issued through it. None of the three is wrong. The decision is whether the unit you chose can enclose the set you will need to remove.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reachability: What the Revocation Unit Has to Enclose
&lt;/h2&gt;

&lt;p&gt;That set is the reachability graph: every credential that can read, write, or mint any secret in the affected set, followed transitively. A token that can read a vault path holding a signing key that can mint further tokens is in the graph, and so is everything those tokens can reach in turn.&lt;/p&gt;

&lt;p&gt;Revocation is complete only if the unit encloses the full closure of that graph. Anything left outside is a survivor, and a survivor with read access to the store holding the replacement secrets can simply collect them.&lt;/p&gt;

&lt;p&gt;Reachability is a graph property, not a list. It grows with every integration, every shared service account, every pipeline granted a convenient scope, and it is recorded nowhere unless the architecture is built to record it.&lt;/p&gt;

&lt;p&gt;The usual response is to rotate everything. That does not escape the problem, it relocates it. The mechanism doing the rotating holds credentials of its own, and those are in the graph too. A rotation job that can write to every store can also be read through, impersonated, or replayed, so the revocation unit has to enclose the rotator as well as the secrets it rotates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkshq6l46t5bnf6f8c7g9.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkshq6l46t5bnf6f8c7g9.jpg" alt="credential reachability graph — a revocation boundary enclosing one token while surviving credentials still reach replacement secrets" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Atomicity: Why Rotation Opens a Window
&lt;/h2&gt;

&lt;p&gt;Atomic revocation means that at one instant, no credential in the closure remains valid except those deliberately reissued. If the revocation unit is smaller than the closure, revocation stops being an operation and becomes a sequence: kill this token, rotate that secret, then the next. A sequence has a window.&lt;/p&gt;

&lt;p&gt;A generic sequence shows the shape. A pipeline token can read a shared store. Responders revoke that token, then rotate the database password, then the signing key. Another token issued to the same service account was never in the revocation unit, so it is still valid. It reads the new database password the moment it is written, and the signing key after it. Every step in the sequence succeeded, and the closure still leaked.&lt;/p&gt;

&lt;p&gt;Inside that window, the failure mode is replacement-secret exposure. Rotation writes fresh, valid, high-value material into a store that surviving credentials can still read. The rotation does not just fail to lock the attacker out. It hands them the new keys. The defenders see a completed rotation and a dead old secret, while the party holding a surviving credential holds a valid replacement.&lt;/p&gt;

&lt;p&gt;Atomic at the unit is not instantaneous at every verifier. Cached validations, token lifetimes and propagation delay leave a residual window even under a trust-root revocation. The design property is not zero. It is a window that is bounded and known in advance, rather than one discovered afterward from logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzicjebshq8pdhew9ik8k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzicjebshq8pdhew9ik8k.jpg" alt="non-atomic revocation window — replacement secret written while an unenumerated credential retains read access" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification: You Can Only Prove Closure Over a Set You Can Name
&lt;/h2&gt;

&lt;p&gt;Revocation is usually treated as an action: run it, confirm it ran. The stronger claim is about proof. If you cannot enumerate the affected authority set, you cannot prove that revocation closed it. You can show that the revocation action executed. You cannot show that no reachable authority survived.&lt;/p&gt;

&lt;p&gt;Enumerability is a prerequisite for proving closure, not for every revocation. A trust-root revocation can invalidate an entire authority domain without listing each credential inside it. But the proof then moves up a level: you have to establish that everything with reach to the replacement secrets chains through that root. That is still a claim about a set, and it has to be checkable.&lt;/p&gt;

&lt;p&gt;A closure test has three parts. Establish the set of principals that could read, write or mint any secret in scope, either by listing them or by showing they all chain through one revoked root. For each, show it is invalid or unreachable after the replacement was written. Keep that evidence somewhere the rotated system cannot rewrite. The question of who has standing to confirm that evidence is the governance problem &lt;a href="https://www.rack2cloud.com/recovery-evidence-boundary/" rel="noopener noreferrer"&gt;Your Recovery Program Has a Recovery Evidence Boundary&lt;/a&gt; addresses. Here the problem is mechanical: whether the set can be established at all.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.rack2cloud.com/adversarial-restore-testing/" rel="noopener noreferrer"&gt;Restore Testing Is Becoming An Adversarial Discipline&lt;/a&gt; already assumes the recovery team's own credentials can end up in the attacker's hands. Closure verification extends that posture to replacement secrets: assume a survivor exists, and go and find it. Architectures built to survive adversarial compromise need credential closure as an explicit completion criterion rather than an assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Trivy Incident Documents
&lt;/h2&gt;

&lt;p&gt;Aqua Security's &lt;a href="https://github.com/aquasecurity/trivy/security/advisories/GHSA-69fq-xp46-6x23" rel="noopener noreferrer"&gt;advisory for the Trivy supply chain compromise&lt;/a&gt; records that after the March 1 initial disclosure, credential rotation was performed without being atomic: not every credential was revoked at the same moment. It adds that an attacker could have used a still-valid token to exfiltrate newly rotated secrets during a rotation window that lasted a few days. The wording is conditional, and this post keeps it conditional.&lt;/p&gt;

&lt;p&gt;That makes it a documented demonstration of the mechanism, not a reconstruction of the attack. The advisory does not establish how many credentials survived or what was taken, and this post does not claim to.&lt;/p&gt;

&lt;p&gt;One more detail from the same advisory is worth keeping. Exposure is scoped per component and per consumption path. Whether a workflow was affected depended on which component it pulled, how it pinned it, and when it ran, and a workflow that pinned one action safely could still pull a compromised one through it. That is reachability appearing in a dependency graph rather than as one clean window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design Properties That Decide Atomicity
&lt;/h2&gt;

&lt;p&gt;Four properties, all fixed at design time, determine whether an architecture can revoke atomically. None depends on any particular incident.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secret-store topology
&lt;/h3&gt;

&lt;p&gt;Where replacement secrets are written, and who can read that location at write time. One shared store readable by an entire pipeline means one surviving credential reads every replacement. Scoped paths per consumer shrink the closure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issuer design and credential lifetime
&lt;/h3&gt;

&lt;p&gt;Static, long-lived credentials have no built-in expiry, so they are revoked or they persist. Short-lived credentials issued from a central root let trust-root revocation collapse the unit onto the issuer: stop issuing and the survivors age out within a lifetime you chose in advance. That is the bounded window described above. For the case where authority keeps working after the trust behind it has failed, see also &lt;a href="https://www.rack2cloud.com/third-party-cloud-access/" rel="noopener noreferrer"&gt;Your Cloud Isn't Compromised. Your Vendor Is. Now What?&lt;/a&gt;. The question here is narrower: whether the unit can reach that authority at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-secret reachability
&lt;/h3&gt;

&lt;p&gt;Some secrets mint others: publishing credentials, signing keys, role-assumption paths. Rotating a leaf secret without the secret that can mint it leaves a way to recreate what you just removed. The closure has to include the minters.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verification requirements
&lt;/h3&gt;

&lt;p&gt;The architecture has to make the affected set answerable on demand: a record of which principals can reach which secrets, issuance records, and a way to query validity. If the answer has to be reconstructed from logs after the fact, the architecture cannot prove closure. It can only show that rotation executed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;A revocation event is complete when no surviving credential can reach the replacement secrets. It is not complete when the rotation finishes.&lt;/p&gt;

&lt;p&gt;The real problem is that revocation gets treated as an action to execute rather than a property the architecture either supports or does not. The revocation unit, the reachability graph and the enumerability of the affected set are all fixed long before an incident. During the incident, you discover what you built.&lt;/p&gt;

&lt;p&gt;If you cannot enumerate the affected authority set, you cannot prove that revocation closed it. You can show that the action executed. You cannot show that no reachable authority survived.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/data-protection-architecture-strategy-guide/" rel="noopener noreferrer"&gt;Data Protection Architecture&lt;/a&gt; — the pillar page for recovery, resiliency and backup architecture; this post sits in its credential-and-authority layer&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/persistent-access-survives-fix/" rel="noopener noreferrer"&gt;The Server Was Fixed. Persistent Access Wasn't.&lt;/a&gt; — what survives when remediation never reaches the layer persistence lives in; this post extends that argument inside the credential layer&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/adversarial-restore-testing/" rel="noopener noreferrer"&gt;Restore Testing Is Becoming An Adversarial Discipline&lt;/a&gt; — the adversarial posture toward the recovery team's own credentials that closure verification extends to replacement secrets&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/recovery-evidence-boundary/" rel="noopener noreferrer"&gt;Your Recovery Program Has a Recovery Evidence Boundary&lt;/a&gt; — the governance question of who has standing to confirm recovery claims; this post covers the mechanical precondition, a provable set&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/third-party-cloud-access/" rel="noopener noreferrer"&gt;Your Cloud Isn't Compromised. Your Vendor Is. Now What?&lt;/a&gt; — see also: authority that keeps working after the trust behind it has failed&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/aquasecurity/trivy/security/advisories/GHSA-69fq-xp46-6x23" rel="noopener noreferrer"&gt;Trivy ecosystem supply chain compromise (GHSA-69fq-xp46-6x23)&lt;/a&gt; — Aqua Security's advisory; primary source for the non-atomic rotation language used in the evidence section&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nvd.nist.gov/vuln/detail/CVE-2026-33634" rel="noopener noreferrer"&gt;CVE-2026-33634&lt;/a&gt; — NVD record carrying the same advisory text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/revocation-unit-credential-rotation/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>architecture</category>
      <category>supplychain</category>
    </item>
    <item>
      <title>The Gateway Consolidated Your Controls. NetScaler Compromise Response Has to Unconsolidate Them.</title>
      <dc:creator>NTCTech</dc:creator>
      <pubDate>Thu, 01 Oct 2026 12:23:56 +0000</pubDate>
      <link>https://dev.to/ntctech/the-gateway-consolidated-your-controls-netscaler-compromise-response-has-to-unconsolidate-them-42md</link>
      <guid>https://dev.to/ntctech/the-gateway-consolidated-your-controls-netscaler-compromise-response-has-to-unconsolidate-them-42md</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs4ucm46pvnqiy3s0mbbg.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs4ucm46pvnqiy3s0mbbg.jpg" alt="Field Notes — Engineering Notes from the Complexity Gap | Rack2Cloud" width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;NetScaler compromise response is difficult for the same reason the appliance is valuable: it concentrates authentication, remote access, certificates and administrative trust in one node, so every step of response has to unwind that concentration.&lt;/p&gt;

&lt;p&gt;Citrix disclosed eight NetScaler ADC and Gateway vulnerabilities on September 27, 2026, two of them already exploited. The guidance that followed from Citrix, CISA and Google's Mandiant and Threat Intelligence Group reads less like a patch procedure than a list of interruptions, and the order depends on what you find on the appliance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F46h3w21ylxlne5sa0mdu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F46h3w21ylxlne5sa0mdu.jpg" alt="NetScaler compromise response diagram: one appliance node with six dependent controls, each connection tagged INTERRUPT" width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Every control the gateway concentrated is a connection that compromise response has to cut.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Was Disclosed, and What Wasn't
&lt;/h2&gt;

&lt;p&gt;Citrix published bulletin CTX697096 on September 27, 2026, covering CVE-2026-88771 through CVE-2026-88778. The bulletin says exploitation of CVE-2026-88771 and CVE-2026-88772 has been observed on unmitigated deployments. The first is an unauthenticated command-execution flaw that affects every deployment in its default configuration. The second is a memory-overflow flaw that requires DTLS, which is on by default for VPN virtual servers. The bulletin covers customer-managed deployments; Citrix upgrades its own cloud-managed services.&lt;/p&gt;

&lt;p&gt;CISA added both to its Known Exploited Vulnerabilities catalog the same day, with a September 30 federal remediation date and a requirement for forensic triage under BOD 26-04. Its alert also carries a caution that matters later in this note: preserve forensic evidence before applying updates, because updates can cost forensic visibility.&lt;/p&gt;

&lt;p&gt;The bulletin says nothing about how long exploitation had been running, how widely, or by whom. The public source for that is Google's Mandiant and Threat Intelligence Group, whose September 29 report describes a campaign against CVE-2026-88772 that was "ongoing since at least early September," with likely impact on government, financial services, technology, education, and legal and professional services organizations in North America and Europe. For CVE-2026-88771 the report relies on the vendor's disclosure rather than its own analysis. It does not attribute the activity, and neither does this note. How long an exposure runs before an operator can see it is a cost in its own right, covered in &lt;a href="https://www.rack2cloud.com/patch-visibility-debt/" rel="noopener noreferrer"&gt;patch visibility debt&lt;/a&gt;, and it is why the missing start date matters for NetScaler compromise response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Concentration Is the Point of the Appliance
&lt;/h2&gt;

&lt;p&gt;A NetScaler in the path exists so that authentication brokering, TLS termination, remote access and policy enforcement happen in one controlled place instead of inside every application behind it. Deciding where to concentrate enforcement is a &lt;a href="https://www.rack2cloud.com/cloud-strategy/" rel="noopener noreferrer"&gt;cloud architecture strategy&lt;/a&gt; decision, and it is also a decision about where failure will concentrate. Google's report notes that these devices face the internet, sit outside endpoint detection, and often store or process credentials that reach deeper into the network. Because TLS terminates on the appliance, upstream network devices generally cannot see the request paths or headers inside it.&lt;/p&gt;

&lt;p&gt;None of that is an argument against gateways. The concentration is the design working. The argument is about what happens afterward, because NetScaler compromise response inherits the concentration. Whatever the appliance holds, response has to invalidate. Whatever it fronts, response has to be ready to interrupt. The question for an architect is not whether the appliance is important, which was settled when it was placed in the path, but whether anyone has written down what it costs to take it out of service, and who may decide to.&lt;/p&gt;

&lt;h2&gt;
  
  
  NetScaler Compromise Response Is a Sequence of Interruptions
&lt;/h2&gt;

&lt;p&gt;Three documents describe what to do, and they start from different states. CISA writes for the gap between disclosure and update. Google's guidance writes for an estate that may or may not be compromised. Citrix's standing article on suspected compromise writes for an appliance you no longer trust. Each step in NetScaler compromise response has a service cost, and several steps cost the same service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7qdqh7mnq6oxa5buf335.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7qdqh7mnq6oxa5buf335.jpg" alt="Five-step response sequence of hunt, preserve, isolate, patch and rotate, each annotated with the service it interrupts" width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each step in the response sequence has a service cost; isolation and rotation reach every user of the node.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Evidence comes first, if you can afford it. Citrix's article starts with preservation: snapshot a virtual appliance, record system time and NTP settings before isolation, keep remote syslog and management-console logs, and collect a support bundle, while noting that the vendor does not support forensic investigation. Its next step is a core file of the packet engine, and the article states that the system performs a warm restart during that process and drops SSH sessions. Google asks for a memory-inclusive snapshot of a virtual appliance before any reboot where operationally possible, and several of its detections depend on logs the appliance does not forward by default. That matters because the actor Google describes scrubbed its traces from appliance files and, per Google's hunting guidance, from web access logs, which is the boundary in &lt;a href="https://www.rack2cloud.com/evidence-layer-trust-boundary/" rel="noopener noreferrer"&gt;your logs are not evidence if the infrastructure that produces them can rewrite the record&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then isolation, which for a gateway means removing remote access. Google says isolating a compromised or suspected appliance can cause significant business disruption where the appliance provides remote access, and that broad internet isolation or strict allow-listing disrupts remote workforces. It recommends a targeted, phased approach that prioritizes the fixed build, with isolation weighed against risk tolerance and operational requirements. When the appliance fronts services owned by several teams, who may make that call is an ownership question before it is a technical one, the pattern in &lt;a href="https://www.rack2cloud.com/multi-cloud-ownership-boundary/" rel="noopener noreferrer"&gt;an ownership problem, not a technology problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In a high-availability pair, Google adds a step that turns the redundancy mechanism into the thing being contained: halt configuration synchronization and assess each node independently, so a compromised node cannot replicate attacker-modified configuration to its standby. Google presents this as a preventive step, not a reported occurrence. The architectural reading is mine. The feature that keeps the pair available is also a propagation path, so containment means running the pair as two unvalidated nodes until each is cleared. Delay is exposure. Action is lost redundancy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fah9zg9iir45y5oyd0f39.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fah9zg9iir45y5oyd0f39.jpg" alt="High-availability NetScaler pair with configuration synchronization halted so modified configuration cannot reach the standby" width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The mechanism that keeps the pair available is also the path containment has to close.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then the fix, which is not one action either. Citrix's article has virtual appliances replaced rather than repaired, firmware upgraded before any configuration is restored, and the restored backup verified to predate the compromise. That last condition needs a date. Google's early-September floor covers one of the two exploited flaws, and the vendor bulletin gives no date for either. Citrix's article also says that where law enforcement involvement is possible, counsel should weigh in before rebuild, because evidence preservation can outrank restoring service. And a fixed build closes the flaw without evicting an actor who persisted through it. Google describes web-server configuration changes, an elevated-privilege setting on the shell and an appliance reboot used to make access survive, which is the argument in &lt;a href="https://www.rack2cloud.com/persistent-access-survives-fix/" rel="noopener noreferrer"&gt;the server was fixed and persistent access wasn't&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Concentration Makes You Rotate
&lt;/h2&gt;

&lt;p&gt;The rotation guidance in NetScaler compromise response is where the concentration becomes visible. Google and Citrix both list what has to change, and the lists overlap almost entirely. They differ on timing: Citrix revokes before the rebuild and rotates restored secrets afterward, while Google places rotation after patching.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What the appliance concentrates&lt;/th&gt;
&lt;th&gt;What the guidance has you change&lt;/th&gt;
&lt;th&gt;Who feels it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Remote-access sessions, including administrative, Gateway, VPN and ICA/HDX&lt;/td&gt;
&lt;td&gt;Revoke and terminate the sessions&lt;/td&gt;
&lt;td&gt;Every user connected through the node&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User accounts authenticated through Gateway or AAA virtual servers&lt;/td&gt;
&lt;td&gt;Change credentials on their respective systems (Citrix)&lt;/td&gt;
&lt;td&gt;Every user population the node authenticated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Appliance administrator, local and SSH credentials, plus key encryption keys (Citrix)&lt;/td&gt;
&lt;td&gt;Rotate&lt;/td&gt;
&lt;td&gt;Administrators and the automation that uses them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Certificates and private keys&lt;/td&gt;
&lt;td&gt;Revoke and replace&lt;/td&gt;
&lt;td&gt;Every service that presents the node's certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LDAP, RADIUS, TACACS, SNMP and API integration credentials&lt;/td&gt;
&lt;td&gt;Change on the systems they authenticate to&lt;/td&gt;
&lt;td&gt;Identity, network and monitoring teams at once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connected infrastructure such as StoreFront, delivery controllers and session hosts&lt;/td&gt;
&lt;td&gt;Review for lateral movement&lt;/td&gt;
&lt;td&gt;Teams that never owned the appliance&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The first two columns come from the two documents. The third is my analysis.&lt;/p&gt;

&lt;p&gt;Read down the first column and you have the appliance's real dependency map: the directory, the authentication path, the certificate chain, the management plane and the user population, all in one node. Nobody drew it that way when the appliance was deployed, and it was there the whole time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Questions to Run Against Your Estate
&lt;/h2&gt;

&lt;p&gt;Run these against your estate before NetScaler compromise response is something you are doing rather than planning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pre-incident questions:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What terminates on each NetScaler, and which teams own the services behind it?&lt;/li&gt;
&lt;li&gt;Who may authorize isolating a Gateway, and is that authority written down?&lt;/li&gt;
&lt;li&gt;Is the list of secrets, certificates and integration credentials on each appliance maintained, or would you be assembling it during response?&lt;/li&gt;
&lt;li&gt;Does the runbook say when to halt synchronization in a high-availability pair, and what redundancy you give up while it is halted?&lt;/li&gt;
&lt;li&gt;Which configuration backup would you trust, and how would you show when it was taken relative to the compromise?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Architect's Verdict
&lt;/h2&gt;

&lt;p&gt;A gateway consolidates controls on purpose, and compromise response has to unconsolidate them on demand. NetScaler compromise response is not a patch. It is an ordered series of interruptions to everything the appliance was trusted to hold together.&lt;/p&gt;

&lt;p&gt;Every incident response interrupts service, so that alone is not the argument. The difference is scope. Each decision in this sequence reaches every service that shared the node, and the public guidance enumerates them: sessions, administrative access, certificates, directory and authentication integrations, management integrations, and the infrastructure connected behind it.&lt;/p&gt;

&lt;p&gt;The rotation inventory is the architecture diagram. It shows what the appliance concentrated, in the order a responder has to undo it, and it is more accurate than any design document written when the appliance was deployed.&lt;/p&gt;

&lt;p&gt;Gateways earn their place in the path. The cost of that placement arrives as a list, on the day you trust the node least.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/cloud-strategy/" rel="noopener noreferrer"&gt;Cloud Architecture Strategy&lt;/a&gt; — pillar hub for the architecture decisions behind where enforcement, and failure, concentrate&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/evidence-layer-trust-boundary/" rel="noopener noreferrer"&gt;Your Logs Are Not Evidence If The Infrastructure That Produces Them Can Rewrite The Record&lt;/a&gt; — why appliance-side logs cannot carry the investigation alone&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/persistent-access-survives-fix/" rel="noopener noreferrer"&gt;The Server Was Fixed. Persistent Access Wasn't.&lt;/a&gt; — why a fixed build does not end a compromise&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/patch-visibility-debt/" rel="noopener noreferrer"&gt;SharePoint Vulnerabilities And The Cost Of Patch Visibility Debt&lt;/a&gt; — the cost of the gap between exposure and operator visibility&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.rack2cloud.com/multi-cloud-ownership-boundary/" rel="noopener noreferrer"&gt;Multi-Cloud Coherence Is an Ownership Problem, Not a Technology Problem&lt;/a&gt; — why cross-team decisions stall on ownership before technology&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/blog/topics/threat-intelligence/defending-against-active-exploitation-of-citrix-netscaler-adc-and-gateway-appliances" rel="noopener noreferrer"&gt;Defending Against Active Exploitation of Citrix NetScaler ADC and Gateway Appliances&lt;/a&gt; — Mandiant and Google Threat Intelligence Group campaign analysis and containment guidance, September 29, 2026&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.citrix.com/external/article/CTX694799/steps-to-take-if-netscaler-adc-is-suspected-to-be-compromised.html" rel="noopener noreferrer"&gt;Steps to Take if NetScaler ADC is Suspected to be Compromised (CTX694799)&lt;/a&gt; — Citrix's own compromise-response sequence&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.citrix.com/external/article/CTX697096/citrix-netscaler-adc-and-citrix-netscale.html" rel="noopener noreferrer"&gt;NetScaler ADC and Gateway Security Bulletin for CVE-2026-88771 through CVE-2026-88778 (CTX697096)&lt;/a&gt; — the vendor bulletin, published September 27, 2026&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.cisa.gov/news-events/alerts/2026/09/27/critical-zero-day-vulnerabilities-exploited-citrix-netscaler-adc-gateway" rel="noopener noreferrer"&gt;Critical Zero-Day Vulnerabilities Exploited in Citrix NetScaler ADC, Gateway (CISA)&lt;/a&gt; — CISA alert carrying the preserve-evidence-before-updating caution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://www.rack2cloud.com/netscaler-compromise-response/" rel="noopener noreferrer"&gt;rack2cloud.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>devops</category>
      <category>infrastructure</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
