> 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/device-policy/policies.md).

# Policies

Policies are reusable rules that you bundle into profiles to control what is allowed on developer machines. Each policy targets one category:

* **IDE extensions**: targets one IDE and defines which extensions and versions developers can install.
* **Package config**: targets one package ecosystem and points developer machines at your tenant's Secure Registry.

The **Policies** page under **Developer Machines** > **Device Policy** lists every policy in the following columns:

| Column                 | Description                                                                                      |
| ---------------------- | ------------------------------------------------------------------------------------------------ |
| **Name**               | The policy name, with its description underneath if one is set                                   |
| **Type**               | **Secure registry**, **Allow-list**, or **Block-list**                                           |
| **Category**           | **IDE extensions** or **Package config**                                                         |
| **Rules**              | The number of rules in the policy. Package config policies show a dash, since they have no rules |
| **Profiles**           | How many profiles the policy is attached to                                                      |
| **Last updated (GMT)** | When the policy last changed                                                                     |

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2F9zJFVwZANUP3AV8xxiCj%2FScreenshot%202026-09-29%20at%2010.23.13.png?alt=media&amp;token=2fd6bc1c-95b2-4a6a-9288-0bc6cb85bbad" alt=""><figcaption></figcaption></figure>

**Follow this interactive demo to see how it works:**

{% embed url="<https://app.storylane.io/share/uivtaxit0ole>" %}

### Create a Policy

* Click **New policy**, then complete the **Basics** section:

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FmD7Y2GlnFOHpsh2wC1JJ%2FScreenshot%202026-07-08%20at%2000.16.21.png?alt=media&amp;token=ced80656-8aac-48b2-b7c0-b10219cb68f5" alt=""><figcaption></figcaption></figure>

Give the policy a name (for example, "Approved VS Code extensions") and an optional description of what it controls and why. Then select the **Category**. Your choice determines both the remaining fields and the target selector next to it:

| Category                                                                      | Target selector                                                                                                                                        |
| ----------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **IDE extensions**, described as "Editor / IDE plugins"                       | **IDE**: VS Code                                                                                                                                       |
| **Package config**, described as "Route installs through the secure registry" | **Ecosystem**: npm (`~/.npmrc · registry + credential`), PyPI (`pip.conf / uv.toml · index-url + credential`), or Go (`go/env · GOPROXY + credential`) |

A **Compiled preview** panel is shown alongside the editor throughout. It renders the exact configuration that will be delivered to devices, and updates as you make changes. Use the copy button to copy it at any time.

When you are done, click **Create policy**. To enforce the policy on devices, add it to a profile. See [Profiles](/developer-machines/device-policy/profiles.md).

### IDE Extension Policies

An IDE extension policy defines which extensions and versions developers can install in a given IDE. VS Code is supported today.

#### Mode

Choose whether the listed extensions are the only ones allowed, or the ones blocked:

* **Allow-list**: block everything except the listed extensions
* **Block-list**: allow everything except the listed extensions

#### Rules

Rules define the extensions and publishers the policy applies to. The section heading shows the current rule count, and its description reflects the mode you chose: an allow-list lists what developers are allowed to install, a block-list lists what they are blocked from installing.

You can add rules in two ways.

**Add rules from inventory or manually**

Click **Add rules** to open the rule picker.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FFS7kPIlpwTOAz0CvD2J0%2FScreenshot%202026-07-31%20at%2021.43.12.png?alt=media&amp;token=1d51a9bd-c275-4db5-a808-4fa617239fe6" alt=""><figcaption></figcaption></figure>

* **From inventory**: search the extensions Dev Machine Guard has already observed across your fleet, by name or publisher. Each entry shows the extension ID, the IDE, and the number of devices where it is installed, so you can build the policy from real usage.
* **Add manually**: add an extension that has not been observed in your fleet yet. Enter the publisher (for example, `ms-python`) and optionally the extension ID (for example, `python`). Leave the extension ID empty to write a publisher-wide rule. Manual rules use their own version strategy setting: allow any version, stable releases only, or pin specific versions.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FuSTKCrmzppzqPxvkhQ1E%2FScreenshot%202026-07-31%20at%2021.44.55.png?alt=media&amp;token=36d49079-41aa-475a-aa52-97b6497787d8" alt=""><figcaption></figcaption></figure>

Before adding the selection, choose a **default version strategy**. It applies to every selected extension, and you can change individual rules afterwards:

* **Allow any version**: any published version is permitted.
* **Stable releases only**: pre-release and preview builds are rejected.
* **Pin specific versions**: add the extensions first, then pin exact versions on each rule from the rules table.
* **Allow everything from the publisher**: creates one publisher-wide rule per distinct publisher in the selection.

You can also add an optional **comment**. It is recorded on every rule you add, for audits and reviews, and is never delivered to devices.

**Import an existing configuration**

Click **Import** to upload an existing configuration and turn its entries into rules. Supported formats are an `extensions.allowed` JSON file, a `.mobileconfig`, or a preferences plist, up to 5 MB.

#### Rules Table

Added rules appear in a table with these columns:

| Column        | Description                                                                                                                                     |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| **Publisher** | The extension publisher, for example `hashicorp`                                                                                                |
| **Extension** | The specific extension, or `whole publisher` for a publisher-wide rule                                                                          |
| **Scope**     | The version constraint that applies. In a block-list policy, a publisher-wide rule shows `n/a · deny blocks all`, because the block is absolute |
| **Comment**   | The optional audit comment. Click **Add comment** to set one                                                                                    |

You can change the scope per rule, or remove a rule with the **X** at the end of its row.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FazPJxNOzy5nsbNvZEAE1%2FScreenshot%202026-07-08%20at%2000.20.04.png?alt=media&amp;token=e6f9942e-d6ac-4b08-bc7e-9b8f8dce712e" alt=""><figcaption></figcaption></figure>

#### Private Marketplace

By default, assigned devices install extensions from the public Visual Studio Marketplace. If your organization hosts its own extension gallery, enter its URL in the optional **Private marketplace** section to point assigned devices at that gallery instead.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FvgBwupMFxJrutOFmEdIr%2FScreenshot%202026-07-31%20at%2021.48.02.png?alt=media&amp;token=0ccd6149-8432-4d14-8df4-e0532536c4ab" alt=""><figcaption></figcaption></figure>

Leave the field blank to keep the public Marketplace. Rule enforcement is identical either way: the allow-list or block-list you defined above applies to whichever gallery the device uses, so switching galleries does not weaken or change your rules.

When a URL is set, it is added to the compiled configuration as `extensions.gallery.serviceUrl`, and delivered in the same artifact as the rest of the policy. Because the gallery URL determines where every extension on the device comes from, it is also verified: if your MDM deploys a different gallery URL than the policy defines, the profile reports drift and the diff shows both values. See Profiles.

#### Compiled Preview

For VS Code, the policy compiles to the `extensions.allowed` setting inside `settings.json`. The preview is labelled with the effect of your chosen mode, so you can confirm the logic at a glance: **Allow only these, block the rest** for an allow-list, or **Block these, allow the rest** for a block-list.

An allow-list policy denies everything with a `"*": false` wildcard, then permits each listed entry:

```json
{
  "extensions.allowed": {
    "*": false,
    "bradlc.vscode-tailwindcss": true,
    "github.vscode-github-actions": true,
    "ms-vscode-remote.remote-ssh": true,
    "ms-vscode-remote.remote-ssh-edit": true
  }
}
```

A block-list policy inverts the wildcard, permitting everything and denying only the listed entries:

```json
{
  "extensions.allowed": {
    "*": true,
    "hashicorp": false,
    "ms-python.python": false
  }
}
```

If a private marketplace URL is set, an `extensions.gallery.serviceUrl` key is included alongside `extensions.allowed`.

These settings are enforced on assigned devices through both your MDM and the Dev Machine Guard agent. A device reports compliant once the settings are applied.

### Package Config Policies

A package config policy configures a package manager on each assigned device to resolve packages through your tenant's Secure Registry instead of the public registry. Each policy targets one ecosystem:

| Ecosystem | Clients                                                                       | Files the agent manages           |
| --------- | ----------------------------------------------------------------------------- | --------------------------------- |
| **npm**   | npm. pnpm, Yarn v1, and Bun read the same file, so they follow the policy too | `~/.npmrc`                        |
| **PyPI**  | pip, uv, or both                                                              | `~/.netrc`, `pip.conf`, `uv.toml` |
| **Go**    | The Go toolchain                                                              | `~/.netrc`, `go/env`              |

This removes the per-machine setup work described in the Secure Registry setup guide: rather than each developer editing their own configuration, you define the policy once and deliver it to the fleet.

Package config policies manage user-level configuration only. Project files, virtual environments, and system-level configuration are never touched, and a device does not need the package manager installed to report compliant.

{% hint style="info" %}
PyPI and Go policies, and npm **Additional configuration**, require Dev Machine Guard agent **v1.17.0 or later**. Devices on an older agent show **Agent update required** in the profile's Compliance tab.
{% endhint %}

#### **Enforcement**

Package config policies have no mode or rules to configure. Routing installs through your tenant's Secure Registry is **Always on** for this category, so the **Enforcement** section is informational and summarizes what the agent does on each device. On every check-in the agent verifies the configuration it manages; if a developer edits it, the agent restores it and reports drift.

{% hint style="info" %}
These behaviors describe the Dev Machine Guard agent. If you deliver this policy through your MDM instead, the equivalent work is done by the audit, remediation, and uninstall scripts that the profile generates for you. See [Profiles](/developer-machines/device-policy/profiles.md).
{% endhint %}

#### **npm**

The **Secure npm registry** enforcement:

* **Writes** a clearly marked managed block into the user's `~/.npmrc`: the registry URL plus an authentication token, then any additional configuration sorted by key. Existing user configuration is preserved.
* **Verifies** it on every check-in. If a developer edits the block, the agent restores it and reports drift.
* **Removes** the block cleanly when the policy is detached from the profile or the tenant offboards, leaving no residue.

Only the user-level `~/.npmrc` is managed. Project `.npmrc` files and everything outside the managed block are never touched.

The compiled preview shows the managed block the agent writes to `~/.npmrc` on each device, in place, around any existing configuration:

```
# ... your existing .npmrc configuration ...
# BEGIN StepSecurity Secure Registry -- managed by dmg
registry=https://registry.stepsecurity.io/javascript
//registry.stepsecurity.io/javascript/:_authToken=step_xxxxxxxx::dev:<DEVICE-SERIAL-ID>
# END StepSecurity Secure Registry
```

The `BEGIN` and `END` markers delimit the managed region. Configuration outside the markers is left untouched, which is what allows the block to be updated or removed later without disturbing a developer's own settings.

The registry authentication token is shared across your tenant. The agent appends a per-device `:dev:` suffix to it, so registry access from each device is attributed separately even though the underlying token is the same.

**Additional configuration**

Use the optional **Additional configuration** section to deliver extra `.npmrc` settings to every assigned device, alongside the Secure Registry settings. A common use is a scoped registry, so packages under your organization's scope resolve from your private registry while everything else routes through Secure Registry. Any other `.npmrc` option can be delivered the same way.

```
@example-org:registry=https://registry.example-org.com/
//registry.example-org.com/:_authToken=${REGISTRY_TOKEN}
save-exact=true
engine-strict=true
```

* Enter one `key=value` pair per line. Comments, sections, and arrays are not supported.
* A policy can hold up to 50 keys and 4.0 KiB of configuration.
* The agent writes these settings into the same managed block, sorted by key.

{% hint style="warning" %}
**Never paste tokens.** Reference them as `${ENV_NAME}` and npm reads the value from the developer's environment at install time. The variable must already exist on each device. StepSecurity never sees or stores it.
{% endhint %}

#### **PyPI**

Under **Python package clients**, select the clients the policy manages: **pip**, **uv**, or both. At least one is required, and both share one Secure Registry credential.

The **Secure PyPI index** enforcement:

* **Writes** the shared Secure Registry credential to the user's `~/.netrc`.
* **Sets** the Secure Registry as pip's sole managed index in the user's `pip.conf`.
* **Sets** the Secure Registry as uv's default index with `index-strategy = "first-index"` in the user's `uv.toml`.
* **Verifies** it on every check-in. If a developer edits it, the agent restores it and reports drift.
* **Restores** the user's previous configuration when a client is deselected or the policy is detached.

If an environment variable that takes precedence over these files is set on the device, such as `PIP_INDEX_URL`, a `UV_INDEX` variable, or `NETRC`, the agent reports the override rather than reporting the device compliant.

The compiled preview shows each file the policy manages, for the clients you selected:

```
# ~/.netrc
# ... your existing .netrc configuration ...
#stepsecurity-package-config-credential-dmg-begin
machine <registry-host>
login step-security
password step_xxxxxxxx::dev:<DEVICE-SERIAL-ID>
#stepsecurity-package-config-credential-end
```

```
# pip.conf
# ... your existing pip.conf configuration ...
# BEGIN StepSecurity Package Configuration pip -- managed by dmg
[global]
index-url = https://<pypi-registry-url>
no-index = false
# END StepSecurity Package Configuration pip
```

```
# uv.toml
# ... your existing uv.toml configuration ...
# BEGIN StepSecurity Package Configuration uv -- managed by dmg
index-strategy = "first-index"

[[index]]
name = "stepsecurity"
url = "https://<pypi-registry-url>"
default = true
authenticate = "always"
# END StepSecurity Package Configuration uv
```

#### **Go**

The **Secure Go module proxy** enforcement:

* **Writes** the shared Secure Registry credential to the user's `~/.netrc`.
* **Sets** the Secure Registry as the sole `GOPROXY` in the user's `go/env` file.
* **Verifies** it on every check-in. If a developer edits it, the agent restores it and reports drift.
* **Restores** the user's previous `GOPROXY` when the policy is detached.

`GOPRIVATE`, `GONOPROXY`, `GONOSUMDB`, and `GOSUMDB` are never touched, so private module settings keep working as configured.

```
# go/env
# ... your existing go/env configuration ...
# BEGIN StepSecurity Package Configuration go -- managed by dmg
GOPROXY=https://<go-registry-url>
# END StepSecurity Package Configuration go
```

The Go policy writes the same `~/.netrc` credential block shown for PyPI.

**The Shared `.netrc` Credential**

PyPI and Go policies authenticate with a single Secure Registry credential stored in the user's `~/.netrc` (`_netrc` on Windows). The credential is written once and shared by both policies, and it stays on the device until both policies are detached.

The credential is issued only to the agent and to the MDM script export. It is never returned by the API or shown in the console. As with npm, the tenant token carries a per-device `:dev:` suffix, so registry access from each device is attributed separately.

#### **Verifying the Result**

Once the policy is delivered, the Package Configs page under **Developer Machines** > **Packages** audits which registry each machine actually resolves from. Use it to confirm the policy took effect across the fleet, and to find machines still resolving from the public registry.


---

# 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, and the optional `goal` query parameter:

```
GET https://docs.stepsecurity.io/developer-machines/device-policy/policies.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
