Policy as code
Cooldown policy
A cooldown policy hides newly published versions of packages from your repository index until they reach a minimum age based on the package version’s publish date. Packages that do not meet the age requirement are hidden from the index, preventing package managers from accessing them. This protects your supply chain from recently published packages that may carry malware or have not yet undergone sufficient community scrutiny, while automatically resolving to the latest compliant version when one is available.
A cooldown policy applies at the Cloudsmith index level and is supported for Go, Maven, npm, NuGet, and Python packages that originate from a public upstream source. It can apply to packages proxied directly from an upstream source as well as packages that are cached in your Cloudsmith workspace.
Automatic reversal
If a cooldown policy is updated, disabled, or deleted, packages will be re-evaluated. This is different from other policies that only apply to cached packages and do not have automatic reversal.
How it works
A cooldown policy is a templated Rego policy with specific customizable settings and variables. For information about which parts of your cooldown policy are customizable, see Policy configuration.
Only one cooldown policy can be created per workspace.
A cooldown policy is evaluated directly on the package index, which is made up of two types of packages:
- Upstream cached packages already in your Cloudsmith workspace.
- Packages that originate from an upstream source but are not yet cached in your Cloudsmith workspace.
When a cooldown policy is enabled, packages that do not meet the configured age requirement are hidden from the index.
- Packages that are not yet cached in Cloudsmith and need to be requested directly from a public upstream source are hidden from the index. They will not be downloaded or cached in Cloudsmith.
- Packages that are already cached in Cloudsmith are quarantined and hidden from the index until the cooldown period elapses. Once the cooldown period expires, the package is unquarantined and becomes available for download and visible in the index, provided it does not violate any other active policies.
Tip
You can exclude packages that are already cached in your Cloudsmith workspace from the policy scope:
- Via the web app: By leaving the Apply to packages already in use option unchecked in the Edit policy view.
- Via the API: By setting the
include_local_packagesvariable tofalsein your Rego policy logic.
Decision logs for a cooldown policy are only generated for packages that are already cached in your Cloudsmith workspace. They are accessible via the Cloudsmith web app and the Cloudsmith API.
Cloudsmith determines a package's age by using metadata retrieved from the upstream source. Where package age metadata is not populated, the cooldown policy will not apply, meaning the package will not be hidden from the index.
Supported package formats
| Format | Description |
|---|---|
| Go | Applies to packages where the Time field has been populated by the Go module proxy. This field is set when the proxy first fetches and caches a tagged version, and is exposed via the proxy's @v/<version>.info metadata. This timestamp is typically very close to, but not always identical to, the original tag creation time. Cooldown policies are not supported for private GOPROXY upstreams. |
| Maven | Applies to packages where the Last-Modified header has been populated by the upstream Maven repository. Cloudsmith uses this header to populate the published_at timestamp. This value is typically a close approximation of the actual package publish date. |
| npm | Applies to packages where the time field has been populated by the upstream source. |
| NuGet | NuGet V2: Applies to packages where the data:Published field in the OData feed response has been populated by the upstream source. NuGet V3: Applies to packages where the published field of the catalog leaf has been populated by the upstream source. |
| Python | Applies to packages where the upload-time field has been populated by the upstream source. |
The developer experience
What developers experience depends on how their dependencies are specified:
- Compliant version available: The package manager resolves to the latest compliant version. Non-compliant versions are skipped automatically.
- No compliant version available: Cloudsmith returns a 404 Not Found or 403 Forbidden error - this is common when pinned versions or a lockfile is used to resolve dependencies. Behavior may vary in different package managers. To resolve this, choose a version that satisfies the cooldown requirement.
| Error | Cause |
|---|---|
| 404 Not Found | The specific pinned version you requested does not exist, or the version (or version within your declared range) is not old enough to be allowed. |
| 403 Forbidden | The package has been quarantined, or you do not have the requisite permissions to access the package. |
| 200 OK | The requested version is accessible and has been downloaded. |
Impact on existing packages
If caching is enabled on upstreams, packages previously pulled through Cloudsmith are already stored in your workspace. Excluding those from the policy means your existing builds are unlikely to break, because only new package versions entering the workspace are subject to the cooldown period. If a cooldown policy is applied to packages that are already in your workspace, or if upstreams are proxy-only, builds are more likely to break because non-compliant versions may be hidden.
Enhanced 403 error messaging
For supported package managers, Cloudsmith returns a customizable error message to the native client when a package is hidden from the index. The message is returned as part of the standard 403 response body and surfaced directly by the package manager, with no client-side configuration required.
The message includes:
- Policy name: The name of the cooldown policy that matched the package.
- Policy description: The policy description field, which you can use to include internal guidance. For example, who to contact, or a link to internal documentation.
- Policy ID: The unique identifier for the policy action, for reference and troubleshooting.
Supported package managers
- uv (Python)
- npm
- Maven
Policy configuration
Note
A cooldown policy is always set to Terminal, which prevents the evaluation of any further policies if this policy matches. This setting cannot be edited.
Note
Index-applicable policies have a higher precedence than any other policy. This setting cannot be edited.
Policies within a workspace are ordered based on the precedence integer defined in each policy. The policy with the lowest number is evaluated first, then each remaining policy is evaluated in order of ascending precedence.
You can configure and edit the following fields for your cooldown policy:
API parameters
| Field | Parameter name | Description |
|---|---|---|
| Policy name | name | A display name for the cooldown policy. The default policy name can be customized as needed. For package managers where enhanced 403 error messaging is supported, the policy name is returned with any 403 error. |
| Description | description | A description of the cooldown policy. The default policy description can be customized as needed. For package managers where enhanced 403 error messaging is supported, the policy description is returned with any 403 error. |
| Enabled | enabled | A toggle that indicates whether the cooldown policy is enabled or disabled. |
Rego variables
| Field | Variable name | Description |
|---|---|---|
| Included repositories | included_repositories | The repositories that the cooldown policy applies to. By default, the cooldown policy applies to all repositories in a workspace unless configured otherwise. |
| Excluded repositories | excluded_repositories | The repositories that the cooldown policy does not apply to. By default, the cooldown policy applies to all repositories in a workspace unless configured otherwise. |
| Format | supported_formats | The package formats the policy applies to. Currently supported: go, maven, npm, nuget, and python. |
| Cooldown period | within_past_days | The minimum age, in days, a package must reach before it appears in the index. Packages published more recently than this value are hidden from the index. |
| Apply to packages already in use | include_local_packages | Unchecked by default for policies created in the web app. For a cooldown policy created via the API or Terraform provider, you must manually set this value to true or false. When unchecked or set to false, packages already in Cloudsmith will not be quarantined by the cooldown policy or hidden from the repository index. |
Creating and managing a cooldown policy via the Cloudsmith web app (recommended method)
To create and manage a cooldown policy, you must have access to policy as code in your workspace.
Important
Policy changes may take a few minutes to take effect on cached packages.
Create a cooldown policy via the Cloudsmith web app (recommended method)
Note
Only one cooldown policy can be created per workspace.
- From the overview page in the Cloudsmith web app, go to the Policies tab and click Policy as code.
- Click + Create new policy.
- Select Start from a template, and then select the Cooldown period template.
The Cooldown period policy template opens. - Click Use template to create the cooldown policy. When created from a template, your cooldown policy is disabled by default.
The cooldown policy opens in the Edit policy view. - (Optional) Click the edit icon next to the policy name to customize the policy name and description.
- Customize the policy options. For guidance on which policy options are configurable, see Policy configuration.
- Click Save policy to save and apply your changes.
Edit a cooldown policy via the Cloudsmith web app (recommended method)
To edit an existing cooldown policy, go to the Policies tab of the overview page in the Cloudsmith web app, click Policy as code, and select the cooldown policy from the list. The policy opens in read-only mode. Click Edit policy to make changes.
For more information about editable policy fields, see Policy configuration.
Enable a cooldown policy via the Cloudsmith web app (recommended method)
You can enable a cooldown policy from the Policies tab of the overview page in the Cloudsmith web app:
- From the overview page in the Cloudsmith web app, go to the Policies tab.
- Click Policy as code.
- In the policy list, find the cooldown policy that you want to enable. Hovering over the toggle next to the policy displays Click to enable policy.
- Click the toggle to enable the policy.
Disable a cooldown policy via the Cloudsmith web app (recommended method)
You can disable a cooldown policy from the Policies tab of the overview page in the Cloudsmith web app:
- From the overview page in the Cloudsmith web app, go to the Policies tab.
- Click Policy as code.
- In the policy list, find the cooldown policy that you want to disable. Hovering over the toggle next to the policy displays Click to disable policy.
- Click the toggle to disable the policy.
Delete a cooldown policy via the Cloudsmith web app (recommended method)
You can delete a cooldown policy from the Policies tab of the overview page in the Cloudsmith web app:
- From the overview page in the Cloudsmith web app, go to the Policies tab.
- Click Policy as code.
- In the policy list, find the cooldown policy that you want to delete.
- Click the options menu next to the policy.
- Click Delete policy.
- In the Delete policy: DANGER view that opens, click Delete to confirm that you want to delete the policy.
Creating and managing a cooldown policy via the Cloudsmith API
To create and manage a cooldown policy, you must have access to policy as code in your workspace.
Important
Policy changes may take a few minutes to take effect on cached packages.
Policy actions are not automatically generated for cooldown policies created via the API
When you create a cooldown policy from the Cooldown period template in the Cloudsmith web app, Cloudsmith creates the required policy action for you. When you create a cooldown policy via the API, you must create the policy action yourself.
A cooldown policy with no policy action is evaluated and matches packages, but does not hide anything from the index.
A cooldown policy and its actions can be created and managed via the following endpoints.
Policies:
- Create a policy:
POST /v2/workspaces/{workspace}/policies/ - Update a policy:
PUT /v2/workspaces/{workspace}/policies/{policy_slug}/ - Partially update a policy:
PATCH /v2/workspaces/{workspace}/policies/{policy_slug}/ - List policies:
GET /v2/workspaces/{workspace}/policies/ - Retrieve a policy:
GET /v2/workspaces/{workspace}/policies/{policy_slug}/ - Delete a policy:
DELETE /v2/workspaces/{workspace}/policies/{policy_slug}/
Policy actions:
- Create an action:
POST /v2/workspaces/{workspace}/policies/{policy_slug}/actions/ - List actions:
GET /v2/workspaces/{workspace}/policies/{policy_slug}/actions/ - Retrieve an action:
GET /v2/workspaces/{workspace}/policies/{policy_slug}/actions/{action_slug}/ - Partially update an action:
PATCH /v2/workspaces/{workspace}/policies/{policy_slug}/actions/{action_slug}/ - Update an action:
PUT /v2/workspaces/{workspace}/policies/{policy_slug}/actions/{action_slug}/ - Delete an action:
DELETE /v2/workspaces/{workspace}/policies/{policy_slug}/actions/{action_slug}/
Policy logic must meet specific criteria to be recognized and applied as a cooldown policy by Cloudsmith.
Ensure that your policy logic:
- Is syntactically correct
- Has a match rule
- Contains the following required variables:
within_past_dayssupported_formatsincluded_repositoriesexcluded_repositoriesinclude_local_packages
- Uses only supported operators:
==!=>>=<<=innot
- Uses only supported fields and functions:
input.v0.package.nameinput.v0.package.versioninput.v0.package.formatinput.v0.package.filenameinput.v0.package.is_localinput.v0.package.upstream_metadata.published_atinput.v0.package.uploaded_atinput.v0.repository.slugstartswithendswithcontainsregex_matchre_matchregex.matchtime.now_nstime.add_datetime.parse_rfc3339_ns
Example policy:
package cloudsmith
import rego.v1
default match := false
# --- Settings ---
# Cooldown period in days. Packages published more recently than this
# are hidden from the index.
within_past_days := 14
# Currently supported formats: Go, npm, NuGet, Maven, and Python.
supported_formats := {"npm", "python", "go", "nuget", "maven"}
# Repository inclusion list, by repository slug.
# Leave empty to apply to all repositories.
included_repositories := {}
# Repository exclusion list, by repository slug.
# All repositories listed here will be excluded even if they're in
# the `included_repositories` list.
excluded_repositories := {}
# Only proxied packages are evaluated by default, these can be from
# proxy-only upstreams or new upstream packages that aren't cached
# in this workspace yet. Cached packages are not affected unless this
# is set to `true`.
include_local_packages := false
# --- Policy logic - do not change below this line ---
match if count(reason) != 0
# Whether to evaluate this package at all. Skips cached packages unless
# `include_local_packages` is enabled.
_should_evaluate if {
not input.v0.package.is_local
}
_should_evaluate if {
include_local_packages == true
}
_repo_allowed if {
count(included_repositories) == 0
not input.v0.repository.slug in excluded_repositories
}
_repo_allowed if {
input.v0.repository.slug in included_repositories
not input.v0.repository.slug in excluded_repositories
}
# Produce a reason when the package is in scope
# and published within the cooldown window.
reason contains msg if {
_should_evaluate
_repo_allowed
pkg := input.v0.package
within_past_days_date := time.add_date(time.now_ns(), 0, 0, 0 - within_past_days)
publish_date := time.parse_rfc3339_ns(pkg.upstream_metadata.published_at)
publish_date >= within_past_days_date
pkg.format in supported_formats
msg := sprintf(
"Package %v/%v (%v) is within the %v-day cooldown period: published %v",
[pkg.name, pkg.version, pkg.format, within_past_days, pkg.upstream_metadata.published_at],
)
}Exemptions
When creating a cooldown policy, you can exclude specific repositories, formats, and local packages from the policy scope by using the options described in Policy configuration.
Note
Cooldown policy does not currently support exemptions for specific package versions. If a specific package version needs to bypass the cooldown policy urgently, we recommend that your security or platform team downloads the required package directly and uploads it into Cloudsmith manually. The cooldown policy will not apply to these packages because they have no upstream publication metadata to indicate the package age.
Viewing packages that violate your cooldown policy
Upstream packages that are already cached in your Cloudsmith workspace and violate your cooldown policy are displayed as HIDDEN in the Cloudsmith web app and via the Cloudsmith API. These packages cannot be downloaded, unhidden, or unquarantined.
To find packages currently hidden due to a cooldown policy, search your workspace using the search term status:hidden:
Hovering over the HIDDEN status in the web app will display why the package is hidden:
When a cooldown policy is deleted or disabled, packages previously displayed as HIDDEN revert to their prior status.
After a cooldown policy is created, it may take several minutes for the non-compliant packages in your Cloudsmith workspace to appear as HIDDEN.