> For the complete documentation index, see [llms.txt](https://docs.stepsecurity.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.stepsecurity.io/developer-machines/installation-script/mdm-deployment/windows/microsoft-intune.md).

# Microsoft Intune

This guide walks IT admins through deploying Dev Machine Guard across a Windows fleet with **Microsoft Intune**, packaged as a **Win32 app** built from the signed MSI (`.intunewin`). It covers install, validation, upgrades, and removal — all driven from the Intune portal.

### What ships

Download the `.intunewin` for your architecture from [GitHub Releases](https://github.com/step-security/dev-machine-guard/releases):

* `stepsecurity-dev-machine-guard-<version>-x64.intunewin` (Windows on Intel/AMD)
* `stepsecurity-dev-machine-guard-<version>-arm64.intunewin` (Windows on ARM)

Each `.intunewin` is Microsoft's Win32 Content Prep Tool output wrapping the **signed MSI** plus a thin `install.cmd` / `uninstall.cmd` pair that forward Intune's arguments to `msiexec`. Each release also publishes a matching Sigstore (cosign) `.intunewin.bundle` alongside it — grab it too if you plan to verify provenance before staging (see Signature verification below).

### How installation works

The agent installs entirely through native Windows Installer (`msiexec`), with **no PowerShell anywhere in the chain**. In locked-down fleets where EDR, AppLocker, or Constrained Language Mode restrict scripting, a script-based deployment can be blocked or flagged — a pure-MSI install is not:

```
Intune Management Extension → install.cmd → msiexec.exe → stepsecurity-dev-machine-guard.exe → schtasks.exe
```

With **Install behavior = System**, the install runs as SYSTEM, so it deploys to a device even before any user logs on.

> **Install runs as SYSTEM; the scan runs as the signed-in user.** A device with nobody logged in installs fine and shows **Installed** in Intune, but won't report to the StepSecurity dashboard until a user signs in and the scheduled task fires. This is expected, not a failure.

### Passing tenant credentials

Pass credentials **inline** as MSI public properties in the install command (see Program below):

| Property        | Required | Description                                                              |
| --------------- | -------- | ------------------------------------------------------------------------ |
| `CUSTOMERID`    | yes      | Your StepSecurity tenant ID                                              |
| `APIENDPOINT`   | yes      | StepSecurity backend URL (typically `https://agent.api.stepsecurity.io`) |
| `APIKEY`        | yes      | Tenant API key from your StepSecurity dashboard                          |
| `SCANFREQUENCY` | no       | Scheduled scan frequency in hours (default `4`)                          |

#### A note on the persisted `config.json`

The installer writes the resolved config — **including `api_key` in plaintext** — to `C:\ProgramData\StepSecurity\config.json`, because the scheduled task reads it at scan time. It hardens the file's ACL (SYSTEM + Administrators = Full, Users = Read, inheritance disabled), so any signed-in user can read the key but not modify it. On a **shared multi-user machine** that means every interactive user can read the tenant API key — if that's unacceptable, scope deployment to single-user devices.

### Intune Win32 app setup, step by step

**Apps → Windows → Add**, then select app type **Windows app (Win32)**.

<figure><img src="/files/FHhj3adqR74rzuXsjGJC" alt=""><figcaption></figcaption></figure>

**Step 1 — App information.** Upload the `.intunewin` for your architecture via **Select file**, then fill in:

| Field                             | Value                                                                                                           |
| --------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Name                              | `StepSecurity Dev Machine Guard` (suffix the version, e.g. `… 1.11.5`, so supersedence chains stay unambiguous) |
| Publisher                         | `StepSecurity`                                                                                                  |
| App version                       | The version inside the `.intunewin` — **must match** the MSI's `ProductVersion`                                 |
| Category / featured / URLs / logo | leave default / empty                                                                                           |

<figure><img src="/files/fNuzI9Fzqm3RizY89Zpv" alt=""><figcaption></figcaption></figure>

**Step 2 — Program.**

| Field                             | Value                                                                                                                        |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Install command                   | `install.cmd CUSTOMERID=<your_customer> APIKEY=<your_api_key> APIENDPOINT=https://agent.api.stepsecurity.io SCANFREQUENCY=4` |
| Uninstall command                 | `uninstall.cmd`                                                                                                              |
| Install behavior                  | **System**                                                                                                                   |
| Installation time required (mins) | `60` (raise the default — a slow endpoint can otherwise time out and report Failed)                                          |
| Allow available uninstall         | **No** (required security tool — users must not self-uninstall)                                                              |
| Device restart behavior           | No specific action                                                                                                           |
| Return codes                      | Defaults                                                                                                                     |

`install.cmd` forwards all arguments to `msiexec /i`, so MSI public properties pass through in any order.

<figure><img src="/files/s9r7cU09lkcWPItpngbT" alt=""><figcaption></figcaption></figure>

**Step 3 — Requirements.**

| Field                         | Value                                                                |
| ----------------------------- | -------------------------------------------------------------------- |
| Operating system architecture | the arch matching this `.intunewin` (x64 **or** ARM64)               |
| Minimum operating system      | Windows 10 / Windows Server 2016 (or your org's baseline, if higher) |

If your fleet has both x64 and ARM64 endpoints, create **two separate Win32 apps**, one per architecture, each gated to its own arch.

<figure><img src="/files/OWX8xEaRGlxNNaWK6y0t" alt=""><figcaption></figcaption></figure>

**Step 4 — Detection rules.** Choose **Manually configure detection rules**, add a **Registry** rule:

| Field                        | Value                                               |
| ---------------------------- | --------------------------------------------------- |
| Key path                     | `HKEY_LOCAL_MACHINE\Software\StepSecurity`          |
| Value name                   | `AgentVersion`                                      |
| Detection method             | String comparison                                   |
| Operator                     | **Equals**                                          |
| Value                        | The version inside the `.intunewin` (e.g. `1.11.5`) |
| 32-bit app on 64-bit clients | No                                                  |

<figure><img src="/files/sUH5539U6VpJeVpYRYa8" alt=""><figcaption></figcaption></figure>

The MSI writes the installed version to `HKLM\Software\StepSecurity\AgentVersion` on every install. Use a registry rule, not a product-code rule — the product code changes with each release, so a product-code rule would report "Not installed" after an upgrade. The version-valued key works for both fresh installs and upgrades, with no custom detection script.

**Step 5 — Dependencies / Supersedence.** Skip both on initial deploy. Supersedence is used later when uploading a newer version — see Upgrades.

**Step 6 — Assignments.** Add the target Entra device group under **Required** (App availability + Installation deadline = As soon as possible). Leave **Available for enrolled devices** and **Uninstall** empty.

<figure><img src="/files/g4fzl27m9sYUSU0BP4Ue" alt=""><figcaption></figcaption></figure>

**Step 7 — Review + create.** Verify the summary and **Create**. Intune processes the payload (under a minute for a \~4 MB build) and the app appears under **Apps → Windows apps**.

<figure><img src="/files/ljfugeoHL5ISbb06lUYs" alt=""><figcaption></figcaption></figure>

### Validating a successful deployment

Both checks use surfaces you already have — no shell access to the endpoint is needed.

A fresh assignment typically takes **20–30 minutes** to flip a device's status to **Installed**, even with a manual sync — manual sync shortens IME's check-in, not Intune's backend propagation. Be patient on the first attempt.

1. **Intune portal** — Apps → the app → **Device install status** → the device row reads **Installed**. This confirms the detection rule matched (the agent's version key is present on the device).

<figure><img src="/files/awPlfywlRDc9Ws6D5PJM" alt=""><figcaption></figcaption></figure>

2. **StepSecurity dashboard** — the endpoint appears within a few minutes of its first scheduled scan. This is the end-to-end confirmation that the agent is both installed *and* reporting. Recall the scan runs in the signed-in user's context, so a device with nobody logged in shows **Installed** in Intune but won't appear in the dashboard until a user signs in.

### Upgrades

To ship a new version, upload it as a **separate Win32 app that supersedes the current one**. The MSI performs the in-place major upgrade; Intune just routes the new version to devices via the supersedence link.

Create the new version as a **separate Win32 app** (same setup as above, new App version + version-suffixed Name), with one delta on the **Supersedence** page:

| Field                          | Value                                              |
| ------------------------------ | -------------------------------------------------- |
| **+ Add**                      | The previous version's app entry (e.g. `… 1.11.5`) |
| **Uninstall previous version** | **Off** — row reads `Update`, not `Replace`        |

<figure><img src="/files/Iwp6ztEaCsLYtGVq4Eo3" alt=""><figcaption></figcaption></figure>

Leave **Uninstall previous version off** — the MSI does an atomic in-place upgrade, so forcing an Intune uninstall first would take the agent down mid-transition and risk orphaning its config. IME runs the new `install.cmd`, detection flips automatically (the new app's rule passes, the old one's fails), and `C:\ProgramData\StepSecurity\config.json` is preserved — no admin touches the device.

### Uninstall

Removal is driven from Intune — never `msiexec /x` on the endpoint directly. For **each** app entry targeting the device, move the group from **Required** to **Uninstall** (Properties → Assignments → Edit → Review + save). On the next IME check-in, `uninstall.cmd` removes the scheduled task, binaries, registry key, and ARP entry.

{% hint style="info" %}
**Flip every version in the supersedence chain, not just the latest.** Intune doesn't infer uninstall intent from the newer entry. If you flip only the newest app while an older superseded one is still **Required**, IME uninstalls the new version and then **reinstalls the old** to satisfy that surviving intent — leaving the device downgraded and mis-configured.
{% endhint %}

<figure><img src="/files/Hxh4gl4mihBZI69l2iwg" alt=""><figcaption></figcaption></figure>

`C:\ProgramData\StepSecurity\config.json` is intentionally **kept** so tenant identity survives an uninstall/reinstall. It stays ACL-restricted after removal, so it isn't a live exposure. If you must purge it fleet-wide — e.g. when retiring the tenant entirely — push a cleanup script through Intune to delete `C:\ProgramData\StepSecurity\`, since the endpoints aren't reachable directly.

### Troubleshooting

Everything below is diagnosable from the Intune portal — no access to the endpoint is needed. To retrieve device logs remotely, use **Devices → \[device] → Collect diagnostics**, which pulls the Intune Management Extension logs (`AgentExecutor.log`, `IntuneManagementExtension.log`) into a downloadable package.

| Symptom (visible to you)                                                     | Likely cause                                                                                     | What to do                                                                                                                |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| Device never appears in **Device install status** (Total = 0) after 30+ min  | Device not in the assigned group, or hasn't checked in yet                                       | Groups → group → **Members**; Devices → device → **Last check-in**, then **Sync**                                         |
| Device shows **Failed**                                                      | Typo in the install command, or msiexec error                                                    | **Device install status** shows the error / exit code; **Collect diagnostics** to read the msiexec result in the IME logs |
| Shows **Installed** in Intune but **absent from the StepSecurity dashboard** | No user has signed in yet (the scan runs in the user context), or wrong `APIKEY` / `APIENDPOINT` | Confirm a user has signed in; re-check the credential values in the app's **install command**                             |
| Uninstall applies to one chain app but not another                           | Per-app reevaluation throttle                                                                    | Force a device **Sync** and wait a cycle; if it persists, **Collect diagnostics** and open a support case                 |

For a support case, run **Devices → \[device] → Collect diagnostics** and attach the resulting package. If someone has access to the device, also include the MSI verbose log (`C:\ProgramData\StepSecurity\install.log`) and the agent logs (`agent.log`, `agent.error.log`).

### Signature verification

The `.intunewin` ships with a **Sigstore (cosign) bundle** proving it was built by this repo's GitHub Actions release workflow from a tagged commit, with no out-of-band tampering. Verify before staging:

```bash
# Linux/macOS with cosign installed
cosign verify-blob \
  --bundle stepsecurity-dev-machine-guard-<version>-x64.intunewin.bundle \
  --certificate-identity-regexp 'https://github.com/step-security/dev-machine-guard/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  stepsecurity-dev-machine-guard-<version>-x64.intunewin
```

Output ends with `Verified OK`. Any other result — abort the deployment.

The MSI inside is also Authenticode-signed (Azure Trusted Signing); Windows verifies that transparently at install time, and IME extracts the MSI verbatim so the publisher signature flows through unchanged. No action needed on your side.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.stepsecurity.io/developer-machines/installation-script/mdm-deployment/windows/microsoft-intune.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
