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_packages variable to false in 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

FormatDescription
GoApplies 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.
MavenApplies 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.
npmApplies to packages where the time field has been populated by the upstream source.
NuGetNuGet 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.
PythonApplies 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.
ErrorCause
404 Not FoundThe 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 ForbiddenThe package has been quarantined, or you do not have the requisite permissions to access the package.
200 OKThe 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

FieldParameter nameDescription
Policy namenameA 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.
DescriptiondescriptionA 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.
EnabledenabledA toggle that indicates whether the cooldown policy is enabled or disabled.

Rego variables

FieldVariable nameDescription
Included repositoriesincluded_repositoriesThe repositories that the cooldown policy applies to.

By default, the cooldown policy applies to all repositories in a workspace unless configured otherwise.
Excluded repositoriesexcluded_repositoriesThe repositories that the cooldown policy does not apply to.

By default, the cooldown policy applies to all repositories in a workspace unless configured otherwise.
Formatsupported_formatsThe package formats the policy applies to.

Currently supported: go, maven, npm, nuget, and python.
Cooldown periodwithin_past_daysThe 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 useinclude_local_packagesUnchecked 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.

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.

Note

Only one cooldown policy can be created per workspace.
  1. From the overview page in the Cloudsmith web app, go to the Policies tab and click Policy as code.
  2. Click + Create new policy.
  3. Select Start from a template, and then select the Cooldown period template.
    The Cooldown period policy template opens.
  4. 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.
  5. (Optional) Click the edit icon next to the policy name to customize the policy name and description.
  6. Customize the policy options. For guidance on which policy options are configurable, see Policy configuration.
  7. Click Save policy to save and apply your changes.

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.

You can enable a cooldown policy from the Policies tab of the overview page in the Cloudsmith web app:

  1. From the overview page in the Cloudsmith web app, go to the Policies tab.
  2. Click Policy as code.
  3. 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.
  4. Click the toggle to enable the policy.

You can disable a cooldown policy from the Policies tab of the overview page in the Cloudsmith web app:

  1. From the overview page in the Cloudsmith web app, go to the Policies tab.
  2. Click Policy as code.
  3. 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.
  4. Click the toggle to disable the policy.

You can delete a cooldown policy from the Policies tab of the overview page in the Cloudsmith web app:

  1. From the overview page in the Cloudsmith web app, go to the Policies tab.
  2. Click Policy as code.
  3. In the policy list, find the cooldown policy that you want to delete.
  4. Click the options menu next to the policy.
  5. Click Delete policy.
  6. 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:

Policy actions:

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_days
    • supported_formats
    • included_repositories
    • excluded_repositories
    • include_local_packages
  • Uses only supported operators:
    • ==
    • !=
    • >
    • >=
    • <
    • <=
    • in
    • not
  • Uses only supported fields and functions:
    • input.v0.package.name
    • input.v0.package.version
    • input.v0.package.format
    • input.v0.package.filename
    • input.v0.package.is_local
    • input.v0.package.upstream_metadata.published_at
    • input.v0.package.uploaded_at
    • input.v0.repository.slug
    • startswith
    • endswith
    • contains
    • regex_match
    • re_match
    • regex.match
    • time.now_ns
    • time.add_date
    • time.parse_rfc3339_ns

Example policy:

rego
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.