# Azure VM JIT Access Not Enabled

> Without a Defender for Cloud just-in-time policy, an Azure VM's management ports stay open to whatever the NSG allows around the clock, and internet scanners find an exposed port 22 or 3389 within minutes. RC-1301 fires only when the JIT-policy lookup set proves no policy covers the VM.

Source: https://zop.dev/integrations/azure/recommendations/azure-vm-jit-access-not-enabled
Updated: 2026-08-19

---

## Standing open ports are what gets brute-forced

Management ports are the most-scanned surface on the public internet: a VM answering on 22 or
3389 collects credential-stuffing attempts within minutes of getting a public IP, and it keeps
collecting them every hour it exists. The exposure isn't hypothetical misconfiguration; it is
the default posture of any VM whose NSG permits inbound management traffic, which stays true
whether anyone is actually logging in this week or not.

## What a JIT policy does mechanically

Just-in-time access inverts the default. Defender for Cloud writes deny rules for the
management ports into the NSG, and access becomes a request: an operator asks for a port, a
source IP range, and a time window (capped by the policy's maximum), Defender opens a scoped
allow rule, and the window expires on its own. The ports are closed at every moment nobody has
an approved reason to be on the machine, and every opening leaves an audit trail of who asked
and when.

## How ZopNight knows, and when it won't claim to

The discoverer pulls the subscription's JIT-policy lookup set and stamps each VM's
`jit_access_enabled` metadata from membership, so `"false"` means the policies were enumerated
and none covers this VM. The prior implementation trusted a `jit_access` customer tag that no
producer wrote, leaving it dead on real data and spoofable by anyone who could edit tags. When the
metadata key is absent, the rule abstains; it never converts missing evidence into a security
finding.

## Enumerate JIT coverage in a subscription

```bash
az security jit-policy list \
  --query "[].{name:name, location:location, vms:length(virtualMachines)}" -o table
```

Any VM not referenced by a listed policy matches what this rule reports.

## Adoption notes

Enable JIT from Defender for Cloud's workload protections (it requires the servers plan), set
the port list and maximum request duration per VM, and grant operators the request flow rather
than standing NSG exceptions. Automation that SSHes on a schedule needs its source ranges
baked into the policy or it will break at the first closed window. Detection is reproducible
with Reader; ZopNight modifies no NSG and no policy.
