Running GitLab security scanners offline in an air-gapped instance
A self-managed GitLab instance on a network with no outbound internet access cannot pull scanner analyzer images, vulnerability data or language packages on its own. Without them, SAST, secret detection, dependency scanning and container scanning jobs either fail or silently run with stale data. The work is therefore less about turning scanners on and more about moving everything they need across the isolation boundary in a controlled way. GitLab documents running self-managed instances in offline, air-gapped environments and publishes separate guidance for running its security scanners offline, so that guidance is the first document to read before any design decision is made.
The job has three parts: mirroring the analyzer container images into a registry the instance can reach, bringing in the advisory and vulnerability data each analyzer depends on, and providing a package source for the build tools those analyzers call. Each part needs an owner, a transfer path and a refresh schedule, because offline data goes stale the day it is copied. Teams should confirm with GitLab which analyzer versions their instance tier and release line support, how the SECURE_ANALYZERS_PREFIX variable redirects jobs to the internal registry, and whether any analyzer still reaches out for data at runtime. Plan that verification before the cutover, not after the first failed pipeline.
Teams usually need this setup when a regulator, customer contract or internal policy forbids connecting the build environment to the internet, or when source code must stay inside a sovereign or classified boundary. Some controls, such as the supply chain integrity expectations in NERC CIP-013-2, make verifying the authenticity of every package carried across an isolated boundary part of procurement, so the transfer process must be auditable. This section sets the scope for the rest of the page: which network paths to close, which image and data sources to mirror, and what to confirm about licensing for offline use before buying or enabling anything.
What has to cross the boundary before scans can run
A scanner pipeline on an offline GitLab instance depends on more than the GitLab package itself. Each category below must be mirrored, redirected, switched off or verified before a scan can complete. Treat them as one inventory, because that list is what your transfer team needs to move content across the boundary.
Analyzer container images
Each scanner runs as a container image that the CI job pulls from a registry, so every analyzer your templates call must exist in a registry your runners can reach. Mirror the images your pipelines reference, pin the versions you tested, and point jobs at the mirror with SECURE_ANALYZERS_PREFIX. Confirm the current analyzer list and image names against the offline documentation before copying anything, because the set changes between releases.
Vulnerability advisory data
Dependency and container scanners match your components against vulnerability advisory data, which normally updates over the internet. An offline instance needs a repeatable process that fetches the advisory feeds in a connected zone, transfers them across the boundary, and loads them where the analyzers can read them. Confirm which data sources each analyzer uses, how often they update, and how your team will detect and report a stale database.
Language package sources
Build jobs that install dependencies before scanning fetch libraries from public package registries. Inside a closed network those requests fail unless you provide internal package mirrors and configure each package manager to use them. Confirm which package managers your projects use and which ones the scan jobs call, then test a full pipeline with outbound access blocked so failures surface before go-live.
Cloud-dependent features to disable
Some scanner features and instance options reach services hosted outside your network, and a licensing check can attempt an outbound call. Before the first offline run, list every setting, template variable and instance option that contacts an external endpoint, and decide which to turn off. Ask GitLab to confirm the cloud licensing opt-out and any features that remain unavailable offline, since a call that hangs can look like a pipeline fault.
Scanner templates and CI includes
Scan jobs come from included CI templates that reference images, variables and scripts, and an offline instance must resolve those includes from inside the network. Decide whether templates come from a mirrored copy of the GitLab project, an internal project or a vendored file, and record the exact version you pinned. Changing a template version changes what runs, so place it under the same change control as the images.
Integrity checks on transferred content
Every image, advisory file and package that enters the environment is software entering a controlled boundary. If your organization falls under NERC CIP, CIP-013-2 asks procurement processes to address verification of software integrity and authenticity, and the same discipline suits scanner content. Record checksums or signatures at export, verify them at import, and keep the transfer log with the change record.
Which tier and licensing choices to settle before the mirror is built
Settle your GitLab tier before anyone writes a mirror script, because the tier decides which scanners you need to carry across the boundary at all. The pricing page lists GitLab Free at no cost, Premium at 29 US dollars per user per month billed annually, and Ultimate as custom priced, with all three available for self-managed installations. Application security testing, software supply chain security, vulnerability management and compliance features are listed for Ultimate. Do not assume your tier includes a given analyzer. Ask your GitLab account team or check the feature comparison for your exact version which analyzers and scan templates your tier includes, then build the mirror list from that answer, not from the templates you saw in a public example.
Next, settle the cloud licensing opt-out. An offline instance cannot reach the cloud services that normally handle license checks and some scanner functions, so you need to confirm with GitLab how your subscription is activated and whether the offline procedure in the GitLab offline environments documentation fits your license type. Confirm who owns the license file, how renewals are delivered into the isolated network, and what happens to scanner features if the license lapses during a long change freeze. Record the answers in writing, because they determine whether a scanner works after the first upgrade stop.
The last decision is whether to mirror every analyzer and vulnerability database or to accept named gaps. Mirroring everything is the simplest control story, but each mirrored image and database is a new artifact you must verify, refresh and retain, which adds recurring work for your team or a partner. Accepting a gap is defensible only when you document which scan type is missing, which compensating control covers it, and who approves the risk. Make this call before the build starts, because it changes the pipeline design, the storage sizing and the change record you will need later.
Mirror and configuration options and when each fits
The table compares three ways to get analyzer images and vulnerability data into an isolated GitLab: a fully mirrored internal registry, a staged transfer pipeline and a partially offline setup with package mirrors. Read each row against your network boundary and your change control process, then confirm the exact variables and offline steps in the GitLab documentation for your version.
| Approach | Best fit and operational burden | What to confirm in the offline documentation |
|---|---|---|
| Fully mirrored internal registry with SECURE_ANALYZERS_PREFIX | Fits instances with no outbound path at all. Burden is recurring: someone must refresh analyzer images and rules on each GitLab release and keep the registry reachable from runners. | The current variable name and syntax for SECURE_ANALYZERS_PREFIX, the analyzer image list for your version, and how the offline scanner guidance handles vulnerability database updates. |
| Staged pipeline across a transfer boundary | Fits regulated environments where every file crossing the boundary needs a recorded review. Burden is mainly process: export, scan, approve, import and evidence each batch, and it adds lead time to every update. | Whether your boundary policy allows the transfer method you plan, and how to verify image digests and signatures after import against the GitLab guidance for your release. |
| Partially offline setup with package mirror | Fits sites that allow controlled access to internal package repositories but not public registries. Burden is lower for language and OS packages, but scanners that fetch advisory data still need their own offline source. | Which analyzers need network access at run time, which package managers the scanners call, and whether the mirror endpoints must be set through specific configuration keys. |
| Cloud licensing opt-out | Needed in every fully isolated case where GitLab would otherwise attempt cloud license or service calls. Setup is one-time per instance, but it must be rechecked after upgrades. | The exact settings that disable cloud license and usage ping traffic for your GitLab version, and whether any feature you need depends on that traffic. |
| Tier and license dependency | Affects which scanners you can run at all. Some capabilities are gated by tier, so confirm the edition before designing the mirror set. | Which analyzers and policy features are available in your tier, using the GitLab pricing page and the security scanning documentation for your version. |
How to set up mirrored scanners in order
This sequence takes a self-managed GitLab instance from an online configuration to one where its security scanners pull analyzer images and advisory data from infrastructure you control. Each step ends with a check you can record before moving on.
Confirm the offline documentation for your version
The platform team confirms the exact GitLab version in production and reads the offline environments guidance for that version, including the section on running security scanners offline. Offline procedures change between releases, so the team records the version, the page it used and any open questions for GitLab support or the account team. Done means a short written note that names the version, the documentation reviewed and the owner who signed it off. Do not start the mirror build until the note exists, because later steps depend on the analyzer names and paths it lists.
Turn off cloud-dependent licensing features
The GitLab administrator reviews every setting that makes the instance call an external service, including licensing and usage features that the offline guidance says to disable in air-gapped installs. Changes go into the configuration files under change control, and the team applies them in a maintenance window. Done means the instance runs a reconfigure cleanly, and a firewall or egress log shows no outbound connections from the GitLab host to vendor endpoints during a normal pipeline run. Record each setting changed so the audit trail matches the running state.
Build the staging sync for analyzers and advisories
On a connected staging host, the team builds a sync job that pulls the analyzer images for the scanners it plans to run, along with the vulnerability advisory data those scanners need. The Secure-Binaries pipeline pattern in the offline guidance is a useful reference for structuring this work. Each image is pinned to a tag or digest, and the team writes an inventory listing every image, digest and data snapshot date. Done means the inventory is complete for the scanners in scope and the staging registry holds every item on it.
Transfer and verify content across the boundary
The team moves the staged images and advisory bundles across the boundary using the transfer method its security policy approves, such as removable media or a one-way data diode. On the isolated side, it recomputes digests and checks them against the inventory from the previous step. It also verifies any signatures the scanner vendor publishes, using the trust process your organization already applies to vendor software. Done means every digest matches, every signature check passes, and the verification record is filed with the change ticket.
Point SECURE_ANALYZERS_PREFIX at your registry
The GitLab administrator sets the SECURE_ANALYZERS_PREFIX variable so that scanner jobs resolve analyzer images from the internal container registry instead of the default location. The value is set at the level the offline guidance recommends, and the team confirms how it interacts with any group or project overrides. Done means a rendered CI job log shows the internal registry path for each analyzer image, and no job attempts to reach an external registry. Keep the variable value in version-controlled configuration so the next upgrade does not silently reset it.
Configure package mirrors for language dependencies
Scanners and the projects they test often download language packages at run time, so the team points the relevant package managers at internal mirrors. The mirror list covers each ecosystem used by the scanned projects and the analyzers themselves, and runner images are configured to use those mirrors. Done means a test job installs a known package from the internal mirror with outbound access to public package indexes blocked. Keep the list of mirrored ecosystems with the inventory, since a missing ecosystem is a common reason a job fails late in rollout.
Run a test pipeline with each scanner
The team creates a test project with known findings, enables each scanner in scope and runs a pipeline on the offline runner fleet. It confirms each job completes, each report appears in the pipeline and merge request views, and the advisory data date matches the snapshot in the inventory. The team also checks that the test project produces no outbound network attempts beyond the approved internal endpoints. Done means a signed-off test record exists for each scanner, and the record names the image digests and data snapshot used. Repeat this run after every mirror refresh.
Security checks for content carried across an isolated boundary
Every analyzer image, rule set and vulnerability database that enters an offline GitLab instance is a supply chain input. The cards below cover the checks that sit around the transfer: verifying what arrives, controlling who can pull from the internal registry, isolating the runners that execute scans, and keeping mirror content current on a schedule you document.
Verify integrity and authenticity
Check the digest and signature of every analyzer image, package and vulnerability data set before it is imported into the isolated network. Record the checksums in the transfer manifest so the import side can compare them against what was exported. Confirm with GitLab which artifacts it publishes with verifiable signatures and which you must verify by checksum alone. Treat a mismatch as a stop condition, not a warning, and keep the rejected file in a quarantine location for review.
Why NERC CIP-013-2 applies
NERC CIP-013-2 requires electric utilities to address verification of software integrity and authenticity in their supply chain risk management processes. The same expectation applies to a scanner mirror carried across a boundary: the team must show how it knows the content is what the vendor released. Illustrative example: a utility's compliance team asks for the procedure, the transfer record and the checksum comparison for one scanner update, and the offline GitLab process should produce all three on request.
Control access to the internal registry
The internal container registry that holds mirrored analyzer images should accept pulls only from the runners and GitLab components that need them. Restrict push rights to the mirror pipeline's service identity, and review who holds project or group roles that could alter the image path referenced by SECURE_ANALYZERS_PREFIX. Confirm with your registry product which authentication methods and audit logs it provides, since the controls available depend on the registry you choose.
Isolate the scanning runners
Run the jobs that execute analyzers on runners dedicated to security scanning, separate from runners that build production artifacts. Use an executor type that matches your trust model, and do not give scan runners access to deployment credentials. Keep runner and GitLab versions aligned, as the GitLab Runner documentation advises, and confirm how each executor handles the mirrored images with your own tests before rollout.
Keep mirror content current
Analyzer images and vulnerability data go stale, so set a documented refresh cadence and an owner for each feed. Each refresh should follow the same path as the first import, with checksums, manifest and approval recorded. Track the GitLab release that each mirror was built against, because security fixes are backported to the previous two monthly releases, while bug fixes reach only the current stable release. Plan the refresh around the minor release on the third Thursday of each month.
Record each transfer as evidence
Keep one record per transfer that lists the artifacts, their checksums, the person who approved the import, the date it entered the boundary and the scanner version it enables. This record supports change management reviews and gives assessors a single trail to follow. Ask your auditor which format they expect before you design the log, because requirements differ between sectors and assessment bodies.
How offline scanning changes upgrades and day-two work
Offline scanning ties the analyzer images to the GitLab version you run, so every GitLab upgrade is also a scanner upgrade. GitLab ships a major release yearly, a minor release on the third Thursday of each month and patch releases twice a month, and it currently maintains 19.5, 19.4 and 19.3. Upgrades must pass through required upgrade stops, which since GitLab 17.5 fall at x.2, x.5, x.8 and x.11, so plan your analyzer mirror around those stops rather than around every monthly release. Treat each analyzer version as a change that must be tested against the target GitLab version in a staging instance before it reaches production.
- Pin the target first: Decide the GitLab version and its required stop before you refresh the mirrored analyzer images.
- Mirror per release line: Keep the analyzer tags that match your current and planned GitLab versions available in the internal registry.
- Respect backport limits: Bug fixes reach only the current stable release, while security fixes also reach the previous two monthly releases, so your offline window may need a faster security cadence than your feature cadence.
- Rehearse on staging: Run a pipeline with each mirrored analyzer against a staging instance on the target version before promotion.
- Record the pairing: Keep a dated list of GitLab version, analyzer tags and mirror source so an upgrade can be rolled back cleanly.
Confirm with your GitLab account team or documentation which analyzer versions are compatible with each target release before you schedule the upgrade window.
On an offline instance, vulnerability data is only as current as your last transfer. The scanner can run correctly and still report against advisories that are weeks old, so security teams need a rule for judging how stale a finding may be. Findings from a mirror should be read with the advisory snapshot date in mind, and a clean result should not be treated as proof that no vulnerability exists. This is especially important for dependency and container findings, where the database drives most of the result.
- Check the snapshot date: Note when the vulnerability data was last imported and show that date beside scan results used for decisions.
- Separate new from stale: When a finding appears after a fresh import, triage it as new. When a known finding persists, check whether a fix has been published since the snapshot.
- Set a refresh expectation: Agree with the platform team how often advisory data crosses the boundary, and what happens to merge requests while data is older than that expectation.
- Review accepted risk: Re-review allowlisted vulnerabilities at each data refresh, since a risk accepted under old advisory data may now have a known fix.
- Watch policy effects: Confirm how approval policies behave when scanner output is missing or stale, so a failed import does not silently pass builds.
Confirm with your team how the scanner reports the age of its vulnerability data before you rely on that field in governance reports.
Compliance leads need evidence that the transfer process itself is controlled, not just the scanner output. Supply chain requirements in regulated sectors, such as the software integrity and authenticity controls in NERC CIP-013-2, expect procurement and verification of software and patches to be traceable. For an isolated GitLab, each package carried across the boundary is a change to the system of record, so its origin, checks and approval should be documented in the same way as application changes. DeployOpen prepares these records as readiness material; independent auditors and certification bodies decide whether they meet a given standard.
- Log each transfer: Record the date, the person who approved it, the source of each image and database, and the checksums or signatures verified.
- Keep versions linked: Store the GitLab version, analyzer tags and vulnerability snapshot together so an auditor can reconstruct what scanned what on a given date.
- Retain upgrade evidence: Keep staging test results and the required upgrade stop plan with each GitLab upgrade record.
- Document exceptions: When a transfer is late or a scanner runs on stale data, record the reason and the compensating control.
- Map to your framework: Relate these records to the controls your assessors use, through your own control mapping rather than vendor claims.
Confirm with your assessor which evidence format and retention period they expect before the first transfer is recorded.
Limits to confirm in your environment before committing
Offline scanning depends on details that change between GitLab versions, tiers and runner setups. Each card below names one limit to verify, so the scope you agree on matches what your instance can actually run without internet access.
Analyzer support by GitLab version
Not every application security analyzer is documented for offline use on every GitLab release, and the list can change as analyzers are added, renamed or retired. Check the offline environments guidance for the exact version you plan to run, and list each analyzer your pipelines call. Ask your GitLab account team to confirm any analyzer that is missing from that list before you commit to a scanning design.
Vulnerability data sources you can mirror
Some scanners rely on advisory databases or vulnerability feeds that must be copied into your network on a schedule. Confirm which data sources each analyzer reads, whether each one can be mirrored, and who produces the update files. Decide how often the mirror refreshes and how you will prove the data is current, because stale advisories produce false confidence.
Tier entitlements for each scanner
Scanner availability depends on your GitLab subscription tier, and some capabilities such as dependency scanning, DAST and policy enforcement sit in higher tiers. Map every scanner in your plan to the tier that includes it, and confirm that the entitlement applies to a self-managed offline instance. Ask for the tier in writing as part of the quote, since a scanner that works in a lab may not be licensed for production.
Runner executor compatibility
Analyzer jobs run on GitLab Runner, and the executor you choose determines how images are pulled, cached and isolated. Confirm that your shell, Docker or autoscaling executor can reach your internal container registry and mirror without outbound access. Also confirm the Runner version matches your GitLab version, since the documentation advises keeping major and minor versions aligned.
Features that call online services
Some features may send requests to a GitLab-hosted or third-party service, which breaks an air-gapped design unless you disable or replace it. Review each enabled scanner and policy feature for outbound calls, including update checks, license lookups and AI features. Document every exception and the control that approves it, so your security team can see what leaves the boundary.
Package and dependency sources
Scanner jobs and build steps often install language packages, base images or helper tools at runtime. Confirm which package managers your pipelines contact and whether each one has an internal mirror that you control. Record the mirror source, sync method and integrity checks, because an unmirrored dependency will fail silently or push teams toward unapproved public sources.
Questions buyers ask before running scanners offline
How much does it cost to run GitLab security scanners offline?
The cost comes from four parts: the GitLab subscription, staging infrastructure, the transfer process and the recurring mirror refresh. GitLab's pricing page lists Free at 0 US dollars, Premium at 29 US dollars per user per month billed annually, and the highest tier with custom pricing, with all three available for self-managed installations. Which scanners you can use depends on your tier, so confirm that before buying. Staging hardware and the first transfer are one-time costs. Mirror refresh, upgrade testing and vulnerability data updates recur. DeployOpen prices follow from a written, fixed scope, so ask for a quote that separates the one-time build from the ongoing work.
Does our GitLab subscription include offline scanner use?
Offline operation is documented for self-managed instances, but the features your subscription includes are set by tier. GitLab's pricing page lists advanced CI/CD and priority support for Premium, and application security testing and software supply chain security for the highest tier. Scanner availability on a given tier should be confirmed with GitLab in writing, including whether analyzers used in an air-gapped instance are covered. Ask GitLab, and your reseller if you buy through one, to confirm the exact analyzers and the license terms for disconnected use before you build the mirror.
How long does an offline scanner setup take?
No fixed duration applies, because the timeline depends on the work in front of you. The main variables are how many analyzers you need, the GitLab version you run, whether a staging instance already exists, how quickly your package mirror is ready, and how long your security and change approvals take for transferring media across the boundary. Ask for a timeline as part of the written scope, with milestones for the staging test, the first full transfer and the first refresh cycle. Treat any date given before the scope is agreed as an estimate only.
What does our team need to provide before the work starts?
The work needs several inputs from your side:
- A self-managed GitLab instance, its exact version and a plan for the staging copy
- An internal container registry and a route for the analyzer images
- A package mirror for the operating system and language packages the analyzers use
- Named owners for security approval, change control and the transfer process
- Written approval for the transfer media and the boundary crossing procedure
- Access to your current vulnerability data policy so refresh rules match your risk tolerance
Missing inputs are the most common cause of schedule slips, so confirm each one during scoping. The GitLab offline environments guidance is the natural starting point for checking what your instance needs.
Can our own team run offline scanner updates without a partner?
Yes, if your team already administers GitLab, owns CI/CD pipelines and has capacity for a recurring cycle. Offline updates are not a one-off task. GitLab ships a minor release on the third Thursday of each month and patch releases twice a month, so mirror, test and transfer work repeats. Upgrades must pass through required upgrade stops, which fall at versions x.2, x.5, x.8 and x.11. Assess your team against those duties, and ask whether a retainer for upgrade testing and refresh would cover the gaps. Partial ownership is also a valid model, with your team running the routine refresh and a partner covering the first build and major upgrades.
How often do scanner images and vulnerability data need refreshing?
The refresh cadence follows two clocks: GitLab's release schedule and your own vulnerability data policy. According to GitLab's maintenance policy, minor releases arrive monthly and patch releases twice a month, and security fixes are backported to the previous two monthly releases as well as the current one. Analyzer images should match the GitLab version you run, so each upgrade changes the set you mirror. Agree in writing how often vulnerability data is refreshed, who approves each transfer, and how long a stale copy is acceptable before a security exception is raised.
How do we verify packages carried across an isolated boundary?
Verify each transfer before it enters the isolated network. Record checksums for every image, package and database file, check signatures wherever the publisher provides them, and keep the transfer log with the approval record. The control NERC CIP-013-2 addresses this directly for utilities, requiring supply chain procurement processes to cover verification of software integrity and authenticity for vendor software and patches. Other sectors can use the same approach as evidence of their own supply chain controls. Confirm with your security team which verification steps they accept and where the records are stored.
Does DeployOpen certify that our offline scanning setup is compliant?
No. DeployOpen plans, builds and documents the offline setup and prepares the systems, controls and evidence that an assessor will review. Independent auditors and certification bodies issue audit reports, attestations and certifications, and only they can confirm compliance. For the transfer process, ask for the procedure, verification records and refresh logs in a form your auditor can test. Confirm the assessor's requirements before scoping, because they determine which evidence the build must produce.
How DeployOpen scopes and delivers offline GitLab scanning
DeployOpen plans, implements, hardens, documents and supports self-hosted open-source platforms inside your own infrastructure, including air-gapped networks. For offline GitLab scanning, we start with an inventory of which analyzers and vulnerability data your tier needs, then build the mirror, the import path and the verification steps around that list.
How we scope
- We confirm your GitLab tier, edition and the scanners you intend to run before any mirroring work starts.
- We list the analyzer images, vulnerability data sources and package repositories each scanner needs in your network.
- We document the cloud licensing opt-out and any outbound connections that must be removed or replaced.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work begins.
How we build
- We build the transfer pipeline that pulls approved analyzer images and data into your offline environment.
- We configure the offline GitLab instance to pull scanners from your internal registry through SECURE_ANALYZERS_PREFIX.
- We set up internal package mirrors so dependency and build jobs run without public internet access.
- We test each scanner job in a staging instance and record which findings depend on refreshed vulnerability data.
How we hand over
- You receive the written runbook for each mirror, including source, checksum and approval steps for every transfer.
- You receive configuration records for the GitLab instance, CI/CD templates and registry settings used by scanners.
- We walk your platform and security engineers through the update cycle so the next import runs without us.
- Evidence for compliance readiness is documented for your assessors, though independent auditors issue any attestation.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer, scoped in writing.
- Retainer work can cover refreshing analyzer images and vulnerability data on a schedule you approve.
- Upgrade planning for GitLab follows the required upgrade stops, so mirrored versions stay aligned with your instance.

