[{"data":1,"prerenderedAt":706},["ShallowReactive",2],{"/en-us/blog/tutorial-security-scanning-in-air-gapped-environments/":3,"navigation-en-us":38,"banner-en-us":453,"footer-en-us":468,"Fernando Diaz":678,"next-steps-en-us":691},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":27,"_id":31,"_type":32,"title":33,"_source":34,"_file":35,"_stem":36,"_extension":37},"/en-us/blog/tutorial-security-scanning-in-air-gapped-environments","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Tutorial: Security scanning in air-gapped environments","Security scanning remains crucial even in air-gapped environments to detect internal threats, prevent data exfiltration, and maintain operational integrity. Learn how GitLab can help get air-gapped environments secure.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099301/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1097303277_6gTk7M1DNx0tFuovupVFB1_1750099300786.jpg","https://about.gitlab.com/blog/tutorial-security-scanning-in-air-gapped-environments","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Tutorial: Security scanning in air-gapped environments\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Fernando Diaz\"}],\n        \"datePublished\": \"2025-02-05\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Fernando Diaz","2025-02-05","Air-gapped environments are computer networks or systems that are physically isolated from unsecured networks, such as the public internet or unsecured local area networks. This isolation is implemented as a security measure to protect sensitive data and critical systems from external cyber threats by providing:\n\n* Enhanced security: By physically isolating systems from external networks, air-gapped environments help prevent remote attacks, malware infections, and unauthorized data access. This is crucial for highly sensitive data and critical systems.\n* Data protection: Air-gapping provides the strongest protection against data exfiltration since there's no direct connection that attackers could use to steal information.\n* Critical infrastructure protection: For systems that control vital infrastructure (like power plants, water treatment facilities, or military systems), air-gapping helps prevent potentially catastrophic cyber attacks.\n* Compliance requirements: Many regulatory frameworks require air-gapping for certain types of sensitive data or critical systems, particularly in government, healthcare, and financial sectors.\n* Malware protection: Without network connectivity, systems are protected from network-based malware infections and ransomware attacks.\n\nEven though air-gapped systems are isolated, they can still have vulnerabilities. Regular security scanning helps identify these weaknesses before they can be exploited. In this article, you will learn the different security scanners GitLab provides and how they can be added/updated in a limited-connectivity environment.\n\n## GitLab security scanners in air-gapped environments\n\nGitLab provides a variety of different security scanners for the complete application lifecycle. The scanners that support air-gapped environments include:\n\n* [Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/index.html#running-sast-in-an-offline-environment)  \n* [Dynamic Application Security Testing (DAST](https://docs.gitlab.com/ee/user/application_security/dast/browser/configuration/offline_configuration.html))  \n* [Secret Detection](https://docs.gitlab.com/ee/user/application_security/secret_detection/pipeline/index.html#offline-configuration)  \n* [Container Scanning](https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#running-container-scanning-in-an-offline-environment)  \n* [Dependency Scanning](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#offline-environment)  \n* [API Fuzzing](https://docs.gitlab.com/ee/user/application_security/api_fuzzing/configuration/offline_configuration.html)  \n* [License Scanning](https://docs.gitlab.com/ee/user/compliance/license_scanning_of_cyclonedx_files/index.html#running-in-an-offline-environment)\n\nBy default, GitLab Self-Managed instances pull security scanner images from the public GitLab container registry (registry.gitlab.com) and store them within the [built-in local GitLab container registry](https://docs.gitlab.com/ee/user/packages/container_registry/). I will demonstrate this flow below by running the following pipeline that scans for secrets on a [sample project](https://gitlab.com/gitlab-da/tutorials/security-and-governance/owasp/juice-shop): \n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n```\n\nWhen running the job in an internet-connected GitLab instance the job passes:\n\n![GitLab Runner with internet access successfully pulling from external registry\n](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/pass-1_aHR0cHM6_1750099328577.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner with internet access successfully pulling from external registry\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\nHowever, If I disable internet access to the VM running GitLab, the `secret-detection` job will fail to download the container image, causing the job to fail:\n\n![GitLab Runner without internet access failing to pull from external registry](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/fail-1_aHR0cHM6_1750099328577.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access failing to pull from external registry\u003C/i>\u003C/center>\n\u003Cbr>\u003C/br>\n\nAlternatively, if I set my GitLab Runners’ pull image policy to `if-not-present` from `always`, I can load the cached version of the scanner if it was run before on the internet by using the image stored in our local docker:\n\n![GitLab Runner without internet access successfully pulling from internal registry cache](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099329/Blog/Content%20Images/Blog/Content%20Images/pass-2_aHR0cHM6_1750099328579.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access successfully pulling from internal registry cache\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\n### Setting up offline scanning prerequisites\n\nRunning these security scanners in an air-gapped environment requires the following:\n\n* [GitLab Ultimate subscription](https://about.gitlab.com/pricing/ultimate/)  \n* [Offline cloud license](https://about.gitlab.com/pricing/licensing-faq/cloud-licensing/#offline-cloud-licensing)  \n* GitLab Self-Managed cluster\n\nYou can follow along with this tutorial in any GitLab Self-Managed EE instance (even those that are not air-gapped) to learn how to transfer and run images in an air-gapped environment. In this tutorial, I will demonstrate how to load scanner images onto a GitLab-EE instance running in a Google Compute VM where I cut off the `EGRESS` to everything by implementing firewall rules:\n\n```bash\n# egress firewall rule to block all outbound traffic to the internet\n$ gcloud compute firewall-rules create deny-internet-egress \\\n    --direction=EGRESS \\\n    --priority=1000 \\\n    --network=default \\\n    --action=DENY \\\n    --rules=all \\\n    --destination-ranges=0.0.0.0/0 \\\n    --target-tags=no-internet\n\n# Create an allow rule for internal traffic with higher priority\n$ gcloud compute firewall-rules create allow-internal-egress \\\n    --direction=EGRESS \\\n    --priority=900 \\\n    --network=default \\\n    --action=ALLOW \\\n    --rules=all \\\n    --destination-ranges=10.0.0.0/8,192.168.0.0/16,172.16.0.0/12 \\\n    --target-tags=no-internet\n\n# Apply tag to VM\n$ gcloud compute instances add-tags YOUR_VM_NAME \\\n    --zone=YOUR_ZONE \\\n    --tags=no-internet\n```\n\nThen, once I SSH into my VM, you can see we cannot connect to registry.gitlab.com:\n\n```bash\n# showing I can’t access the gitlab container registry\n$ ping registry.gitlab.com\nPING registry.gitlab.com (35.227.35.254) 56(84) bytes of data.\n^C\n--- registry.gitlab.com ping statistics ---\n3 packets transmitted, 0 received, 100% packet loss, time 2031ms\n```\n\n**Note:** I am still allowing ingress so I can copy files and SSH into the machine.\n\n## Load security scanners in air-gapped environments\n\nTo use the various security scanners on air-gapped environments, the GitLab Runner must be able to fetch the scanner container images from GitLab’s built-in container registry. This means that the container images for the security scanners must be downloaded and packaged in a separate environment with access to the public internet. The process of loading security scanners onto an air-gapped environment includes the following:\n\n1. Download and package container images from the public internet.\n2. Transfer images to offline environment.\n3. Load transferred images into offline container registry.\n\nNow let’s go over how we can implement GitLab Secret Detection in an air-gapped environment.\n\n### Download and package container images from public internet\n\nLet’s download the container image for secret detection and store it within our local container registry. Other scanner images can be found in the [offline deployments documentation](https://docs.gitlab.com/ee/user/application_security/offline_deployments/). I will be using Podman desktop to download these images, but you can use Docker desktop or other alternatives.\n\n1. Pull the GitLab Secret Detection image.\n\n```bash\n$ podman pull registry.gitlab.com/security-products/secrets:6\nTrying to pull registry.gitlab.com/security-products/secrets:6...\nGetting image source signatures\nCopying blob sha256:999745130ac045f2b1c29ecce088b43fc4a95bbb82b7960fb7b8abe0e3801bf8\nCopying blob sha256:a4f7c013bb259c146cd8455b7c3943df7ed84b157e42a2348eef16546d8179b1\nCopying blob sha256:1f3e46996e2966e4faa5846e56e76e3748b7315e2ded61476c24403d592134f0\nCopying blob sha256:400a41f248eb3c870bd2b07073632c49f1e164c8efad56ea3b24098a657ec625\nCopying blob sha256:9090f17a5a1bb80bcc6f393b0715210568dd0a7749286e3334a1a08fb32d34e6\nCopying blob sha256:c7569783959081164164780f6c1b0bbe1271ee8d291d3e07b2749ae741621ea3\nCopying blob sha256:20c7ca6108f808ad5905f6db4f7e3c02b21b69abdea8b45abfa34c0a2ba8bdb5\nCopying blob sha256:e8645a00be64d77c6ff301593ce34cd8c17ffb2b36252ca0f2588009a7918d2e\nCopying config sha256:0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\nWriting manifest to image destination\nWARNING: image platform (linux/amd64) does not match the expected platform (linux/arm64)\n0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\n\n$ podman images\nREPOSITORY                                                  TAG         IMAGE ID      CREATED      SIZE\nregistry.gitlab.com/security-products/secrets               6           0235ed43fc7f  4 hours ago  85.3 MB\n```\n\n2. Save the image as a tarball.\n\n```bash\n$ podman save -o secret-detection.tar registry.gitlab.com/security-products/secrets:6\n$ chmod +r secret-detection.tar\n$ ls -al secret-detection.tar\n-rw-r--r--@ 1 fern  staff  85324800 Jan 10 10:25 secret-detection.tar\n```\n\nAlternatively, you can use the [official GitLab template](https://docs.gitlab.com/ee/user/application_security/offline_deployments/#using-the-official-gitlab-template) on an environment with internet access to download the container images needed for the security scanners and save them as job artifacts or push them to the container registry of the project where the pipeline is executed. \n\n### Transfer images to offline environment\n\nNext, let's transfer the tarball to our air-gapped environment. This can be done in several ways, depending on your needs, such as:\n\n* Physical media transfer  \n* Data diodes  \n* Guard systems  \n* Cross-domain solutions (CDS) \n\nI will SCP (Secure Copy Protocol) the tarball directly to my VM that does not have egress access, but does allow ingress. As this is just for demonstration purposes, make sure to consult your organization's security policies and transfer procedures for air-gapped environments.\n\n#### Verify the image is not cached\n\nBefore transferring the file, I’ll delete the Docker images on my GitLab instance pertaining to secret detection to make sure they aren't cached:\n\n```bash\n$ docker images\nREPOSITORY                                                          TAG              IMAGE ID       CREATED        SIZE\nregistry.gitlab.com/security-products/secrets                       6                0235ed43fc7f   9 hours ago    84.8MB\nregistry.gitlab.com/security-products/secrets                       \u003Cnone>           16d88433af61   17 hours ago   74.9MB\n\n$ docker image rmi 16d88433af61 -f\nUntagged: registry.gitlab.com/security-products/secrets@sha256:f331da6631d791fcd58d3f23d868475a520f50b02d64000e2faf1def66c75d48\nDeleted: sha256:16d88433af618f0b405945031de39fe40b3e8ef1bddb91ca036de0f5b32399d7\nDeleted: sha256:1bb06f72f06810e95a70039e797481736e492201f51a03b02d27db055248ab6f\nDeleted: sha256:a5ef2325ce4be9b39993ce301f8ed7aad1c854d7ee66f26a56a96967c6606510\nDeleted: sha256:f7cdac818a36d6c023763b76a6589c0db7609ca883306af4f38b819e62f29471\nDeleted: sha256:5eabf4d47287dee9887b9692d55c8b5f848b50b3b7248f67913036014e74a0e9\nDeleted: sha256:51b7cb600604c0737356f17bc02c22bac3a63697f0bf95ba7bacb5b421fdb7da\nDeleted: sha256:1546193b011d192aa769a15d3fdd55eb4e187f201f5ff7506243abb02525dc06\nDeleted: sha256:1ea72408d0484c3059cc0008539e6f494dc829caa1a97d156795687d42d9cb57\nDeleted: sha256:1313ee9da7716d85f63cfdd1129f715e9bbb6c9c0306e4708ee73672b3e40f26\nDeleted: sha256:954ebfd83406f0dfed93eb5157ba841af5426aa95d4054174fff45095fd873a1\n\n$ docker image rmi 0235ed43fc7f -f\nUntagged: registry.gitlab.com/security-products/secrets:6\nDeleted: sha256:0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\nDeleted: sha256:f05f85850cf4fac79e279d93afb6645c026de0223d07b396fce86c2f76096c1f\nDeleted: sha256:7432b0766b885144990edd3166fbabed081be71d28d186f4d525e52729f06b1f\nDeleted: sha256:2c6e3361c2ee2f43bd75fb9c7c12d981ce06df2d51a134965fa47754760efff0\nDeleted: sha256:7ad7f7245b45fbe758ebd5788e0ba268a56829715527a9a4bc51708c21af1c7f\nDeleted: sha256:3b73a621115a59564979f41552181dce07f3baa17e27428f7fff2155042a1901\nDeleted: sha256:78648c2606a7c4c76885806ed976b13e4d008940bd3d7a18b52948a6be71b60d\nDeleted: sha256:383d4a6dc5be9914878700809b4a3925379c80ab792dfe9e79d14b0c1d6b5fad\n```\n\nThen I'll rerun the job to show the failure:\n\n![GitLab Runner without internet access fails to pull an image from internal registry cache](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/image2_aHR0cHM6_1750099328580.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access fails to pull an image from internal registry cache\u003C/i>\u003C/center>\n\n#### SCP file to GitLab instance\n\nNow, from my local machine, I will SCP the file to my GitLab instance as follows:\n\n```bash\n$ gcloud compute scp secret-detection.tar INSTANCE:~ --zone=ZONE\nsecret-detection.tar                                                          100%   81MB  21.5MB/s   00:03\n```\n\n### Load transferred images into offline container registry\n\nNext, I'll SSH into my VM and load the Docker image:\n\n```bash\n$ gcloud compute ssh INSTANCE --zone=ZONE\n\n$ sudo docker load -i secret-detection.tar\nc3c8e454c212: Loading layer [==================================================>]  2.521MB/2.521MB\n51e93afaeedc: Loading layer [==================================================>]  32.55MB/32.55MB\ne8a25e39bb30: Loading layer [==================================================>]  221.2kB/221.2kB\n390704968493: Loading layer [==================================================>]  225.8kB/225.8kB\n76cf57e75f63: Loading layer [==================================================>]  17.64MB/17.64MB\nc4c7a681fd10: Loading layer [==================================================>]  4.608kB/4.608kB\nf0690f406157: Loading layer [==================================================>]  24.01MB/24.01MB\nLoaded image: registry.gitlab.com/security-products/secrets:6\n```\n\n### Run the scanners\n\nI'll [re-run the pipeline manually](https://docs.gitlab.com/ee/ci/pipelines/#run-a-pipeline-manually) and the scanner will be pulled from the cache. Once the pipeline completes, we can see the secret detection job is successful:\n\n![GitLab Runner without internet access successfully pulling from internal registry cache after image loaded](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/image7_aHR0cHM6_1750099328581.png)\n\n\u003Ccenter>\u003Ci>GitLab Runner without internet access successfully pulling from internal registry cache after image loaded\u003C/center>\u003C/i>\n\nIf you want to pull the image from a different location or you tag your images in a different way, you can edit the config as follows:\n\n```yaml\ninclude:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n\nvariables:\n  SECURE_ANALYZERS_PREFIX: \"localhost:5000/analyzers\"\n```\n\nSee the [offline environments documentation](https://docs.gitlab.com/ee/user/application_security/offline_deployments/) for more information.\n\n### View scanner results\n\nOnce the scanner completes on the default branch, a vulnerability report is populated with all the findings. The vulnerability report provides information about vulnerabilities from scans of the default branch.\n\nYou can access the vulnerability report by navigating to the side tab and selecting **Secure > Vulnerability Report**:\n\n![GitLab Vulnerability Report with secret detection findings](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/vulnerability_report_aHR0cHM6_1750099328581.png)\n\n\u003Ccenter>\u003Ci>GitLab Vulnerability Report with secret detection findings\u003C/i>\u003C/center>\n\n\u003Cbr>\u003C/br>\n\nThe project’s vulnerability report provides:\n- totals of vulnerabilities per severity level\n- filters for common vulnerability attributes\n- details of each vulnerability, presented in tabular layout\n- a timestamp showing when it was updated, including a link to the latest pipeline\n\nWe can see that two vulnerabilities were detected by the Secret Detection scanner. If we click on a vulnerability, we will be transported to its vulnerability page:\n\n![GitLab Vulnerability Page showing detailed insights](https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099329/Blog/Content%20Images/Blog/Content%20Images/insights_aHR0cHM6_1750099328582.png)\n\n\u003Ccenter>\u003Ci>GitLab Vulnerability Page showing detailed insights\u003C/center>\u003C/i>\n\n\u003Cbr>\u003C/br>\n\nThe vulnerability page provides details of the vulnerability, which can be used to triage and find a path to remediation. These vulnerability details include:\n- description\n- when it was detected\n- current status\n- available actions\n- linked issues\n- actions log\n- filename and line number of the vulnerability (if available)\n- severity\n\n## Read more\n\nTo learn more about GitLab and running security scanners in air-gapped environments, check out the following resources:\n\n* [GitLab Ultimate](https://about.gitlab.com/pricing/ultimate/)  \n* [GitLab Security and Compliance Solutions](https://about.gitlab.com/solutions/security-compliance/)  \n* [GitLab Offline Deployments Documentation](https://docs.gitlab.com/ee/user/application_security/offline_deployments/)  \n* [GitLab Application Security Documentation](https://docs.gitlab.com/ee/user/application_security/)\n","security",[23,21,24,25,26],"tutorial","public sector","DevSecOps platform","features",{"slug":28,"featured":29,"template":30},"tutorial-security-scanning-in-air-gapped-environments",true,"BlogPost","content:en-us:blog:tutorial-security-scanning-in-air-gapped-environments.yml","yaml","Tutorial Security Scanning In Air Gapped Environments","content","en-us/blog/tutorial-security-scanning-in-air-gapped-environments.yml","en-us/blog/tutorial-security-scanning-in-air-gapped-environments","yml",{"_path":39,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"data":41,"_id":449,"_type":32,"title":450,"_source":34,"_file":451,"_stem":452,"_extension":37},"/shared/en-us/main-navigation","en-us",{"logo":42,"freeTrial":47,"sales":52,"login":57,"items":62,"search":390,"minimal":421,"duo":440},{"config":43},{"href":44,"dataGaName":45,"dataGaLocation":46},"/","gitlab logo","header",{"text":48,"config":49},"Get free trial",{"href":50,"dataGaName":51,"dataGaLocation":46},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":53,"config":54},"Talk to sales",{"href":55,"dataGaName":56,"dataGaLocation":46},"/sales/","sales",{"text":58,"config":59},"Sign in",{"href":60,"dataGaName":61,"dataGaLocation":46},"https://gitlab.com/users/sign_in/","sign in",[63,107,201,206,311,371],{"text":64,"config":65,"cards":67,"footer":90},"Platform",{"dataNavLevelOne":66},"platform",[68,74,82],{"title":64,"description":69,"link":70},"The most comprehensive AI-powered DevSecOps Platform",{"text":71,"config":72},"Explore our Platform",{"href":73,"dataGaName":66,"dataGaLocation":46},"/platform/",{"title":75,"description":76,"link":77},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":78,"config":79},"Meet GitLab Duo",{"href":80,"dataGaName":81,"dataGaLocation":46},"/gitlab-duo/","gitlab duo ai",{"title":83,"description":84,"link":85},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":86,"config":87},"Learn more",{"href":88,"dataGaName":89,"dataGaLocation":46},"/why-gitlab/","why gitlab",{"title":91,"items":92},"Get started with",[93,98,103],{"text":94,"config":95},"Platform Engineering",{"href":96,"dataGaName":97,"dataGaLocation":46},"/solutions/platform-engineering/","platform engineering",{"text":99,"config":100},"Developer Experience",{"href":101,"dataGaName":102,"dataGaLocation":46},"/developer-experience/","Developer experience",{"text":104,"config":105},"MLOps",{"href":106,"dataGaName":104,"dataGaLocation":46},"/topics/devops/the-role-of-ai-in-devops/",{"text":108,"left":29,"config":109,"link":111,"lists":115,"footer":184},"Product",{"dataNavLevelOne":110},"solutions",{"text":112,"config":113},"View all Solutions",{"href":114,"dataGaName":110,"dataGaLocation":46},"/solutions/",[116,141,163],{"title":117,"description":118,"link":119,"items":124},"Automation","CI/CD and automation to accelerate deployment",{"config":120},{"icon":121,"href":122,"dataGaName":123,"dataGaLocation":46},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[125,129,133,137],{"text":126,"config":127},"CI/CD",{"href":128,"dataGaLocation":46,"dataGaName":126},"/solutions/continuous-integration/",{"text":130,"config":131},"AI-Assisted Development",{"href":80,"dataGaLocation":46,"dataGaName":132},"AI assisted development",{"text":134,"config":135},"Source Code Management",{"href":136,"dataGaLocation":46,"dataGaName":134},"/solutions/source-code-management/",{"text":138,"config":139},"Automated Software Delivery",{"href":122,"dataGaLocation":46,"dataGaName":140},"Automated software delivery",{"title":142,"description":143,"link":144,"items":149},"Security","Deliver code faster without compromising security",{"config":145},{"href":146,"dataGaName":147,"dataGaLocation":46,"icon":148},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[150,153,158],{"text":151,"config":152},"Security & Compliance",{"href":146,"dataGaLocation":46,"dataGaName":151},{"text":154,"config":155},"Software Supply Chain Security",{"href":156,"dataGaLocation":46,"dataGaName":157},"/solutions/supply-chain/","Software supply chain security",{"text":159,"config":160},"Compliance & Governance",{"href":161,"dataGaLocation":46,"dataGaName":162},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":164,"link":165,"items":170},"Measurement",{"config":166},{"icon":167,"href":168,"dataGaName":169,"dataGaLocation":46},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[171,175,179],{"text":172,"config":173},"Visibility & Measurement",{"href":168,"dataGaLocation":46,"dataGaName":174},"Visibility and Measurement",{"text":176,"config":177},"Value Stream Management",{"href":178,"dataGaLocation":46,"dataGaName":176},"/solutions/value-stream-management/",{"text":180,"config":181},"Analytics & Insights",{"href":182,"dataGaLocation":46,"dataGaName":183},"/solutions/analytics-and-insights/","Analytics and insights",{"title":185,"items":186},"GitLab for",[187,192,197],{"text":188,"config":189},"Enterprise",{"href":190,"dataGaLocation":46,"dataGaName":191},"/enterprise/","enterprise",{"text":193,"config":194},"Small Business",{"href":195,"dataGaLocation":46,"dataGaName":196},"/small-business/","small business",{"text":198,"config":199},"Public Sector",{"href":200,"dataGaLocation":46,"dataGaName":24},"/solutions/public-sector/",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":46,"dataNavLevelOne":205},"/pricing/","pricing",{"text":207,"config":208,"link":210,"lists":214,"feature":298},"Resources",{"dataNavLevelOne":209},"resources",{"text":211,"config":212},"View all resources",{"href":213,"dataGaName":209,"dataGaLocation":46},"/resources/",[215,248,270],{"title":216,"items":217},"Getting started",[218,223,228,233,238,243],{"text":219,"config":220},"Install",{"href":221,"dataGaName":222,"dataGaLocation":46},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":46},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":46,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":46},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":46},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":46},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":46},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":46},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":46},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":46},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":46},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":46},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":46},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":46},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":46},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"/images/navigation/the-source-promo-card.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":46},"/the-source/","the source",{"text":312,"config":313,"lists":315},"Company",{"dataNavLevelOne":314},"company",[316],{"items":317},[318,323,329,331,336,341,346,351,356,361,366],{"text":319,"config":320},"About",{"href":321,"dataGaName":322,"dataGaLocation":46},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":46},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":46},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":46},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":46},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":46},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":46},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":46},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":46},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":46},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":46},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":53,"config":378},{"href":55,"dataGaName":379,"dataGaLocation":46},"talk to sales",{"text":381,"config":382},"Get help",{"href":383,"dataGaName":384,"dataGaLocation":46},"/support/","get help",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":46},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":391,"login":392,"suggestions":399},"Close",{"text":393,"link":394},"To search repositories and projects, login to",{"text":395,"config":396},"gitlab.com",{"href":60,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":75,"config":403},{"href":80,"dataGaName":75,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":126,"config":409},{"href":128,"dataGaName":126,"dataGaLocation":398},{"text":411,"config":412},"GitLab on AWS",{"href":413,"dataGaName":411,"dataGaLocation":398},"/partners/technology-partners/aws/",{"text":415,"config":416},"GitLab on Google Cloud",{"href":417,"dataGaName":415,"dataGaLocation":398},"/partners/technology-partners/google-cloud-platform/",{"text":419,"config":420},"Why GitLab?",{"href":88,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":51,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-type.svg",{"text":436,"config":437},"Get Started",{"href":438,"dataGaName":439,"dataGaLocation":426},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":441,"mobileIcon":445,"desktopIcon":447},{"text":442,"config":443},"Learn more about GitLab Duo",{"href":80,"dataGaName":444,"dataGaLocation":426},"gitlab duo",{"altText":428,"config":446},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":448},{"src":434,"dataGaName":431,"dataGaLocation":426},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":454,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"title":455,"button":456,"image":460,"config":463,"_id":465,"_type":32,"_source":34,"_file":466,"_stem":467,"_extension":37},"/shared/en-us/banner","is now in public beta!",{"text":86,"config":457},{"href":458,"dataGaName":459,"dataGaLocation":46},"/gitlab-duo/agent-platform/","duo banner",{"config":461},{"src":462},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":464},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":469,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"data":470,"_id":674,"_type":32,"title":675,"_source":34,"_file":676,"_stem":677,"_extension":37},"/shared/en-us/main-footer",{"text":471,"source":472,"edit":478,"contribute":483,"config":488,"items":493,"minimal":666},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":473,"config":474},"View page source",{"href":475,"dataGaName":476,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":479,"config":480},"Edit this page",{"href":481,"dataGaName":482,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":484,"config":485},"Please contribute",{"href":486,"dataGaName":487,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":489,"facebook":490,"youtube":491,"linkedin":492},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[494,516,573,602,636],{"title":64,"links":495,"subMenu":499},[496],{"text":25,"config":497},{"href":73,"dataGaName":498,"dataGaLocation":477},"devsecops platform",[500],{"title":202,"links":501},[502,506,511],{"text":503,"config":504},"View plans",{"href":204,"dataGaName":505,"dataGaLocation":477},"view plans",{"text":507,"config":508},"Why Premium?",{"href":509,"dataGaName":510,"dataGaLocation":477},"/pricing/premium/","why premium",{"text":512,"config":513},"Why Ultimate?",{"href":514,"dataGaName":515,"dataGaLocation":477},"/pricing/ultimate/","why ultimate",{"title":517,"links":518},"Solutions",[519,524,527,529,534,539,543,546,550,555,557,560,563,568],{"text":520,"config":521},"Digital transformation",{"href":522,"dataGaName":523,"dataGaLocation":477},"/topics/digital-transformation/","digital transformation",{"text":151,"config":525},{"href":146,"dataGaName":526,"dataGaLocation":477},"security & compliance",{"text":140,"config":528},{"href":122,"dataGaName":123,"dataGaLocation":477},{"text":530,"config":531},"Agile development",{"href":532,"dataGaName":533,"dataGaLocation":477},"/solutions/agile-delivery/","agile delivery",{"text":535,"config":536},"Cloud transformation",{"href":537,"dataGaName":538,"dataGaLocation":477},"/topics/cloud-native/","cloud transformation",{"text":540,"config":541},"SCM",{"href":136,"dataGaName":542,"dataGaLocation":477},"source code management",{"text":126,"config":544},{"href":128,"dataGaName":545,"dataGaLocation":477},"continuous integration & delivery",{"text":547,"config":548},"Value stream management",{"href":178,"dataGaName":549,"dataGaLocation":477},"value stream management",{"text":551,"config":552},"GitOps",{"href":553,"dataGaName":554,"dataGaLocation":477},"/solutions/gitops/","gitops",{"text":188,"config":556},{"href":190,"dataGaName":191,"dataGaLocation":477},{"text":558,"config":559},"Small business",{"href":195,"dataGaName":196,"dataGaLocation":477},{"text":561,"config":562},"Public sector",{"href":200,"dataGaName":24,"dataGaLocation":477},{"text":564,"config":565},"Education",{"href":566,"dataGaName":567,"dataGaLocation":477},"/solutions/education/","education",{"text":569,"config":570},"Financial services",{"href":571,"dataGaName":572,"dataGaLocation":477},"/solutions/finance/","financial services",{"title":207,"links":574},[575,577,579,581,584,586,588,590,592,594,596,598,600],{"text":219,"config":576},{"href":221,"dataGaName":222,"dataGaLocation":477},{"text":224,"config":578},{"href":226,"dataGaName":227,"dataGaLocation":477},{"text":229,"config":580},{"href":231,"dataGaName":232,"dataGaLocation":477},{"text":234,"config":582},{"href":236,"dataGaName":583,"dataGaLocation":477},"docs",{"text":257,"config":585},{"href":259,"dataGaName":5,"dataGaLocation":477},{"text":252,"config":587},{"href":254,"dataGaName":255,"dataGaLocation":477},{"text":261,"config":589},{"href":263,"dataGaName":264,"dataGaLocation":477},{"text":274,"config":591},{"href":276,"dataGaName":277,"dataGaLocation":477},{"text":266,"config":593},{"href":268,"dataGaName":269,"dataGaLocation":477},{"text":279,"config":595},{"href":281,"dataGaName":282,"dataGaLocation":477},{"text":284,"config":597},{"href":286,"dataGaName":287,"dataGaLocation":477},{"text":289,"config":599},{"href":291,"dataGaName":292,"dataGaLocation":477},{"text":294,"config":601},{"href":296,"dataGaName":297,"dataGaLocation":477},{"title":312,"links":603},[604,606,608,610,612,614,616,620,625,627,629,631],{"text":319,"config":605},{"href":321,"dataGaName":314,"dataGaLocation":477},{"text":324,"config":607},{"href":326,"dataGaName":327,"dataGaLocation":477},{"text":332,"config":609},{"href":334,"dataGaName":335,"dataGaLocation":477},{"text":337,"config":611},{"href":339,"dataGaName":340,"dataGaLocation":477},{"text":342,"config":613},{"href":344,"dataGaName":345,"dataGaLocation":477},{"text":347,"config":615},{"href":349,"dataGaName":350,"dataGaLocation":477},{"text":617,"config":618},"Sustainability",{"href":619,"dataGaName":617,"dataGaLocation":477},"/sustainability/",{"text":621,"config":622},"Diversity, inclusion and belonging (DIB)",{"href":623,"dataGaName":624,"dataGaLocation":477},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":626},{"href":354,"dataGaName":355,"dataGaLocation":477},{"text":362,"config":628},{"href":364,"dataGaName":365,"dataGaLocation":477},{"text":367,"config":630},{"href":369,"dataGaName":370,"dataGaLocation":477},{"text":632,"config":633},"Modern Slavery Transparency Statement",{"href":634,"dataGaName":635,"dataGaLocation":477},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":637,"links":638},"Contact Us",[639,642,644,646,651,656,661],{"text":640,"config":641},"Contact an expert",{"href":55,"dataGaName":56,"dataGaLocation":477},{"text":381,"config":643},{"href":383,"dataGaName":384,"dataGaLocation":477},{"text":386,"config":645},{"href":388,"dataGaName":389,"dataGaLocation":477},{"text":647,"config":648},"Status",{"href":649,"dataGaName":650,"dataGaLocation":477},"https://status.gitlab.com/","status",{"text":652,"config":653},"Terms of use",{"href":654,"dataGaName":655,"dataGaLocation":477},"/terms/","terms of use",{"text":657,"config":658},"Privacy statement",{"href":659,"dataGaName":660,"dataGaLocation":477},"/privacy/","privacy statement",{"text":662,"config":663},"Cookie preferences",{"dataGaName":664,"dataGaLocation":477,"id":665,"isOneTrustButton":29},"cookie preferences","ot-sdk-btn",{"items":667},[668,670,672],{"text":652,"config":669},{"href":654,"dataGaName":655,"dataGaLocation":477},{"text":657,"config":671},{"href":659,"dataGaName":660,"dataGaLocation":477},{"text":662,"config":673},{"dataGaName":664,"dataGaLocation":477,"id":665,"isOneTrustButton":29},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[679],{"_path":680,"_dir":681,"_draft":6,"_partial":6,"_locale":7,"content":682,"config":686,"_id":688,"_type":32,"title":18,"_source":34,"_file":689,"_stem":690,"_extension":37},"/en-us/blog/authors/fernando-diaz","authors",{"name":18,"config":683},{"headshot":684,"ctfId":685},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659556/Blog/Author%20Headshots/fern_diaz.png","fjdiaz",{"template":687},"BlogAuthor","content:en-us:blog:authors:fernando-diaz.yml","en-us/blog/authors/fernando-diaz.yml","en-us/blog/authors/fernando-diaz",{"_path":692,"_dir":40,"_draft":6,"_partial":6,"_locale":7,"header":693,"eyebrow":694,"blurb":695,"button":696,"secondaryButton":700,"_id":702,"_type":32,"title":703,"_source":34,"_file":704,"_stem":705,"_extension":37},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":48,"config":697},{"href":698,"dataGaName":51,"dataGaLocation":699},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":53,"config":701},{"href":55,"dataGaName":56,"dataGaLocation":699},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1754424515440]