Standard CI/CD pipelines are built on the assumption of ubiquitous outbound internet connectivity. Every runner pulls a base image from a public registry, every build resolves dependencies from upstream package repositories, every scan tool downloads fresh vulnerability signatures on startup. In a classified, air-gapped defense environment, none of those assumptions hold — and the engineering consequences reach into every layer of the toolchain. This guide covers the architectural decisions, toolchain choices, and operational procedures that make continuous integration and delivery work in the absence of internet access, on STIG-hardened infrastructure, inside an accreditation boundary.

Why standard CI/CD fails in air-gapped defense environments

The failure mode is not a single missing feature — it is a cascade of assumptions baked into every modern CI/CD tool that dissolves on contact with an air-gapped accreditation boundary. Understanding these failure modes in advance prevents wasted procurement cycles and last-minute architecture reversals when the ATO review begins.

Network isolation. A classified enclave at Secret and above has no outbound internet access by design. Runners cannot pull images from Docker Hub, Maven Central, npmjs.com, or PyPI. Build tools that download plugins or extensions on first use fail silently or with cryptic errors about unreachable hosts. Update mechanisms in Jenkins, GitLab, and most commercial CI tools phone home on startup — this traffic is blocked and often generates noise in the network monitoring console that the ISSM has to explain to the AO.

Software approval and accreditation. Every software component deployed inside a DoD accreditation boundary must be approved by the Authorizing Official (AO) as part of the System Authorization Package. This includes not just the CI server, but every plugin, every build agent image, every library the pipeline itself depends on. "We'll use the latest version from the public registry" is not an acceptable answer in an ATO context. The approved software list is a controlled document; adding new packages requires a formal request, a vulnerability scan, a license review, and — for packages with no existing STIG coverage — an additional documentation burden on the engineering team. This process typically takes days to weeks per package, which makes ad-hoc dependency additions incompatible with the development tempo a modern CI pipeline demands. The solution is to front-load the approval process by identifying every dependency before the pipeline is deployed, not after.

Tool procurement and licensing. Some CI tooling is straightforwardly available to government contractors. Some requires specific licensing agreements for government use, Some requires export control review (ITAR/EAR classification). Jenkins OSS and GitLab CE avoid most of these issues, which partly explains their dominance in classified environments. Commercial CI platforms that bundle proprietary runners, managed secrets services, or cloud-based analytics are generally not viable inside an air-gapped enclave without significant architectural modification.

The net result is that air-gapped CI/CD must be designed from first principles, not adapted from a commercial SaaS pattern. The building blocks are available and proven — they simply require explicit offline provisioning for every component that a standard pipeline would resolve dynamically. For the broader DevSecOps framing that governs these decisions, see our guide to DevSecOps for defense pipelines.

Offline artifact registry architecture

The artifact registry is the supply chain anchor for an air-gapped build environment. Every dependency — JARs, npm packages, Python wheels, Go modules, RPMs — must be served from inside the enclave. Two products dominate this space in classified environments: Sonatype Nexus Repository (OSS and Pro) and JFrog Artifactory (OSS and Pro). Both are deployable on RHEL with no outbound connectivity required for operation; both support the repository formats a typical defense software project needs.

The topology has two halves. On the low side (internet-connected but not classified), a curator workstation runs the same Nexus or Artifactory version as the high-side instance. The curator uses the repository manager's built-in export/import tooling or a scripted workflow to pull approved artifacts, resolve their transitive dependencies, verify checksums against the upstream registry's published hashes, and assemble a signed transfer bundle. The signing step is critical: the transfer bundle must be signed with the program's transfer key so that the high-side system can verify integrity before importing anything.

# Low-side curator: assemble and sign the transfer bundle
nexus-curator export \
  --format maven \
  --repos approved-central-proxy \
  --output /transfer/bundle-2026-06-24.tar.gz

# Generate SHA-256 manifest
sha256sum /transfer/bundle-2026-06-24.tar.gz \
  > /transfer/bundle-2026-06-24.manifest

# GPG-sign the manifest with the program transfer key
gpg --detach-sign --armor \
  --local-user transfer@program.mil \
  /transfer/bundle-2026-06-24.manifest

# Physical transfer via encrypted removable media or data diode
# ...

# High-side import: verify before extracting
gpg --verify bundle-2026-06-24.manifest.asc \
              bundle-2026-06-24.manifest
sha256sum -c bundle-2026-06-24.manifest
nexus-curator import --file bundle-2026-06-24.tar.gz
            

On the high side, the Nexus or Artifactory instance serves only hosted repositories — there are no proxy repositories pointing to external URLs, because those URLs are unreachable. Build agent tool configuration files reference only the internal hostname. A table of the configuration files that require modification:

Ecosystem Config file Key setting
Maven ~/.m2/settings.xml <mirror> pointing to internal Nexus
npm / Node.js .npmrc registry=https://nexus.enclave.mil/repository/npm-hosted/
Python / pip pip.conf index-url = https://nexus.enclave.mil/repository/pypi-hosted/simple/
Go GONOSUMCHECK / GOFLAGS GOPROXY=https://nexus.enclave.mil/repository/go-proxy/
Container images /etc/containers/registries.conf unqualified-search-registries = ["harbor.enclave.mil"]

Curation cadence is a policy decision: typically monthly for security patches, quarterly for new dependency versions, and immediate for any CVE with a CVSS score above 8.0. The program's Configuration Control Board owns the decision on each import.

STIG-hardened CI server: Jenkins or GitLab on classified infrastructure

The two most common choices for CI execution on classified infrastructure are Jenkins (the long-dominant option, widely deployed in DoD programs from the mid-2010s onward) and GitLab (increasingly preferred for new programs because of its published DISA STIG and its integrated DevSecOps features). Both can be made compliant; the effort and the residual risk profile differ.

For Jenkins, the hardening baseline is the DISA Application Server SRG combined with the RHEL 9 STIG for the underlying OS. The Jenkins-specific hardening checklist covers the following areas:

  • Disable the Jenkins CLI over remoting (CVE-2024-23897 class of vulnerabilities); use CLI only over SSH if needed.
  • Enable Content Security Policy (CSP) headers to prevent XSS in build console output.
  • Disable the Script Console access for non-admin users; restrict Groovy sandbox escapes.
  • Configure matrix-based security with principle of least privilege: developers can trigger builds, cannot administer agents or credentials.
  • Enable audit-log plugin; forward logs to the enclave SIEM.
  • Set JENKINS_HOME on a filesystem with access controls; restrict world-readable permissions on credentials.xml.
  • Disable update site connections (hudson.model.UpdateCenter.never=true in jenkins.properties).
  • Run Jenkins as a dedicated non-root service account; apply SELinux contexts.

GitLab CE/EE on RHEL benefits from the DISA GitLab Enterprise Edition STIG (V1R1, published 2022), which maps controls directly to GitLab configuration settings. Key controls include enforcing TLS 1.2 minimum, disabling sign-up and OAuth providers, enabling audit events to syslog, restricting Git protocol to SSH over a known port, and disabling auto-DevOps features that make outbound calls. GitLab's integrated registry, merge request workflow, and pipeline YAML syntax reduce the number of separately accredited components compared to a Jenkins-centric stack, which is often the deciding factor in programs where ATO timelines are constrained.

In either case, build agents must run inside the same classification boundary as the controller. Agent images are built from approved base images held in the enclave's container registry, and are rebuilt on a defined schedule (typically monthly) to incorporate OS patch updates transferred through the curation workflow.

Disconnected container registry

Container images in an air-gapped pipeline must be stored, scanned, and signed inside the enclave. Two products are most common: Harbor (CNCF-graduated, widely used in DoD Platform One environments) and Red Hat Quay (supported under the DoD's enterprise Red Hat agreement, integrates tightly with OpenShift). Both support OCI image signing, role-based access control, and vulnerability scanning with offline databases.

The initial population of the registry follows the same transfer workflow as the artifact registry: approved base images (RHEL UBI, hardened Iron Bank images, approved application base layers) are exported from the low-side as OCI tarballs, transferred, and imported into Harbor or Quay using skopeo copy:

# Low side: export approved images as OCI tarballs
skopeo copy \
  docker://registry.access.redhat.com/ubi9/ubi:9.4 \
  oci-archive:/transfer/ubi9-9.4.tar \
  --override-os linux

# Generate and sign manifest
sha256sum /transfer/ubi9-9.4.tar >> /transfer/images.manifest
gpg --detach-sign --armor --local-user transfer@program.mil \
    /transfer/images.manifest

# High side: verify and import
gpg --verify images.manifest.asc images.manifest
sha256sum -c images.manifest
skopeo copy \
  oci-archive:/transfer/ubi9-9.4.tar \
  docker://harbor.enclave.mil/base/ubi9:9.4 \
  --dest-creds admin:${HARBOR_TOKEN}
            

Image signing with Cosign in offline mode uses a long-lived signing key stored in the enclave's Vault Transit engine, bypassing the Sigstore transparency log (which is internet-hosted). The signing key is generated inside Vault and never exported; the CI pipeline calls Vault's Transit API to sign the image digest and attaches the resulting signature as an OCI artifact alongside the image manifest in Harbor. Verification at admission time is handled by a Kyverno policy that calls the Cosign verifier against Harbor using the enclave's internal PKI trust bundle.

# Sign image using Vault Transit key (no transparency log)
cosign sign \
  --key hashivault://transit/keys/image-signing-key \
  --no-tlog-upload \
  harbor.enclave.mil/myapp/service:v1.4.2@sha256:abc123...

# Kyverno policy: require valid Cosign signature on every pod
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: require-image-signature
spec:
  validationFailureAction: Enforce
  rules:
  - name: check-image-signature
    match:
      resources:
        kinds: [Pod]
    verifyImages:
    - imageReferences: ["harbor.enclave.mil/*"]
      attestors:
      - entries:
        - keys:
            publicKeys: |-
              -----BEGIN PUBLIC KEY-----
              ... (enclave signing public key) ...
              -----END PUBLIC KEY-----
            rekor:
              ignoreTlog: true
            

Vulnerability scanning inside the registry uses Trivy or Grype configured with an offline database bundle. The vulnerability database (NVD, OSV, RedHat advisories) is downloaded on the low side, transferred to the high side, and loaded into the scanner's local database path. A daily pipeline job refreshes the database bundle through the curation workflow, keeping the scanner's knowledge current within the transfer cadence.

The software transport workflow: sneakernet to secure update server

The term "sneakernet" predates CI/CD, but the concept is precisely what makes air-gapped software delivery function: physical transport of data between networks of different classification levels. In modern classified facilities this transport is systematized into a documented workflow with mandatory gates, audit trails, and chain-of-custody requirements that mirror what automated supply chain controls provide in a connected environment. The challenge for CI/CD pipelines is that the transport cycle time — typically measured in days, not milliseconds — must be baked into the release planning model.

The workflow has a defined structure:

Low-side workstation (UNCLASSIFIED)
    │
    ├─ [1] Assemble candidate package set
    │      - download, resolve transitive deps
    │      - verify upstream signatures/checksums
    │      - run malware scan (ClamAV / commercial AV)
    │      - run vulnerability scan (Grype offline db)
    │      - license review
    │
    ├─ [2] Generate signed manifest
    │      sha256sum * > manifest.txt
    │      gpg --detach-sign manifest.txt
    │
    ├─ [3] Submit transfer request (CMT/JIRA ticket)
    │      - package name, version, purpose, license
    │      - vulnerability scan results attached
    │
    ├─ [4] ISSO/AO review and approval (Gate)
    │
    ├─ [5] Physical transfer
    │      - encrypted USB (FIPS 140-2 validated)
    │      - OR hardware data diode (one-way)
    │      - transfer log entry created
    │
High-side secure update server (CLASSIFIED)
    │
    ├─ [6] Verify manifest signature
    │      gpg --verify manifest.txt.asc manifest.txt
    │      sha256sum -c manifest.txt
    │
    ├─ [7] Import into Nexus / Harbor
    │
    └─ [8] Log in configuration management tool
            

Package signing uses either GPG with program-specific keys or — on programs that have adopted PKI-based tooling — sigstore/cosign against the program's internal Rekor instance. The key point is that the signing key used for transfer manifests is distinct from the key used for build artifact signing. The transfer key is held by the curator role, not by automated build agents, because the transfer approval is a human gate that must not be automatable.

For programs that run high-tempo patch cycles, one-way hardware data diodes (such as those from Owl Cyber Defense or Waterfall Security) automate the physical layer of the transfer while preserving the one-directional guarantee. Data flows only from low to high; the high-side system cannot send any traffic back. This does not eliminate the approval gate, but it eliminates the physical removable media step and can be used to push nightly patch bundles on a defined schedule. See our broader treatment of supply chain security for defense software for the policy framing that governs what enters the transfer workflow in the first place.

STIG compliance automation in the pipeline

Manual STIG checklists are incompatible with a continuous delivery tempo. A build that deploys daily cannot be manually reviewed against 300+ STIG controls before each release. The solution is compliance as code: encoding the STIG controls as machine-checkable policy, running the policy in the pipeline as an automated gate, and generating structured evidence that satisfies the AO's continuous monitoring requirements.

The primary toolchain is OpenSCAP with the SCAP Security Guide (SSG). SSG ships XCCDF/OVAL content for RHEL 8, RHEL 9, and related distributions that maps directly to DISA STIGs. In an air-gapped environment, the SSG content is bundled into the build agent image rather than downloaded at runtime:

# Pipeline stage: STIG scan of a deliverable container image
stages:
  - build
  - stig-scan
  - sign
  - promote

stig-scan:
  stage: stig-scan
  image: harbor.enclave.mil/tools/openscap-runner:latest
  script:
    - |
      # Mount the container image filesystem for scanning
      skopeo copy \
        docker://harbor.enclave.mil/${CI_PROJECT_PATH}:${CI_COMMIT_SHA} \
        oci:./image-under-test

      # Run STIG profile evaluation
      oscap-chroot ./rootfs xccdf eval \
        --profile xccdf_org.ssgproject.content_profile_stig \
        --results stig-results.xml \
        --report stig-report.html \
        /usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml

      # Block on any CAT I (high severity) failures
      python3 /tools/parse-stig-results.py \
        --results stig-results.xml \
        --fail-on-severity high \
        --output stig-summary.json

  artifacts:
    paths:
      - stig-results.xml
      - stig-report.html
      - stig-summary.json
    expire_in: 90 days
            

The DISA STIG Viewer application can ingest the results.xml output from OpenSCAP and display it in the familiar checklist format that AOs and ISSOs use during reviews. For programs that operate a continuous monitoring dashboard (typically feeding a SIEM or a GRC tool), the structured JSON output from the parse script is pushed to the evidence repository as a pipeline artifact alongside the build.

A common pattern is to separate host-level STIG scanning (run by the infrastructure team against the build agent base images on a monthly cadence) from image-level STIG scanning (run by the application pipeline on every build against the deliverable container). Host-level findings affect the ATO of the CI infrastructure itself and are tracked in the system's POA&M. Image-level findings are tracked at the application level and are the responsibility of the development team. The audit trail clearly delineates which team owns which finding, which matters when an accreditor reviews the continuous monitoring evidence package.

For SBOM enforcement in defense pipelines, the STIG scan output complements the SBOM by providing evidence that the runtime environment the artifact will execute in is also compliant — not just the artifact's software components.

Secret management without internet: HashiCorp Vault in air-gap mode

Secrets management is the component most likely to be improvised poorly in air-gapped environments. The common improvisation — storing credentials in the CI server's built-in credential store, or in a shared password manager, or in environment variables baked into agent images — fails the same audit controls that a connected environment would fail. The approved solution is a dedicated secrets management system deployed inside the accreditation boundary.

HashiCorp Vault OSS (open-source, not Enterprise) requires no internet connectivity for operation. It is deployable on a STIG-hardened RHEL host inside the enclave, initialized with a Shamir secret sharing key split distributed among authorized key custodians:

# Initialize Vault with 5 key shares, threshold of 3
vault operator init \
  -key-shares=5 \
  -key-threshold=3

# Example output (each share goes to a separate custodian):
# Unseal Key 1: AbCdEf...
# Unseal Key 2: GhIjKl...
# Unseal Key 3: MnOpQr...
# Unseal Key 4: StUvWx...
# Unseal Key 5: YzAbCd...
# Initial Root Token: hvs.XXXXXX (use once, then revoke)

# Unseal using 3 of 5 shares (separate operator ceremony)
vault operator unseal  # enter share 1
vault operator unseal  # enter share 2
vault operator unseal  # enter share 3
            

PKI bootstrapping in an air-gapped environment uses Vault's built-in PKI secrets engine to manage the program's certificate infrastructure. The process: generate a root CA key and certificate offline (on an air-gapped workstation, not inside Vault), store the root CA key in a hardware HSM or encrypted offline backup per the program's key management plan. Import the root CA certificate into Vault. Inside Vault's PKI engine, generate an intermediate CA key pair and CSR, sign the CSR with the root CA (offline step), import the signed intermediate certificate into Vault. From this point forward, Vault issues all short-lived TLS certificates for enclave services — the CI server, the artifact registry, the container registry, the secrets manager itself — without any external CA dependency.

CI agent authentication uses Vault's AppRole auth method. Each build agent is provisioned with a role_id (non-secret, can be in agent configuration) and a secret_id (short-lived, injected by the infrastructure provisioner at agent startup). The agent exchanges these for a Vault token scoped to only the secrets its builds require. Tokens are short-lived (1 hour default, renewable during the build) and automatically expire after the build completes. This pattern means that a compromised build agent has no persistent access to secrets — it holds only a token that expires, not a credential that survives indefinitely.

Secret rotation without internet access follows a scheduled ceremony: quarterly rotation of static secrets (API keys, service account passwords), annual rotation of signing keys. Vault's built-in rotation policies handle the timing; the output of each rotation is logged in Vault's audit log, which is forwarded to the enclave SIEM. For dynamic secrets — database credentials, PKI certificates — Vault's dynamic secrets engines generate per-build credentials with short TTLs, making rotation a non-event because each credential is already ephemeral.

Architecture summary: A production-ready air-gapped CI/CD stack has six layers — (1) offline artifact registry (Nexus/Artifactory), (2) STIG-hardened CI server (Jenkins/GitLab), (3) disconnected container registry (Harbor/Quay) with Cosign signing, (4) software transport workflow with signed manifests and approval gates, (5) automated STIG scanning (OpenSCAP + SSG) in every pipeline run, and (6) HashiCorp Vault for secrets and PKI. Each layer can be assembled incrementally, but all six must be present before the pipeline is submitted for ATO review. A stack missing any of these layers will generate POA&M items that block accreditation.

The operational discipline required to run this stack is non-trivial. Curator roles, transfer approval procedures, key custodian ceremonies, and monthly scan cadences are organizational commitments, not one-time engineering decisions. Programs that invest in documenting these procedures as part of the System Security Plan (SSP) rather than as informal tribal knowledge are significantly more resilient to personnel turnover — which, given clearance requirements and the defense labor market, is a realistic operational risk on every long-running program.

For the supply chain policy layer that governs what enters the pipeline in the first place, see our article on SBOM enforcement in defense pipelines. The air-gapped CI stack described here is the execution layer; SBOM enforcement and the broader DevSecOps for defense pipelines framework are the policy layer that determines what the pipeline builds, scans, and attests.