--- title: "Control network access from jobs" description: "Allow the software sources and services your jobs need while blocking other outbound traffic" source: "https://docs.craci.com/guides/setup-action-network/" --- CRACI can control which external services a job may reach and detect supported package downloads for generated SBOMs. Presets cover common software sources. Custom `sources` add private software sources. `connections` allow other destinations and protocols. Organization administrators can create reusable configurations under **Settings → Runner Templates**. Select one with the setup action's `template` input. Without a `template` input, CRACI uses the built-in `default` template. A workflow that includes an explicit `network` input replaces the selected template's network policy for that job. Add `network` when you want to restrict outbound connections. Without a `network` block, CRACI enables every built-in preset and allows connections that do not match a preset. With a `network` block, CRACI still enables every preset, but blocks unmatched connections unless you set `network.default: allow`. CRACI validates the configuration before the job starts. Unknown fields are rejected rather than ignored, so a misspelled setting cannot silently change the policy. CRACI always allows CI job and cache management traffic to GitHub services. See [Runner configuration](/reference/runner-configuration/) for the other `cracicorp/setup@v1` inputs. ## Start with CRACI network features This policy enables every built-in preset. CRACI detects supported package downloads for generated SBOMs and blocks traffic that does not match a preset, source, or connection: ```yaml - uses: cracicorp/setup@v1 with: network: | # Keep every built-in preset and block other unmatched connections. {} ``` You do not need to list the presets. They are all enabled when `network.presets` is omitted. ## Choose a policy Presets let CRACI match known software sources. Custom software sources add package detection for private registries. Connections allow destinations that match TLS, TCP, UDP, or ICMP rules. `network.default` controls traffic that matches none of these, including other HTTP and HTTPS traffic. | Configuration | Package detection | Other HTTP and HTTPS | Other unmatched connections | | ----------------------------------------------- | ------------------------------------------ | ----------------------------------------------------------------- | --------------------------- | | Omit `network` | Enabled for every built-in software source | Allowed | Allowed | | `network: {}` | Enabled for every built-in software source | Blocked | Blocked | | `network.default: deny`, `network.presets: []` | Disabled | Blocked | Blocked | | `network.default: allow`, `network.presets: []` | Disabled | Direct, end-to-end connections using original server certificates | Allowed | `network.presets` has three states: | `network.presets` value | Effective behavior | | ----------------------- | ----------------------------------- | | Omitted | Enable every built-in preset | | `[]` | Disable every built-in preset | | Preset names | Enable only the listed preset names | ## Select built-in software sources The following policy enables package detection for PyPI downloads and records GitHub repository access. It blocks other unmatched traffic. The `github` preset is for repository access; traffic needed to run the GitHub Actions job and manage its cache remains allowed independently. ```yaml - uses: cracicorp/setup@v1 with: network: | default: deny presets: [pypi, github] ``` ## Use standard CI networking To disable CRACI's built-in package detection and matching, select the built-in `audit` runner template. Connections are direct and end to end, including package, SSH, and Kubernetes traffic. CRACI does not detect packages downloaded by these jobs. ```yaml jobs: integration: runs-on: [craci] steps: - uses: cracicorp/setup@v1 with: template: audit ``` For a one-job override, the equivalent `network` configuration is still `default: allow` with `presets: []`. ## Allow a Kubernetes API using mutual TLS Add a TLS connection for the API server hostname and port. The client certificate remains between `kubectl` and the Kubernetes API server. ```yaml - uses: cracicorp/setup@v1 with: network: | connections: - tls: serverNamePatterns: [kube-apiserver.example.com] ports: [6443] - name: Access Kubernetes env: KUBECONFIG: ${{ runner.temp }}/kubeconfig run: kubectl get namespaces ``` Your kubeconfig must use `kube-apiserver.example.com:6443`. The `alpn` field is optional. The hostname must resolve normally from the job. For a kubeconfig that connects directly to an IP address, use `cidrs` instead of `serverNamePatterns`. ## Allow a private package registry Custom sources extend the built-in presets. This example allows a private Python package index in addition to every built-in source: ```yaml - uses: cracicorp/setup@v1 with: network: | default: deny sources: - pypi: urls: - https://packages.example.com/api/pypi/python/simple ``` Each URL is an allowed package endpoint. If your registry exposes multiple independent endpoints, list each URL explicitly. ### Use Artifactory package repositories Add the complete registry URL to the setup action. For example, PyPI and NPM: ```yaml - uses: cracicorp/setup@v1 with: network: | default: allow sources: - pypi: urls: - https://artifactory.example.com/artifactory/api/pypi/pypi-repository/simple - npm: urls: - https://artifactory.example.com/artifactory/api/npm/npm-repository ``` Replace the hostname and repository keys with your Artifactory values. Write the URLs literally: repository variables such as `${{ vars.JF_URL }}` are not currently supported in the setup action's `network` input. #### Example: Install from PyPI with JFrog CLI After checking out the repository and setting up Python, install JFrog CLI, configure its pip resolver, and install the current project: ```yaml - name: Setup JFrog CLI uses: jfrog/setup-jfrog-cli@v4 env: JF_URL: ${{ vars.JF_URL }} JF_ACCESS_TOKEN: ${{ secrets.JF_ACCESS_TOKEN }} - name: Configure pip run: jf pip-config --global=true --repo-resolve=pypi-repository - name: Install dependencies run: jf pip install . ``` Set `JF_URL` to the Artifactory base URL, such as `https://artifactory.example.com`. Repository variables and secrets are supported in the JFrog action's environment. Replace `pypi-repository` in the `jf pip-config` command with your PyPI repository key. #### Example: Install from npm without JFrog CLI Configure npm to use the same registry URL from the setup action: ```yaml - name: Configure npm env: ARTIFACTORY_NPM_TOKEN: ${{ secrets.ARTIFACTORY_NPM_TOKEN }} run: | npm config set registry https://artifactory.example.com/artifactory/api/npm/npm-repository npm config set //artifactory.example.com/artifactory/api/npm/npm-repository/:_authToken "$ARTIFACTORY_NPM_TOKEN" ``` The `npm config` commands are one way to configure the registry. You can instead use an `.npmrc` file or another package-manager configuration mechanism, as long as it selects the same URL. Store the access token in the `ARTIFACTORY_NPM_TOKEN` GitHub Actions secret. CRACI does not send the token to another host when package metadata refers to an external archive. ## Allow a TCP service Use a TCP connection for services that do not use TLS, such as a database on a private network: ```yaml - uses: cracicorp/setup@v1 with: network: | default: deny connections: - tcp: hostPatterns: [postgres.internal.example.com] cidrs: [10.60.0.0/16] ports: [5432] ``` For TCP connections, a hostname or CIDR match is sufficient when both are present. The destination port must also match. ## Configuration reference Validation errors identify unknown fields, missing required fields, and entries that contain more than one software source or connection type. ### Network policy | Setting | Required | Default | Description | | ------------- | -------- | ----------- | -------------------------------------------------------------------------------------------------------- | | `default` | No | `deny` | Controls unmatched traffic when `network` is configured. `allow` permits unmatched outbound connections. | | `presets` | No | All presets | Selects built-in software sources. An empty list disables all presets. | | `sources` | No | None | Adds private or custom software sources. Each item contains exactly one source type. | | `connections` | No | None | Adds TLS, TCP, UDP, or ICMP destinations. Each item contains one connection type. | ### Package sources All source URLs must use HTTP or HTTPS. | Source | Setting | Required | Default | Description | | ---------- | --------------- | -------- | ---------- | ------------------------------------------------------------- | | `pypi` | `urls` | Yes | No default | One or more Python package index URLs. | | `npm` | `urls` | Yes | No default | One or more npm registry URLs. | | `rubygems` | `urls` | Yes | No default | One or more RubyGems registry URLs. | | `apt` | `urls` | Yes | No default | One or more Debian-style repository URLs. | | `apt` | `purlNamespace` | No | None | Package URL namespace recorded for packages from this source. | | `apk` | `urls` | Yes | No default | One or more Alpine repository URLs. | | `golang` | `urls` | Yes | No default | One or more Go module proxy URLs. | | `nix` | `urls` | Yes | No default | One or more Nix binary cache URLs. | | `cargo` | `indexUrl` | Yes | No default | Cargo index URL. | | `cargo` | `downloadUrl` | Yes | No default | Crate download URL. | ### OCI registries ```yaml sources: - oci: urls: [https://registry.example.com] # default: ["**"] - Allows all repositories repositoryPatterns: ["platform/**", "third-party/*"] operations: [pull] ``` | Setting | Required | Default | Description | | -------------------- | -------- | ---------- | ---------------------------------------------------------------------- | | `urls` | Yes | No default | Registry endpoints. Provide at least one URL. | | `repositoryPatterns` | No | `["**"]` | Limits access to matching repositories. | | `operations` | Yes | No default | Allowed operations: `pull`, `push`, or `delete`. Provide at least one. | ### Git sources ```yaml sources: - git: # default: ["**"] - Allows all repositories repositoryPatterns: ["https://git.example.com/platform/**"] https: - baseUrl: https://git.example.com ssh: - host: git.example.com port: 22 user: git upstreamKnownHosts: - "git.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA..." ``` At least one HTTPS or SSH transport is required. | Setting | Required | Default | Description | | -------------------------- | -------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------- | | `repositoryPatterns` | No | `["**"]` | Limits access to matching repositories. | | `https[].baseUrl` | For HTTPS | No default | Base URL of an allowed Git server. | | `ssh[].host` | For SSH | No default | Hostname of an allowed SSH server. | | `ssh[].port` | For SSH | No default | SSH server port. | | `ssh[].user` | No | Any user | Restricts the SSH username when set. | | `ssh[].upstreamKnownHosts` | For SSH connectivity | No trusted host keys | Trusted SSH host keys. The configuration is valid without this field, but the connection fails unless a host key matches. | ### TLS connections ```yaml connections: - tls: # Either cidrs or serverNamePatterns needs to be set. serverNamePatterns: [api.example.com] cidrs: [10.50.0.0/16] ports: [443] # default: no ALPN filtering alpn: [h2] ``` | Setting | Required | Default | Description | | -------------------- | --------------------- | ----------------- | ----------------------------------------------------------------- | | `serverNamePatterns` | One selector required | None | Matches the TLS server name. | | `cidrs` | One selector required | None | Matches the destination IP address. | | `ports` | Yes | No default | Allowed destination ports. Provide at least one. | | `alpn` | No | No ALPN filtering | When set, at least one protocol offered by the client must match. | Set `serverNamePatterns`, `cidrs`, or both. When both are set, both selectors and the destination port must match. ### TCP connections | Setting | Required | Default | Description | | -------------- | --------------------- | --------- | ------------------------------------- | | `hostPatterns` | One selector required | None | Matches the destination hostname. | | `cidrs` | One selector required | None | Matches the destination IP address. | | `ports` | No | All ports | Limits the allowed destination ports. | Set `hostPatterns`, `cidrs`, or both. When both are set, either selector may match. When `ports` is set, the destination port must also match. A TCP rule takes precedence when TCP and TLS rules match the same connection. ### UDP connections | Setting | Required | Default | Description | | ------- | -------- | ---------- | ------------------------------------- | | `cidrs` | Yes | No default | Matches IPv4 destination addresses. | | `ports` | No | All ports | Limits the allowed destination ports. | ### ICMP connections | Setting | Required | Default | Description | | ------- | -------- | ---------- | ----------------------------------- | | `cidrs` | Yes | No default | Matches IPv4 destination addresses. | ## Built-in presets All presets are enabled when `presets` is omitted. A non-empty `presets` list replaces that set. The following table is the complete list of accepted preset names. | Preset | Allows | | ----------------- | -------------------------------------------------------------------------------------- | | `pypi` | PyPI index and package files | | `npm` | Public npm registry and its Yarn mirror | | `rubygems` | Public RubyGems registry and compact index | | `alpine` | Alpine package repositories | | `debian` | Debian package repositories | | `ubuntu` | Ubuntu archive, security, ports, and snapshot repositories | | `cargo` | crates.io index and crate downloads | | `golang` | Public Go module proxy | | `fonts` | Google Fonts, Adobe Fonts, Bunny Fonts, and Fontshare | | `cache-nixos-org` | `cache.nixos.org` and binary caches on `*.cachix.org` | | `dockerhub` | Docker Hub pulls and authentication | | `ghcr` | GitHub Container Registry pulls | | `quay` | Quay container registry pulls | | `gcr` | Google Container Registry pulls | | `ecr-public` | Amazon ECR Public pulls | | `github` | GitHub repositories over HTTPS and SSH | | `gitlab` | GitLab repositories over HTTPS and SSH | | `docker-apt` | Docker's APT repositories | | `nodesource` | NodeSource APT repositories | | `raspbian` | Raspbian repositories | | `yocto` | Yocto downloads and Git repositories | | `openembedded` | OpenEmbedded Git repositories | | `bitbucket` | Bitbucket Git repositories over SSH | | `googlesource` | Chromium's Google Source repository over HTTPS and Google Source repositories over SSH | ## Pattern matching Host patterns may be exact hostnames or begin with one `*.` wildcard. For example, `*.example.com` matches subdomains of `example.com`. OCI repository patterns match the repository name without the registry hostname. They use `*` within one path segment and `**` across path segments. For example, `platform/*` matches one segment below `platform`, while `platform/**` matches repositories at any depth below it. Git repository patterns match the full HTTPS repository URL. Include the server in the pattern, such as `https://git.example.com/platform/**`. SSH access is restricted by the configured `host`, `port`, and optional `user` fields. ## Schema and editor support Use the versioned [JSON Schema](/schemas/setup-action-network.schema.json) for YAML completion and validation in your editor. ## When a job fails to reach something See [Debug network problems in jobs](/guides/network-troubleshooting/) for the job network trace, deny reasons, and CRACI's certificate handling.