> 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/packages/secure-registry/policy.md).

# Policy

The **Policy** tab is where you configure the security controls that Secure Registry enforces. Every package request that flows through Secure Registry is evaluated against the controls you enable here before a response is returned.

Open the **Policy** tab and use the **Registry** selector to choose an ecosystem (e.g npm), then toggle each control on or off. Controls are configured independently per ecosystem, so each ecosystem's policy can differ. Not every control is available for every ecosystem; see Control availability by ecosystem below. Click **Save Changes** to apply.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2Ftdli4DbgXY9KjQ9h7Sht%2FScreenshot%202026-10-16%20at%2010.55.51.png?alt=media&amp;token=e2f6ae51-2f91-47aa-8709-38e7705a180c" alt=""><figcaption></figcaption></figure>

#### Control availability by ecosystem

Controls are configured independently per ecosystem, and not all controls are available in every ecosystem yet. Controls marked **Coming soon** appear in the Policy tab but cannot be enabled.

| Control                      | npm            | PyPI           | Maven          | NuGet          | Go             | RubyGems       | Cargo          | Packagist (PHP) |
| ---------------------------- | -------------- | -------------- | -------------- | -------------- | -------------- | -------------- | -------------- | --------------- |
| **Cooldown Period**          | Available      | Available      | Available      | Available      | Available      | Available      | Available      | Available       |
| **Compromised Packages**     | Available      | Available      | Available      | Available      | Available      | Available      | Available      | Available       |
| **Custom Block List**        | Available      | Available      | Coming soon    | Available      | Available      | Available      | Available      | Available       |
| **Released Tags Only**       | Not applicable | Not applicable | Not applicable | Not applicable | Available      | Not applicable | Not applicable | Not applicable  |
| **Typosquatting Protection** | Available      | Coming soon    | Coming soon    | Coming soon    | Not applicable | Not applicable | Not applicable | Not applicable  |
| **Registry Settings**        | Available      | Not applicable | Not applicable | Not applicable | Available      | Not applicable | Not applicable | Available       |

Each cell has one of three meanings:

* **Available**: the control appears in the Policy tab for that ecosystem and can be enabled.
* **Coming soon**: the control appears in the Policy tab for that ecosystem and cannot be enabled yet. It is on the roadmap.
* **Not applicable**: the control has no equivalent in that ecosystem. It is either absent from the Policy tab or shown as **Not applicable** in the product, and it is not on the roadmap.

### Cooldown Period

Blocks packages published within a configurable number of days, giving the community and StepSecurity's SOC time to vet new releases before they reach your environment. Set the cooldown window in the **Period (days)** field; the default is 2.

Cooldown is the first line of defense against zero-day supply chain attacks. Most malicious packages are discovered within 24 hours of publication, so a multi-day cooldown shifts the discovery window outside your installation window.

#### **Exempted Packages**

Use the **Exempted Packages** field to allow specific packages or scopes to bypass the cooldown window. Type a pattern and press **Enter** to add it. Patterns are matched as regular expressions, so you can exempt a single version, an entire package, or a whole scope.

| Pattern                          | What it exempts                      |
| -------------------------------- | ------------------------------------ |
| `react@2.3.4`                    | A single version of one package      |
| `lodash@*`                       | All versions of one package          |
| `@scope/*`                       | All packages under a scope           |
| `example-org/example-repo@1.2.0` | A single version of one package      |
| `example-org/*`                  | All packages published by one vendor |

Exempted packages still flow through Secure Registry and are evaluated by every other enabled control (for example, Compromised Packages). Only the cooldown check is skipped.

**Need an urgent version now?** If a version inside the cooldown window must be installed immediately (for example, a critical security patch), add the exact version as an exemption (such as `react@2.3.4`), click **Save Changes**, and retry the install. Prefer an exact-version pattern over a package-wide one: it is self-limiting, since it never covers future versions, and once the version ages beyond the cooldown window it would pass anyway.

Use exemptions sparingly. Each exempted pattern is an explicit opt-out of the zero-day window, so reserve them for packages you have already vetted or that you control internally.

### Compromised Packages

Blocks installs of package versions that StepSecurity's SOC or the broader security community has flagged as compromised or malicious. When this control is on, any request for a flagged version is blocked, and the evaluation is recorded in the [Policy Evaluations](/packages/secure-registry/policy-evaluations.md) log.

This control catches packages whose maintainer account was hijacked, packages that were published with embedded malware, and packages reported as malicious after publication. Unlike Cooldown, which buys time for the community to discover an attack, Compromised Packages enforces against attacks that have already been confirmed.

Compromised Packages is independent of the cooldown window: a flagged version is blocked whether or not it falls inside the cooldown period, and exempting a package from cooldown does **not** exempt it from this control.

### Custom Block List

Blocks specific packages or versions from being served through your registry, regardless of publication date or compromise status. Use it to enforce internal bans: a package your security team has rejected, a version with a known incompatibility, or a dependency you are migrating away from.

Turn the control on, then add one pattern per entry. The block list matches glob patterns, so you can block a single version, a version range, an entire package, or a whole scope.

| Pattern                          | What it blocks                       |
| -------------------------------- | ------------------------------------ |
| `lodash@4*`                      | All 4.x versions of one package      |
| `lodash@*`                       | All versions of one package          |
| `@scope/*`                       | All packages under a scope           |
| `example-org/example-repo@1.2.*` | All 1.2.x versions of one package    |
| `monolog/monolog@*`              | All versions of one package          |
| `example-org/*@*`                | All packages published by one vendor |

{% hint style="warning" %}
The Custom Block List and the Cooldown **Exempted Packages** field use different matching syntaxes. Custom Block List patterns are globs; Exempted Packages patterns are regular expressions. The two are not interchangeable, even though the example patterns look similar.&#x20;
{% endhint %}

The Custom Block List is evaluated independently of every other control. A package on the block list is blocked even if it is outside the cooldown window, is not flagged as compromised, and passes the typosquatting check.

### Released Tags Only

**Go only.** Restricts a module to versions that exist as a published release tag. When a module is listed here, Secure Registry refuses to resolve it from a commit hash, a branch name, or a pseudo-version such as `v0.0.0-20241114170450-2d3c2a9cc518`.

Go is the only supported ecosystem where a dependency does not have to be a release. `go get` will happily resolve a module to whatever is at the tip of a branch or to any commit in its history, and the resulting pseudo-version is a legitimate, checksum-verified, reproducible dependency as far as the toolchain is concerned. That is convenient during development and it is also a way for code that no maintainer ever tagged, reviewed, or announced to end up in a build.

Released Tags Only closes that path. It also narrows the surface that your other controls have to reason about, since a release tag is the unit that Cooldown Period and Compromised Packages evaluate.

**Adding modules**

Turn the control on, type a module path in the **Released Tags Only** field, and press **Enter**.

Entries match on the **module path only**, with no version attached. Use `*` to apply the rule to every module.

| Entry                            | What it applies to                     |
| -------------------------------- | -------------------------------------- |
| `*`                              | Every module resolved through Go       |
| `github.com/example-org/*`       | All modules under one repository owner |
| `github.com/example-org/widgets` | One module                             |

{% hint style="info" %}
Start with the modules you consider load bearing rather than with `*`. Some Go dependencies are only ever available as pseudo-versions because their maintainers do not tag releases, and a tenant-wide rule will block those builds until you narrow it.
{% endhint %}

Released Tags Only is evaluated independently of every other control. A module that passes it is still evaluated by Cooldown Period, Compromised Packages, and the Custom Block List.

### Typosquatting Protection

Blocks packages whose names closely resemble popular packages, protecting against typosquatting attacks. When this control is on, a request for a package whose name is a likely typo of a well-known package is blocked, and the evaluation is recorded in the [Policy Evaluations](/packages/secure-registry/policy-evaluations.md) log.

#### Whitelisted Packages

Use the **Whitelisted Packages** field to allow specific packages through the typosquatting check. Type a package name and press **Enter** to add it.

Unlike the Cooldown Exempted Packages field, which matches regular expressions, the whitelist requires **exact package names**. Specify the full name of each package you want to allow (for example, `@scope/package-1` or `lodash`); patterns such as `lodash@*` or `@scope/*` are not supported here.

Whitelist a package when its name legitimately resembles a popular package and the Typosquatting control is flagging it as a false positive. Whitelisting affects only the typosquatting check; the package is still evaluated by every other enabled control.

### Registry Settings

npm, Go, and Packagist (PHP) each have a **Registry Settings** panel for registry behavior that sits outside the blocking controls, such as download routing and the messages developers see when a request is blocked. Settings are configured per ecosystem, alongside that ecosystem's policy.

#### **npm Registry Settings**

The **npm Registry Settings** panel opens as a side panel over the Policy tab and configures how Secure Registry behaves for npm. Changes in the panel are saved separately from the controls: click **Save Changes** in the panel to apply them.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FcS66RgSXWU4PcHRnMraz%2FScreenshot%202026-10-12%20at%2017.31.29.png?alt=media&amp;token=e301fe60-7dea-4cb2-9e79-f76dbff2be07" alt=""><figcaption></figcaption></figure>

**Tarball URL Rewriting**

Rewrites the tarball URLs in npm metadata responses so that package downloads are routed through Secure Registry instead of the public npm registry.

**Block Message**

Adds your own text to the error returned when a policy control blocks a package request. Use it to tell developers what to do next, for example how to request an exception from your security team.

* Secure Registry appends the message to the error body of the blocked request and adds the full stop that separates it from the preceding text.
* The message is added for blocks by every control except **Cooldown Period**. Cooldown Period hides recent versions from package metadata, so developers see the **Hidden Versions Notice** for those versions.
* The message can be up to 500 characters.
* The message supports placeholders that are filled in with details of the blocked request. Click **Available placeholders** below the field to see the full list.

Example:

`Blocked by {{control}} policy. Need {{package}}? Request an exception from your security team.`

**How npm displays the block message**

When the field is empty, npm shows only Secure Registry's reason for the block. In this example, `lodash` matches a Custom Block List pattern:

```
$ npm install lodash
npm error code E403
npm error 403 403 Forbidden - GET https://registry.stepsecurity.io/javascript/lodash - 'lodash' is blocked by security policy with StepSecurity: 'lodash' matches a configured block list pattern
npm error 403 In most cases, you or one of your dependencies are requesting
npm error 403 a package version that is forbidden by your security policy, or
npm error 403 on a server you do not have access to.
npm error A complete log of this run can be found in: /root/.npm/_logs/2026-10-19T16_40_56_487Z-debug-0.log
```

With this block message configured:

`If you wish to use this package '{{package}}' Ask in #platform-security with reason or reach out to support-test@test.com.`

the same install returns:

```
$ npm install lodash
npm error code E403
npm error 403 403 Forbidden - GET https://registry.stepsecurity.io/javascript/lodash - 'lodash' is blocked by security policy with StepSecurity: 'lodash' matches a configured block list pattern. If you wish to use this package 'lodash' Ask in #platform-security with reason or reach out to support-test@test.com.
npm error 403 In most cases, you or one of your dependencies are requesting
npm error 403 a package version that is forbidden by your security policy, or
npm error 403 on a server you do not have access to.
npm error A complete log of this run can be found in: /root/.npm/_logs/2026-10-19T16_42_38_166Z-debug-0.log
```

Your message appears at the end of the `403 Forbidden` line, after Secure Registry's reason, with `{{package}}` replaced by the package name. The lines that start with `In most cases` are npm's standard text for any 403 response, and they stay the same whether or not you configure a block message.

**Hidden Versions Notice**

Replaces the notice npm shows when versions of a package are hidden by policy. Leave the field empty to use the default notice.

* The notice can be up to 300 characters.
* The notice supports placeholders. Click **Available placeholders** below the field to see the full list.

Example:

`{{count}} version(s) of {{package}} hidden by policy. {{details}}.`

**How npm displays the hidden versions notice**

When Secure Registry removes versions from a package's metadata, for example versions still inside the Cooldown Period window, npm resolves to the newest version that remains and the install continues. npm prints the notice as an `npm notice` line so developers know that some versions were held back. Requests like these are recorded as **Modified** in the Policy Evaluations log.

When the field is empty, npm shows the default notice:

```
$ npm install undici-types
npm notice StepSecurity: 6 version(s) of undici-types are hidden by your registry policy. cooldown (14 days): 8.12.3, 8.12.2 (+4 more). They may still be listed on the public registry.

up to date, audited 2 packages in 2s

found 0 vulnerabilities
```

With this notice configured:

`{{count}} version(s) of {{package}} hidden by policy. {{details}}. Need an exception? Ask in #platform-security with reason or reach out to support-test@test.com.`

npm shows:

```
$ npm install undici-types
npm notice 6 version(s) of undici-types hidden by policy. cooldown (14 days): 8.12.3, 8.12.2 (+4 more). Need an exception? Ask in #platform-security with reason or reach out to support-test@test.com.

added 1 package in 2s
```

In this example, `{{count}}` is replaced with the number of hidden versions, `{{package}}` with the package name, and `{{details}}` with the control that hid the versions, its window, and the hidden versions (`cooldown (14 days): 8.12.3, 8.12.2 (+4 more)`).

{% hint style="info" %}
A custom notice replaces the whole default notice, including the `StepSecurity:` prefix and the closing `They may still be listed on the public registry.` sentence. Include any of that wording you still want developers to see.
{% endhint %}

#### **Go Registry Settings**

Go has a **Go Registry Settings** panel, opened from the link at the top right of the Policy tab.

<figure><img src="https://754495266-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQJRZY4cfEeY3I7DXTOCp%2Fuploads%2FvzumE9yvsL7EIubnaWGV%2FScreenshot%202026-10-12%20at%2017.33.37.png?alt=media&amp;token=4688728c-63b9-41a1-a9a3-bc2d2ea0dddb" alt=""><figcaption></figcaption></figure>

### **Packagist Registry Settings**

The **Packagist Registry Settings** panel opens as a side panel over the Policy tab when **Packagist (PHP)** is selected in the **Registry** selector, from the link at the top right. It configures how Secure Registry behaves for Composer. Changes in the panel are saved separately from the controls: click **Save Changes** in the panel to apply them.

#### **Dist URL Rewriting**

Routes package downloads through Secure Registry so every package zip (dist) is checked against your Packagist policy. Composer records each package's download URL in `composer.lock`, so lock files written before you switched to Secure Registry keep downloading straight from the source host. After you turn on Dist URL Rewriting, refresh and commit your lock files as described in Composer lock files.

#### **Keep Git Source**

Keeps git clone entries in package metadata. Composer uses these entries when it installs a package as a git working copy in `vendor/` (for example, with `--prefer-source`). Turn this on only if your developers need git working copies in `vendor/`.

#### **Block Branch Versions**

Hides branch versions (for example, `dev-main` or `2.x-dev`) from package metadata, so Composer can resolve packages only to tagged releases. Many projects pin a branch, so check your `composer.json` files for branch constraints before you turn this on.

### Saving changes

Changes to the Policy tab take effect only after you click **Save Changes**. The page records who last saved the policy and when, so you have a basic audit trail of policy changes per ecosystem.


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.stepsecurity.io/packages/secure-registry/policy.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
