[{"data":1,"prerenderedAt":2456},["ShallowReactive",2],{"/blog/tutorial-security-scanning-in-air-gapped-environments":3,"navigation-en-us":1672,"banner-en-us":2099,"footer-en-us":2109,"blog-post-authors-en-us-Fernando Diaz":2353,"blog-related-posts-en-us-tutorial-security-scanning-in-air-gapped-environments":2368,"blog-promotions-en-us":2393,"next-steps-en-us":2446},{"id":4,"title":5,"authors":6,"body":8,"category":1650,"date":1651,"description":1652,"extension":1653,"externalUrl":1654,"faq":1654,"featured":352,"heroImage":1655,"meta":1656,"navigation":352,"path":1657,"seo":1658,"slug":1663,"stem":1664,"tags":1665,"template":1670,"updatedDate":1654,"__hash__":1671},"blogPosts/en-us/blog/tutorial-security-scanning-in-air-gapped-environments.md","Tutorial: Security scanning in air-gapped environments",[7],"Fernando Diaz",{"type":9,"value":10,"toc":1637},"minimark",[11,15,34,37,42,45,98,113,152,155,162,168,180,186,190,192,194,205,211,215,221,226,229,248,255,473,476,565,572,576,579,591,594,598,607,612,839,844,919,928,932,935,949,952,957,960,1225,1228,1234,1238,1242,1245,1285,1289,1292,1430,1434,1443,1449,1452,1455,1497,1505,1509,1512,1518,1524,1528,1534,1537,1551,1554,1560,1563,1569,1572,1598,1602,1605,1633],[12,13,14],"p",{},"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:",[16,17,18,22,25,28,31],"ul",{},[19,20,21],"li",{},"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.",[19,23,24],{},"Data protection: Air-gapping provides the strongest protection against data exfiltration since there's no direct connection that attackers could use to steal information.",[19,26,27],{},"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.",[19,29,30],{},"Compliance requirements: Many regulatory frameworks require air-gapping for certain types of sensitive data or critical systems, particularly in government, healthcare, and financial sectors.",[19,32,33],{},"Malware protection: Without network connectivity, systems are protected from network-based malware infections and ransomware attacks.",[12,35,36],{},"Even 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.",[38,39,41],"h2",{"id":40},"gitlab-security-scanners-in-air-gapped-environments","GitLab security scanners in air-gapped environments",[12,43,44],{},"GitLab provides a variety of different security scanners for the complete application lifecycle. The scanners that support air-gapped environments include:",[16,46,47,55,63,70,77,84,91],{},[19,48,49],{},[50,51,54],"a",{"href":52,"rel":53},"https://docs.gitlab.com/user/application_security/sast/#running-sast-in-an-offline-environment",[],"Static Application Security Testing (SAST)",[19,56,57,62],{},[50,58,61],{"href":59,"rel":60},"https://docs.gitlab.com/user/application_security/dast/browser/configuration/offline_configuration/",[],"Dynamic Application Security Testing (DAST",")",[19,64,65],{},[50,66,69],{"href":67,"rel":68},"https://docs.gitlab.com/user/application_security/secret_detection/pipeline/#offline-configuration",[],"Secret Detection",[19,71,72],{},[50,73,76],{"href":74,"rel":75},"https://docs.gitlab.com/user/application_security/container_scanning/#running-container-scanning-in-an-offline-environment",[],"Container Scanning",[19,78,79],{},[50,80,83],{"href":81,"rel":82},"https://docs.gitlab.com/user/application_security/dependency_scanning/#offline-environment",[],"Dependency Scanning",[19,85,86],{},[50,87,90],{"href":88,"rel":89},"https://docs.gitlab.com/user/application_security/api_fuzzing/configuration/offline_configuration/",[],"API Fuzzing",[19,92,93],{},[50,94,97],{"href":95,"rel":96},"https://docs.gitlab.com/user/compliance/license_scanning_of_cyclonedx_files/#running-in-an-offline-environment",[],"License Scanning",[12,99,100,101,106,107,112],{},"By default, GitLab Self-Managed instances pull security scanner images from the public GitLab container registry (registry.gitlab.com) and store them within the ",[50,102,105],{"href":103,"rel":104},"https://docs.gitlab.com/user/packages/container_registry/",[],"built-in local GitLab container registry",". I will demonstrate this flow below by running the following pipeline that scans for secrets on a ",[50,108,111],{"href":109,"rel":110},"https://gitlab.com/gitlab-da/tutorials/security-and-governance/owasp/juice-shop",[],"sample project",":",[114,115,120],"pre",{"className":116,"code":117,"language":118,"meta":119,"style":119},"language-yaml shiki shiki-themes github-light","include:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n\n","yaml","",[121,122,123,136],"code",{"__ignoreMap":119},[124,125,128,132],"span",{"class":126,"line":127},"line",1,[124,129,131],{"class":130},"shJU0","include",[124,133,135],{"class":134},"sgsFI",":\n",[124,137,139,142,145,148],{"class":126,"line":138},2,[124,140,141],{"class":134},"  - ",[124,143,144],{"class":130},"template",[124,146,147],{"class":134},": ",[124,149,151],{"class":150},"sYBdl","Jobs/Secret-Detection.gitlab-ci.yml\n",[12,153,154],{},"When running the job in an internet-connected GitLab instance the job passes:",[12,156,157],{},[158,159],"img",{"alt":160,"src":161},"GitLab Runner with internet access successfully pulling from external registry","https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099328/Blog/Content%20Images/Blog/Content%20Images/pass-1_aHR0cHM6_1750099328577.png",[163,164,165],"center",{},[166,167,160],"em",{},[12,169,170,173,175,176,179],{},[171,172],"br",{},[171,174],{},"\nHowever, If I disable internet access to the VM running GitLab, the ",[121,177,178],{},"secret-detection"," job will fail to download the container image, causing the job to fail:",[12,181,182],{},[158,183],{"alt":184,"src":185},"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",[163,187,188],{},[166,189,184],{},[171,191],{},[171,193],{},[12,195,196,197,200,201,204],{},"Alternatively, if I set my GitLab Runners’ pull image policy to ",[121,198,199],{},"if-not-present"," from ",[121,202,203],{},"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:",[12,206,207],{},[158,208],{"alt":209,"src":210},"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",[163,212,213],{},[166,214,209],{},[12,216,217,219],{},[171,218],{},[171,220],{},[222,223,225],"h3",{"id":224},"setting-up-offline-scanning-prerequisites","Setting up offline scanning prerequisites",[12,227,228],{},"Running these security scanners in an air-gapped environment requires the following:",[16,230,231,238,245],{},[19,232,233],{},[50,234,237],{"href":235,"rel":236},"https://about.gitlab.com/pricing/ultimate/",[],"GitLab Ultimate subscription",[19,239,240],{},[50,241,244],{"href":242,"rel":243},"https://about.gitlab.com/pricing/licensing-faq/cloud-licensing/#offline-cloud-licensing",[],"Offline cloud license",[19,246,247],{},"GitLab Self-Managed cluster",[12,249,250,251,254],{},"You 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 ",[121,252,253],{},"EGRESS"," to everything by implementing firewall rules:",[114,256,260],{"className":257,"code":258,"language":259,"meta":119,"style":119},"language-bash shiki shiki-themes github-light","# 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","bash",[121,261,262,268,293,301,309,317,325,333,341,347,354,360,378,385,393,400,408,415,423,428,433,439,459,467],{"__ignoreMap":119},[124,263,264],{"class":126,"line":127},[124,265,267],{"class":266},"sAwPA","# egress firewall rule to block all outbound traffic to the internet\n",[124,269,270,274,277,280,283,286,289],{"class":126,"line":138},[124,271,273],{"class":272},"s7eDp","$",[124,275,276],{"class":150}," gcloud",[124,278,279],{"class":150}," compute",[124,281,282],{"class":150}," firewall-rules",[124,284,285],{"class":150}," create",[124,287,288],{"class":150}," deny-internet-egress",[124,290,292],{"class":291},"sYu0t"," \\\n",[124,294,296,299],{"class":126,"line":295},3,[124,297,298],{"class":291},"    --direction=EGRESS",[124,300,292],{"class":291},[124,302,304,307],{"class":126,"line":303},4,[124,305,306],{"class":291},"    --priority=1000",[124,308,292],{"class":291},[124,310,312,315],{"class":126,"line":311},5,[124,313,314],{"class":291},"    --network=default",[124,316,292],{"class":291},[124,318,320,323],{"class":126,"line":319},6,[124,321,322],{"class":291},"    --action=DENY",[124,324,292],{"class":291},[124,326,328,331],{"class":126,"line":327},7,[124,329,330],{"class":291},"    --rules=all",[124,332,292],{"class":291},[124,334,336,339],{"class":126,"line":335},8,[124,337,338],{"class":291},"    --destination-ranges=0.0.0.0/0",[124,340,292],{"class":291},[124,342,344],{"class":126,"line":343},9,[124,345,346],{"class":291},"    --target-tags=no-internet\n",[124,348,350],{"class":126,"line":349},10,[124,351,353],{"emptyLinePlaceholder":352},true,"\n",[124,355,357],{"class":126,"line":356},11,[124,358,359],{"class":266},"# Create an allow rule for internal traffic with higher priority\n",[124,361,363,365,367,369,371,373,376],{"class":126,"line":362},12,[124,364,273],{"class":272},[124,366,276],{"class":150},[124,368,279],{"class":150},[124,370,282],{"class":150},[124,372,285],{"class":150},[124,374,375],{"class":150}," allow-internal-egress",[124,377,292],{"class":291},[124,379,381,383],{"class":126,"line":380},13,[124,382,298],{"class":291},[124,384,292],{"class":291},[124,386,388,391],{"class":126,"line":387},14,[124,389,390],{"class":291},"    --priority=900",[124,392,292],{"class":291},[124,394,396,398],{"class":126,"line":395},15,[124,397,314],{"class":291},[124,399,292],{"class":291},[124,401,403,406],{"class":126,"line":402},16,[124,404,405],{"class":291},"    --action=ALLOW",[124,407,292],{"class":291},[124,409,411,413],{"class":126,"line":410},17,[124,412,330],{"class":291},[124,414,292],{"class":291},[124,416,418,421],{"class":126,"line":417},18,[124,419,420],{"class":291},"    --destination-ranges=10.0.0.0/8,192.168.0.0/16,172.16.0.0/12",[124,422,292],{"class":291},[124,424,426],{"class":126,"line":425},19,[124,427,346],{"class":291},[124,429,431],{"class":126,"line":430},20,[124,432,353],{"emptyLinePlaceholder":352},[124,434,436],{"class":126,"line":435},21,[124,437,438],{"class":266},"# Apply tag to VM\n",[124,440,442,444,446,448,451,454,457],{"class":126,"line":441},22,[124,443,273],{"class":272},[124,445,276],{"class":150},[124,447,279],{"class":150},[124,449,450],{"class":150}," instances",[124,452,453],{"class":150}," add-tags",[124,455,456],{"class":150}," YOUR_VM_NAME",[124,458,292],{"class":291},[124,460,462,465],{"class":126,"line":461},23,[124,463,464],{"class":291},"    --zone=YOUR_ZONE",[124,466,292],{"class":291},[124,468,470],{"class":126,"line":469},24,[124,471,472],{"class":291},"    --tags=no-internet\n",[12,474,475],{},"Then, once I SSH into my VM, you can see we cannot connect to registry.gitlab.com:",[114,477,479],{"className":257,"code":478,"language":259,"meta":119,"style":119},"# 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",[121,480,481,486,496,513,518,533],{"__ignoreMap":119},[124,482,483],{"class":126,"line":127},[124,484,485],{"class":266},"# showing I can’t access the gitlab container registry\n",[124,487,488,490,493],{"class":126,"line":138},[124,489,273],{"class":272},[124,491,492],{"class":150}," ping",[124,494,495],{"class":150}," registry.gitlab.com\n",[124,497,498,501,504,507,510],{"class":126,"line":295},[124,499,500],{"class":272},"PING",[124,502,503],{"class":150}," registry.gitlab.com",[124,505,506],{"class":134}," (35.227.35.254) 56(",[124,508,509],{"class":272},"84",[124,511,512],{"class":134},") bytes of data.\n",[124,514,515],{"class":126,"line":303},[124,516,517],{"class":272},"^C\n",[124,519,520,523,525,527,530],{"class":126,"line":311},[124,521,522],{"class":272},"---",[124,524,503],{"class":150},[124,526,492],{"class":150},[124,528,529],{"class":150}," statistics",[124,531,532],{"class":291}," ---\n",[124,534,535,538,541,544,547,550,553,556,559,562],{"class":126,"line":319},[124,536,537],{"class":272},"3",[124,539,540],{"class":150}," packets",[124,542,543],{"class":150}," transmitted,",[124,545,546],{"class":291}," 0",[124,548,549],{"class":150}," received,",[124,551,552],{"class":150}," 100%",[124,554,555],{"class":150}," packet",[124,557,558],{"class":150}," loss,",[124,560,561],{"class":150}," time",[124,563,564],{"class":150}," 2031ms\n",[12,566,567,571],{},[568,569,570],"strong",{},"Note:"," I am still allowing ingress so I can copy files and SSH into the machine.",[38,573,575],{"id":574},"load-security-scanners-in-air-gapped-environments","Load security scanners in air-gapped environments",[12,577,578],{},"To 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:",[580,581,582,585,588],"ol",{},[19,583,584],{},"Download and package container images from the public internet.",[19,586,587],{},"Transfer images to offline environment.",[19,589,590],{},"Load transferred images into offline container registry.",[12,592,593],{},"Now let’s go over how we can implement GitLab Secret Detection in an air-gapped environment.",[222,595,597],{"id":596},"download-and-package-container-images-from-public-internet","Download and package container images from public internet",[12,599,600,601,606],{},"Let’s download the container image for secret detection and store it within our local container registry. Other scanner images can be found in the ",[50,602,605],{"href":603,"rel":604},"https://docs.gitlab.com/user/application_security/offline_deployments/",[],"offline deployments documentation",". I will be using Podman desktop to download these images, but you can use Docker desktop or other alternatives.",[580,608,609],{},[19,610,611],{},"Pull the GitLab Secret Detection image.",[114,613,615],{"className":257,"code":614,"language":259,"meta":119,"style":119},"$ 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",[121,616,617,630,643,657,668,677,686,695,704,713,722,731,741,756,775,780,784,793,813],{"__ignoreMap":119},[124,618,619,621,624,627],{"class":126,"line":127},[124,620,273],{"class":272},[124,622,623],{"class":150}," podman",[124,625,626],{"class":150}," pull",[124,628,629],{"class":150}," registry.gitlab.com/security-products/secrets:6\n",[124,631,632,635,638,640],{"class":126,"line":138},[124,633,634],{"class":272},"Trying",[124,636,637],{"class":150}," to",[124,639,626],{"class":150},[124,641,642],{"class":150}," registry.gitlab.com/security-products/secrets:6...\n",[124,644,645,648,651,654],{"class":126,"line":295},[124,646,647],{"class":272},"Getting",[124,649,650],{"class":150}," image",[124,652,653],{"class":150}," source",[124,655,656],{"class":150}," signatures\n",[124,658,659,662,665],{"class":126,"line":303},[124,660,661],{"class":272},"Copying",[124,663,664],{"class":150}," blob",[124,666,667],{"class":150}," sha256:999745130ac045f2b1c29ecce088b43fc4a95bbb82b7960fb7b8abe0e3801bf8\n",[124,669,670,672,674],{"class":126,"line":311},[124,671,661],{"class":272},[124,673,664],{"class":150},[124,675,676],{"class":150}," sha256:a4f7c013bb259c146cd8455b7c3943df7ed84b157e42a2348eef16546d8179b1\n",[124,678,679,681,683],{"class":126,"line":319},[124,680,661],{"class":272},[124,682,664],{"class":150},[124,684,685],{"class":150}," sha256:1f3e46996e2966e4faa5846e56e76e3748b7315e2ded61476c24403d592134f0\n",[124,687,688,690,692],{"class":126,"line":327},[124,689,661],{"class":272},[124,691,664],{"class":150},[124,693,694],{"class":150}," sha256:400a41f248eb3c870bd2b07073632c49f1e164c8efad56ea3b24098a657ec625\n",[124,696,697,699,701],{"class":126,"line":335},[124,698,661],{"class":272},[124,700,664],{"class":150},[124,702,703],{"class":150}," sha256:9090f17a5a1bb80bcc6f393b0715210568dd0a7749286e3334a1a08fb32d34e6\n",[124,705,706,708,710],{"class":126,"line":343},[124,707,661],{"class":272},[124,709,664],{"class":150},[124,711,712],{"class":150}," sha256:c7569783959081164164780f6c1b0bbe1271ee8d291d3e07b2749ae741621ea3\n",[124,714,715,717,719],{"class":126,"line":349},[124,716,661],{"class":272},[124,718,664],{"class":150},[124,720,721],{"class":150}," sha256:20c7ca6108f808ad5905f6db4f7e3c02b21b69abdea8b45abfa34c0a2ba8bdb5\n",[124,723,724,726,728],{"class":126,"line":356},[124,725,661],{"class":272},[124,727,664],{"class":150},[124,729,730],{"class":150}," sha256:e8645a00be64d77c6ff301593ce34cd8c17ffb2b36252ca0f2588009a7918d2e\n",[124,732,733,735,738],{"class":126,"line":362},[124,734,661],{"class":272},[124,736,737],{"class":150}," config",[124,739,740],{"class":150}," sha256:0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\n",[124,742,743,746,749,751,753],{"class":126,"line":380},[124,744,745],{"class":272},"Writing",[124,747,748],{"class":150}," manifest",[124,750,637],{"class":150},[124,752,650],{"class":150},[124,754,755],{"class":150}," destination\n",[124,757,758,761,763,766,769,772],{"class":126,"line":387},[124,759,760],{"class":272},"WARNING:",[124,762,650],{"class":150},[124,764,765],{"class":150}," platform",[124,767,768],{"class":134}," (linux/amd64) does not match the expected platform (",[124,770,771],{"class":272},"linux/arm64",[124,773,774],{"class":134},")\n",[124,776,777],{"class":126,"line":395},[124,778,779],{"class":272},"0235ed43fc7fb2852c76e2d6196601968ae0375c72a517bef714cd712600f894\n",[124,781,782],{"class":126,"line":402},[124,783,353],{"emptyLinePlaceholder":352},[124,785,786,788,790],{"class":126,"line":410},[124,787,273],{"class":272},[124,789,623],{"class":150},[124,791,792],{"class":150}," images\n",[124,794,795,798,801,804,807,810],{"class":126,"line":417},[124,796,797],{"class":272},"REPOSITORY",[124,799,800],{"class":150},"                                                  TAG",[124,802,803],{"class":150}," IMAGE",[124,805,806],{"class":150}," ID",[124,808,809],{"class":150},"      CREATED",[124,811,812],{"class":150},"      SIZE\n",[124,814,815,818,821,824,827,830,833,836],{"class":126,"line":425},[124,816,817],{"class":272},"registry.gitlab.com/security-products/secrets",[124,819,820],{"class":291},"               6",[124,822,823],{"class":150}," 0235ed43fc7f",[124,825,826],{"class":291},"  4",[124,828,829],{"class":150}," hours",[124,831,832],{"class":150}," ago",[124,834,835],{"class":291},"  85.3",[124,837,838],{"class":150}," MB\n",[580,840,841],{"start":138},[19,842,843],{},"Save the image as a tarball.",[114,845,847],{"className":257,"code":846,"language":259,"meta":119,"style":119},"$ 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",[121,848,849,866,879,891],{"__ignoreMap":119},[124,850,851,853,855,858,861,864],{"class":126,"line":127},[124,852,273],{"class":272},[124,854,623],{"class":150},[124,856,857],{"class":150}," save",[124,859,860],{"class":291}," -o",[124,862,863],{"class":150}," secret-detection.tar",[124,865,629],{"class":150},[124,867,868,870,873,876],{"class":126,"line":138},[124,869,273],{"class":272},[124,871,872],{"class":150}," chmod",[124,874,875],{"class":150}," +r",[124,877,878],{"class":150}," secret-detection.tar\n",[124,880,881,883,886,889],{"class":126,"line":295},[124,882,273],{"class":272},[124,884,885],{"class":150}," ls",[124,887,888],{"class":291}," -al",[124,890,878],{"class":150},[124,892,893,896,899,902,905,908,911,914,917],{"class":126,"line":303},[124,894,895],{"class":272},"-rw-r--r--@",[124,897,898],{"class":291}," 1",[124,900,901],{"class":150}," fern",[124,903,904],{"class":150},"  staff",[124,906,907],{"class":291},"  85324800",[124,909,910],{"class":150}," Jan",[124,912,913],{"class":291}," 10",[124,915,916],{"class":150}," 10:25",[124,918,878],{"class":150},[12,920,921,922,927],{},"Alternatively, you can use the ",[50,923,926],{"href":924,"rel":925},"https://docs.gitlab.com/user/application_security/offline_deployments/#using-the-official-gitlab-template",[],"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.",[222,929,931],{"id":930},"transfer-images-to-offline-environment","Transfer images to offline environment",[12,933,934],{},"Next, let's transfer the tarball to our air-gapped environment. This can be done in several ways, depending on your needs, such as:",[16,936,937,940,943,946],{},[19,938,939],{},"Physical media transfer",[19,941,942],{},"Data diodes",[19,944,945],{},"Guard systems",[19,947,948],{},"Cross-domain solutions (CDS)",[12,950,951],{},"I 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.",[953,954,956],"h4",{"id":955},"verify-the-image-is-not-cached","Verify the image is not cached",[12,958,959],{},"Before transferring the file, I’ll delete the Docker images on my GitLab instance pertaining to secret detection to make sure they aren't cached:",[114,961,963],{"className":257,"code":962,"language":259,"meta":119,"style":119},"$ 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",[121,964,965,974,992,1012,1042,1046,1063,1071,1079,1086,1093,1100,1107,1114,1121,1128,1135,1142,1146,1160,1166,1172,1179,1186,1193,1201,1209,1217],{"__ignoreMap":119},[124,966,967,969,972],{"class":126,"line":127},[124,968,273],{"class":272},[124,970,971],{"class":150}," docker",[124,973,792],{"class":150},[124,975,976,978,981,984,986,989],{"class":126,"line":138},[124,977,797],{"class":272},[124,979,980],{"class":150}," TAG",[124,982,983],{"class":150},"              IMAGE",[124,985,806],{"class":150},[124,987,988],{"class":150},"       CREATED",[124,990,991],{"class":150},"        SIZE\n",[124,993,994,996,999,1002,1005,1007,1009],{"class":126,"line":295},[124,995,817],{"class":272},[124,997,998],{"class":291}," 6",[124,1000,1001],{"class":150},"                0235ed43fc7f",[124,1003,1004],{"class":291},"   9",[124,1006,829],{"class":150},[124,1008,832],{"class":150},[124,1010,1011],{"class":150},"    84.8MB\n",[124,1013,1014,1016,1020,1023,1026,1029,1032,1035,1037,1039],{"class":126,"line":303},[124,1015,817],{"class":272},[124,1017,1019],{"class":1018},"sD7c4"," \u003C",[124,1021,1022],{"class":150},"non",[124,1024,1025],{"class":134},"e",[124,1027,1028],{"class":1018},">",[124,1030,1031],{"class":150},"           16d88433af61",[124,1033,1034],{"class":291},"   17",[124,1036,829],{"class":150},[124,1038,832],{"class":150},[124,1040,1041],{"class":150},"   74.9MB\n",[124,1043,1044],{"class":126,"line":311},[124,1045,353],{"emptyLinePlaceholder":352},[124,1047,1048,1050,1052,1054,1057,1060],{"class":126,"line":319},[124,1049,273],{"class":272},[124,1051,971],{"class":150},[124,1053,650],{"class":150},[124,1055,1056],{"class":150}," rmi",[124,1058,1059],{"class":150}," 16d88433af61",[124,1061,1062],{"class":291}," -f\n",[124,1064,1065,1068],{"class":126,"line":327},[124,1066,1067],{"class":272},"Untagged:",[124,1069,1070],{"class":150}," registry.gitlab.com/security-products/secrets@sha256:f331da6631d791fcd58d3f23d868475a520f50b02d64000e2faf1def66c75d48\n",[124,1072,1073,1076],{"class":126,"line":335},[124,1074,1075],{"class":272},"Deleted:",[124,1077,1078],{"class":150}," sha256:16d88433af618f0b405945031de39fe40b3e8ef1bddb91ca036de0f5b32399d7\n",[124,1080,1081,1083],{"class":126,"line":343},[124,1082,1075],{"class":272},[124,1084,1085],{"class":150}," sha256:1bb06f72f06810e95a70039e797481736e492201f51a03b02d27db055248ab6f\n",[124,1087,1088,1090],{"class":126,"line":349},[124,1089,1075],{"class":272},[124,1091,1092],{"class":150}," sha256:a5ef2325ce4be9b39993ce301f8ed7aad1c854d7ee66f26a56a96967c6606510\n",[124,1094,1095,1097],{"class":126,"line":356},[124,1096,1075],{"class":272},[124,1098,1099],{"class":150}," sha256:f7cdac818a36d6c023763b76a6589c0db7609ca883306af4f38b819e62f29471\n",[124,1101,1102,1104],{"class":126,"line":362},[124,1103,1075],{"class":272},[124,1105,1106],{"class":150}," sha256:5eabf4d47287dee9887b9692d55c8b5f848b50b3b7248f67913036014e74a0e9\n",[124,1108,1109,1111],{"class":126,"line":380},[124,1110,1075],{"class":272},[124,1112,1113],{"class":150}," sha256:51b7cb600604c0737356f17bc02c22bac3a63697f0bf95ba7bacb5b421fdb7da\n",[124,1115,1116,1118],{"class":126,"line":387},[124,1117,1075],{"class":272},[124,1119,1120],{"class":150}," sha256:1546193b011d192aa769a15d3fdd55eb4e187f201f5ff7506243abb02525dc06\n",[124,1122,1123,1125],{"class":126,"line":395},[124,1124,1075],{"class":272},[124,1126,1127],{"class":150}," sha256:1ea72408d0484c3059cc0008539e6f494dc829caa1a97d156795687d42d9cb57\n",[124,1129,1130,1132],{"class":126,"line":402},[124,1131,1075],{"class":272},[124,1133,1134],{"class":150}," sha256:1313ee9da7716d85f63cfdd1129f715e9bbb6c9c0306e4708ee73672b3e40f26\n",[124,1136,1137,1139],{"class":126,"line":410},[124,1138,1075],{"class":272},[124,1140,1141],{"class":150}," sha256:954ebfd83406f0dfed93eb5157ba841af5426aa95d4054174fff45095fd873a1\n",[124,1143,1144],{"class":126,"line":417},[124,1145,353],{"emptyLinePlaceholder":352},[124,1147,1148,1150,1152,1154,1156,1158],{"class":126,"line":425},[124,1149,273],{"class":272},[124,1151,971],{"class":150},[124,1153,650],{"class":150},[124,1155,1056],{"class":150},[124,1157,823],{"class":150},[124,1159,1062],{"class":291},[124,1161,1162,1164],{"class":126,"line":430},[124,1163,1067],{"class":272},[124,1165,629],{"class":150},[124,1167,1168,1170],{"class":126,"line":435},[124,1169,1075],{"class":272},[124,1171,740],{"class":150},[124,1173,1174,1176],{"class":126,"line":441},[124,1175,1075],{"class":272},[124,1177,1178],{"class":150}," sha256:f05f85850cf4fac79e279d93afb6645c026de0223d07b396fce86c2f76096c1f\n",[124,1180,1181,1183],{"class":126,"line":461},[124,1182,1075],{"class":272},[124,1184,1185],{"class":150}," sha256:7432b0766b885144990edd3166fbabed081be71d28d186f4d525e52729f06b1f\n",[124,1187,1188,1190],{"class":126,"line":469},[124,1189,1075],{"class":272},[124,1191,1192],{"class":150}," sha256:2c6e3361c2ee2f43bd75fb9c7c12d981ce06df2d51a134965fa47754760efff0\n",[124,1194,1196,1198],{"class":126,"line":1195},25,[124,1197,1075],{"class":272},[124,1199,1200],{"class":150}," sha256:7ad7f7245b45fbe758ebd5788e0ba268a56829715527a9a4bc51708c21af1c7f\n",[124,1202,1204,1206],{"class":126,"line":1203},26,[124,1205,1075],{"class":272},[124,1207,1208],{"class":150}," sha256:3b73a621115a59564979f41552181dce07f3baa17e27428f7fff2155042a1901\n",[124,1210,1212,1214],{"class":126,"line":1211},27,[124,1213,1075],{"class":272},[124,1215,1216],{"class":150}," sha256:78648c2606a7c4c76885806ed976b13e4d008940bd3d7a18b52948a6be71b60d\n",[124,1218,1220,1222],{"class":126,"line":1219},28,[124,1221,1075],{"class":272},[124,1223,1224],{"class":150}," sha256:383d4a6dc5be9914878700809b4a3925379c80ab792dfe9e79d14b0c1d6b5fad\n",[12,1226,1227],{},"Then I'll rerun the job to show the failure:",[12,1229,1230],{},[158,1231],{"alt":1232,"src":1233},"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",[163,1235,1236],{},[166,1237,1232],{},[953,1239,1241],{"id":1240},"scp-file-to-gitlab-instance","SCP file to GitLab instance",[12,1243,1244],{},"Now, from my local machine, I will SCP the file to my GitLab instance as follows:",[114,1246,1248],{"className":257,"code":1247,"language":259,"meta":119,"style":119},"$ gcloud compute scp secret-detection.tar INSTANCE:~ --zone=ZONE\nsecret-detection.tar 100%   81MB  21.5MB/s   00:03\n",[121,1249,1250,1269],{"__ignoreMap":119},[124,1251,1252,1254,1256,1258,1261,1263,1266],{"class":126,"line":127},[124,1253,273],{"class":272},[124,1255,276],{"class":150},[124,1257,279],{"class":150},[124,1259,1260],{"class":150}," scp",[124,1262,863],{"class":150},[124,1264,1265],{"class":150}," INSTANCE:~",[124,1267,1268],{"class":291}," --zone=ZONE\n",[124,1270,1271,1274,1276,1279,1282],{"class":126,"line":138},[124,1272,1273],{"class":272},"secret-detection.tar",[124,1275,552],{"class":150},[124,1277,1278],{"class":150},"   81MB",[124,1280,1281],{"class":150},"  21.5MB/s",[124,1283,1284],{"class":150},"   00:03\n",[222,1286,1288],{"id":1287},"load-transferred-images-into-offline-container-registry","Load transferred images into offline container registry",[12,1290,1291],{},"Next, I'll SSH into my VM and load the Docker image:",[114,1293,1295],{"className":257,"code":1294,"language":259,"meta":119,"style":119},"$ 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",[121,1296,1297,1313,1317,1334,1348,1360,1372,1384,1396,1408,1420],{"__ignoreMap":119},[124,1298,1299,1301,1303,1305,1308,1311],{"class":126,"line":127},[124,1300,273],{"class":272},[124,1302,276],{"class":150},[124,1304,279],{"class":150},[124,1306,1307],{"class":150}," ssh",[124,1309,1310],{"class":150}," INSTANCE",[124,1312,1268],{"class":291},[124,1314,1315],{"class":126,"line":138},[124,1316,353],{"emptyLinePlaceholder":352},[124,1318,1319,1321,1324,1326,1329,1332],{"class":126,"line":295},[124,1320,273],{"class":272},[124,1322,1323],{"class":150}," sudo",[124,1325,971],{"class":150},[124,1327,1328],{"class":150}," load",[124,1330,1331],{"class":291}," -i",[124,1333,878],{"class":150},[124,1335,1336,1339,1342,1345],{"class":126,"line":303},[124,1337,1338],{"class":272},"c3c8e454c212:",[124,1340,1341],{"class":150}," Loading",[124,1343,1344],{"class":150}," layer",[124,1346,1347],{"class":134}," [==================================================>]  2.521MB/2.521MB\n",[124,1349,1350,1353,1355,1357],{"class":126,"line":311},[124,1351,1352],{"class":272},"51e93afaeedc:",[124,1354,1341],{"class":150},[124,1356,1344],{"class":150},[124,1358,1359],{"class":134}," [==================================================>]  32.55MB/32.55MB\n",[124,1361,1362,1365,1367,1369],{"class":126,"line":319},[124,1363,1364],{"class":272},"e8a25e39bb30:",[124,1366,1341],{"class":150},[124,1368,1344],{"class":150},[124,1370,1371],{"class":134}," [==================================================>]  221.2kB/221.2kB\n",[124,1373,1374,1377,1379,1381],{"class":126,"line":327},[124,1375,1376],{"class":272},"390704968493:",[124,1378,1341],{"class":150},[124,1380,1344],{"class":150},[124,1382,1383],{"class":134}," [==================================================>]  225.8kB/225.8kB\n",[124,1385,1386,1389,1391,1393],{"class":126,"line":335},[124,1387,1388],{"class":272},"76cf57e75f63:",[124,1390,1341],{"class":150},[124,1392,1344],{"class":150},[124,1394,1395],{"class":134}," [==================================================>]  17.64MB/17.64MB\n",[124,1397,1398,1401,1403,1405],{"class":126,"line":343},[124,1399,1400],{"class":272},"c4c7a681fd10:",[124,1402,1341],{"class":150},[124,1404,1344],{"class":150},[124,1406,1407],{"class":134}," [==================================================>]  4.608kB/4.608kB\n",[124,1409,1410,1413,1415,1417],{"class":126,"line":349},[124,1411,1412],{"class":272},"f0690f406157:",[124,1414,1341],{"class":150},[124,1416,1344],{"class":150},[124,1418,1419],{"class":134}," [==================================================>]  24.01MB/24.01MB\n",[124,1421,1422,1425,1428],{"class":126,"line":356},[124,1423,1424],{"class":272},"Loaded",[124,1426,1427],{"class":150}," image:",[124,1429,629],{"class":150},[222,1431,1433],{"id":1432},"run-the-scanners","Run the scanners",[12,1435,1436,1437,1442],{},"I'll ",[50,1438,1441],{"href":1439,"rel":1440},"https://docs.gitlab.com/ci/pipelines/#run-a-pipeline-manually",[],"re-run the pipeline manually"," and the scanner will be pulled from the cache. Once the pipeline completes, we can see the secret detection job is successful:",[12,1444,1445],{},[158,1446],{"alt":1447,"src":1448},"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",[163,1450,1451],{},"*GitLab Runner without internet access successfully pulling from internal registry cache after image loaded",[12,1453,1454],{},"If 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:",[114,1456,1458],{"className":116,"code":1457,"language":118,"meta":119,"style":119},"include:\n  - template: Jobs/Secret-Detection.gitlab-ci.yml\n\nvariables:\n  SECURE_ANALYZERS_PREFIX: \"localhost:5000/analyzers\"\n\n",[121,1459,1460,1466,1476,1480,1487],{"__ignoreMap":119},[124,1461,1462,1464],{"class":126,"line":127},[124,1463,131],{"class":130},[124,1465,135],{"class":134},[124,1467,1468,1470,1472,1474],{"class":126,"line":138},[124,1469,141],{"class":134},[124,1471,144],{"class":130},[124,1473,147],{"class":134},[124,1475,151],{"class":150},[124,1477,1478],{"class":126,"line":295},[124,1479,353],{"emptyLinePlaceholder":352},[124,1481,1482,1485],{"class":126,"line":303},[124,1483,1484],{"class":130},"variables",[124,1486,135],{"class":134},[124,1488,1489,1492,1494],{"class":126,"line":311},[124,1490,1491],{"class":130},"  SECURE_ANALYZERS_PREFIX",[124,1493,147],{"class":134},[124,1495,1496],{"class":150},"\"localhost:5000/analyzers\"\n",[12,1498,1499,1500,1504],{},"See the ",[50,1501,1503],{"href":603,"rel":1502},[],"offline environments documentation"," for more information.",[222,1506,1508],{"id":1507},"view-scanner-results","View scanner results",[12,1510,1511],{},"Once 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.",[12,1513,1514,1515,112],{},"You can access the vulnerability report by navigating to the side tab and selecting ",[568,1516,1517],{},"Secure > Vulnerability Report",[12,1519,1520],{},[158,1521],{"alt":1522,"src":1523},"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",[163,1525,1526],{},[166,1527,1522],{},[12,1529,1530,1532],{},[171,1531],{},[171,1533],{},[12,1535,1536],{},"The project’s vulnerability report provides:",[16,1538,1539,1542,1545,1548],{},[19,1540,1541],{},"totals of vulnerabilities per severity level",[19,1543,1544],{},"filters for common vulnerability attributes",[19,1546,1547],{},"details of each vulnerability, presented in tabular layout",[19,1549,1550],{},"a timestamp showing when it was updated, including a link to the latest pipeline",[12,1552,1553],{},"We 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:",[12,1555,1556],{},[158,1557],{"alt":1558,"src":1559},"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",[163,1561,1562],{},"*GitLab Vulnerability Page showing detailed insights",[12,1564,1565,1567],{},[171,1566],{},[171,1568],{},[12,1570,1571],{},"The vulnerability page provides details of the vulnerability, which can be used to triage and find a path to remediation. These vulnerability details include:",[16,1573,1574,1577,1580,1583,1586,1589,1592,1595],{},[19,1575,1576],{},"description",[19,1578,1579],{},"when it was detected",[19,1581,1582],{},"current status",[19,1584,1585],{},"available actions",[19,1587,1588],{},"linked issues",[19,1590,1591],{},"actions log",[19,1593,1594],{},"filename and line number of the vulnerability (if available)",[19,1596,1597],{},"severity",[38,1599,1601],{"id":1600},"read-more","Read more",[12,1603,1604],{},"To learn more about GitLab and running security scanners in air-gapped environments, check out the following resources:",[16,1606,1607,1613,1620,1626],{},[19,1608,1609],{},[50,1610,1612],{"href":235,"rel":1611},[],"GitLab Ultimate",[19,1614,1615],{},[50,1616,1619],{"href":1617,"rel":1618},"https://about.gitlab.com/solutions/application-security-testing/",[],"GitLab Security and Compliance Solutions",[19,1621,1622],{},[50,1623,1625],{"href":603,"rel":1624},[],"GitLab Offline Deployments Documentation",[19,1627,1628],{},[50,1629,1632],{"href":1630,"rel":1631},"https://docs.gitlab.com/user/application_security/",[],"GitLab Application Security Documentation",[1634,1635,1636],"style",{},"html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}",{"title":119,"searchDepth":138,"depth":138,"links":1638},[1639,1642,1649],{"id":40,"depth":138,"text":41,"children":1640},[1641],{"id":224,"depth":295,"text":225},{"id":574,"depth":138,"text":575,"children":1643},[1644,1645,1646,1647,1648],{"id":596,"depth":295,"text":597},{"id":930,"depth":295,"text":931},{"id":1287,"depth":295,"text":1288},{"id":1432,"depth":295,"text":1433},{"id":1507,"depth":295,"text":1508},{"id":1600,"depth":138,"text":1601},"security","2025-02-05","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.","md",null,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1750099301/Blog/Hero%20Images/Blog/Hero%20Images/AdobeStock_1097303277_6gTk7M1DNx0tFuovupVFB1_1750099300786.jpg",{},"/en-us/blog/tutorial-security-scanning-in-air-gapped-environments",{"title":5,"description":1652,"ogTitle":5,"ogDescription":1652,"noIndex":1659,"ogImage":1655,"ogUrl":1660,"ogSiteName":1661,"ogType":1662,"canonicalUrls":1660},false,"https://about.gitlab.com/blog/tutorial-security-scanning-in-air-gapped-environments","https://about.gitlab.com","article","tutorial-security-scanning-in-air-gapped-environments","en-us/blog/tutorial-security-scanning-in-air-gapped-environments",[1666,1650,1667,1668,1669],"tutorial","public sector","DevSecOps platform","features","BlogPost","LilHcwUTl-Cp5biPwciyC1l5Az4-voYhA9gkrdhhwPg",{"logo":1673,"freeTrial":1678,"sales":1683,"login":1688,"items":1693,"search":2019,"minimal":2050,"duo":2069,"switchNav":2078,"pricingDeployment":2089},{"config":1674},{"href":1675,"dataGaName":1676,"dataGaLocation":1677},"/","gitlab logo","header",{"text":1679,"config":1680},"Get free trial",{"href":1681,"dataGaName":1682,"dataGaLocation":1677},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1684,"config":1685},"Request a demo",{"href":1686,"dataGaName":1687,"dataGaLocation":1677},"/sales/?contact-topic=request-demo","sales",{"text":1689,"config":1690},"Sign in",{"href":1691,"dataGaName":1692,"dataGaLocation":1677},"https://gitlab.com/users/sign_in/","sign in",[1694,1723,1822,1827,1941,1997],{"text":1695,"config":1696,"menu":1698},"Platform",{"dataNavLevelOne":1697},"platform",{"type":1699,"columns":1700},"cards",[1701,1707,1715],{"title":1695,"description":1702,"link":1703},"The intelligent orchestration platform for DevSecOps",{"text":1704,"config":1705},"Explore our Platform",{"href":1706,"dataGaName":1697,"dataGaLocation":1677},"/platform/",{"title":1708,"description":1709,"link":1710},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1711,"config":1712},"Meet GitLab Duo",{"href":1713,"dataGaName":1714,"dataGaLocation":1677},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1716,"description":1717,"link":1718},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1719,"config":1720},"Learn more",{"href":1721,"dataGaName":1722,"dataGaLocation":1677},"/why-gitlab/","why gitlab",{"text":1724,"left":352,"config":1725,"menu":1727},"Product",{"dataNavLevelOne":1726},"solutions",{"type":1728,"link":1729,"columns":1733,"feature":1802},"lists",{"text":1730,"config":1731},"View all Solutions",{"href":1732,"dataGaName":1726,"dataGaLocation":1677},"/solutions/",[1734,1758,1781],{"title":1735,"description":1736,"link":1737,"items":1742},"Automation","CI/CD and automation to accelerate deployment",{"config":1738},{"icon":1739,"href":1740,"dataGaName":1741,"dataGaLocation":1677},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1743,1747,1750,1754],{"text":1744,"config":1745},"CI/CD",{"href":1746,"dataGaLocation":1677,"dataGaName":1744},"/solutions/continuous-integration/",{"text":1708,"config":1748},{"href":1713,"dataGaLocation":1677,"dataGaName":1749},"gitlab duo agent platform - product menu",{"text":1751,"config":1752},"Source Code Management",{"href":1753,"dataGaLocation":1677,"dataGaName":1751},"/solutions/source-code-management/",{"text":1755,"config":1756},"Automated Software Delivery",{"href":1740,"dataGaLocation":1677,"dataGaName":1757},"Automated software delivery",{"title":1759,"description":1760,"link":1761,"items":1766},"Security","Deliver code faster without compromising security",{"config":1762},{"href":1763,"dataGaName":1764,"dataGaLocation":1677,"icon":1765},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1767,1771,1776],{"text":1768,"config":1769},"Application Security Testing",{"href":1763,"dataGaName":1770,"dataGaLocation":1677},"Application security testing",{"text":1772,"config":1773},"Software Supply Chain Security",{"href":1774,"dataGaLocation":1677,"dataGaName":1775},"/solutions/supply-chain/","Software supply chain security",{"text":1777,"config":1778},"Software Compliance",{"href":1779,"dataGaName":1780,"dataGaLocation":1677},"/solutions/software-compliance/","software compliance",{"title":1782,"link":1783,"items":1788},"Measurement",{"config":1784},{"icon":1785,"href":1786,"dataGaName":1787,"dataGaLocation":1677},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1789,1793,1797],{"text":1790,"config":1791},"Visibility & Measurement",{"href":1786,"dataGaLocation":1677,"dataGaName":1792},"Visibility and Measurement",{"text":1794,"config":1795},"Value Stream Management",{"href":1796,"dataGaLocation":1677,"dataGaName":1794},"/solutions/value-stream-management/",{"text":1798,"config":1799},"Analytics & Insights",{"href":1800,"dataGaLocation":1677,"dataGaName":1801},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1803,"type":1728,"items":1804},"GitLab for",[1805,1811,1817],{"text":1806,"config":1807},"Enterprise",{"icon":1808,"href":1809,"dataGaLocation":1677,"dataGaName":1810},"Building","/enterprise/","enterprise",{"text":1812,"config":1813},"Small Business",{"icon":1814,"href":1815,"dataGaLocation":1677,"dataGaName":1816},"Work","/small-business/","small business",{"text":1818,"config":1819},"Public Sector",{"icon":1820,"href":1821,"dataGaLocation":1677,"dataGaName":1667},"Organization","/solutions/public-sector/",{"text":1823,"config":1824},"Pricing",{"href":1825,"dataGaName":1826,"dataGaLocation":1677,"dataNavLevelOne":1826},"/pricing/","pricing",{"text":1828,"config":1829,"menu":1831},"Resources",{"dataNavLevelOne":1830},"resources",{"type":1728,"link":1832,"columns":1836,"feature":1930},{"text":1833,"config":1834},"View all resources",{"href":1835,"dataGaName":1830,"dataGaLocation":1677},"/resources/",[1837,1870,1897],{"title":1838,"items":1839},"Getting started",[1840,1845,1850,1855,1860,1865],{"text":1841,"config":1842},"Install",{"href":1843,"dataGaName":1844,"dataGaLocation":1677},"/install/","install",{"text":1846,"config":1847},"Quick start guides",{"href":1848,"dataGaName":1849,"dataGaLocation":1677},"/get-started/","quick setup checklists",{"text":1851,"config":1852},"Learn",{"href":1853,"dataGaLocation":1677,"dataGaName":1854},"https://university.gitlab.com/","learn",{"text":1856,"config":1857},"Product documentation",{"href":1858,"dataGaName":1859,"dataGaLocation":1677},"https://docs.gitlab.com/","product documentation",{"text":1861,"config":1862},"Best practice videos",{"href":1863,"dataGaName":1864,"dataGaLocation":1677},"/getting-started-videos/","best practice videos",{"text":1866,"config":1867},"Integrations",{"href":1868,"dataGaName":1869,"dataGaLocation":1677},"/integrations/","integrations",{"title":1871,"items":1872},"Discover",[1873,1878,1883,1888,1892],{"text":1874,"config":1875},"Customer success stories",{"href":1876,"dataGaName":1877,"dataGaLocation":1677},"/customers/","customer success stories",{"text":1879,"config":1880},"Blog",{"href":1881,"dataGaName":1882,"dataGaLocation":1677},"/blog/","blog",{"text":1884,"config":1885},"Demo Hub",{"href":1886,"dataGaName":1887,"dataGaLocation":1677},"/demo-hub/","demo hub",{"text":1889,"config":1890},"The Source",{"href":1891,"dataGaName":1882,"dataGaLocation":1677},"/the-source/",{"text":1893,"config":1894},"Remote",{"href":1895,"dataGaName":1896,"dataGaLocation":1677},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1898,"items":1899},"Connect",[1900,1905,1910,1915,1920,1925],{"text":1901,"config":1902},"GitLab Services",{"href":1903,"dataGaName":1904,"dataGaLocation":1677},"/services/","services",{"text":1906,"config":1907},"Contribute",{"href":1908,"dataGaName":1909,"dataGaLocation":1677},"https://contributors.gitlab.com","contribute",{"text":1911,"config":1912},"Community",{"href":1913,"dataGaName":1914,"dataGaLocation":1677},"/community/","community",{"text":1916,"config":1917},"Forum",{"href":1918,"dataGaName":1919,"dataGaLocation":1677},"https://forum.gitlab.com/","forum",{"text":1921,"config":1922},"Events",{"href":1923,"dataGaName":1924,"dataGaLocation":1677},"/events/","events",{"text":1926,"config":1927},"Partners",{"href":1928,"dataGaName":1929,"dataGaLocation":1677},"/partners/","partners",{"config":1931,"title":1934,"text":1935,"link":1936},{"background":1932,"textColor":1933},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1937,"config":1938},"Read the latest",{"href":1939,"dataGaName":1940,"dataGaLocation":1677},"/whats-new/","whats new",{"text":1942,"config":1943,"menu":1945},"Company",{"dataNavLevelOne":1944},"company",{"type":1728,"columns":1946},[1947],{"items":1948},[1949,1954,1960,1962,1967,1972,1977,1982,1987,1992],{"text":1950,"config":1951},"About",{"href":1952,"dataGaName":1953,"dataGaLocation":1677},"/company/","about",{"text":1955,"config":1956,"footerGa":1959},"Jobs",{"href":1957,"dataGaName":1958,"dataGaLocation":1677},"/jobs/","jobs",{"dataGaName":1958},{"text":1921,"config":1961},{"href":1923,"dataGaName":1924,"dataGaLocation":1677},{"text":1963,"config":1964},"Leadership",{"href":1965,"dataGaName":1966,"dataGaLocation":1677},"/company/team/e-group/","leadership",{"text":1968,"config":1969},"Handbook",{"href":1970,"dataGaName":1971,"dataGaLocation":1677},"https://handbook.gitlab.com/","handbook",{"text":1973,"config":1974},"Investor relations",{"href":1975,"dataGaName":1976,"dataGaLocation":1677},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1978,"config":1979},"Trust Center",{"href":1980,"dataGaName":1981,"dataGaLocation":1677},"/security/","trust center",{"text":1983,"config":1984},"AI Transparency Center",{"href":1985,"dataGaName":1986,"dataGaLocation":1677},"/ai-transparency-center/","ai transparency center",{"text":1988,"config":1989},"Newsletter",{"href":1990,"dataGaName":1991,"dataGaLocation":1677},"/company/contact/#contact-forms","newsletter",{"text":1993,"config":1994},"Press",{"href":1995,"dataGaName":1996,"dataGaLocation":1677},"/press/","press",{"text":1998,"config":1999,"menu":2000},"Contact us",{"dataNavLevelOne":1944},{"type":1728,"columns":2001},[2002],{"items":2003},[2004,2009,2014],{"text":2005,"config":2006},"Talk to sales",{"href":2007,"dataGaName":2008,"dataGaLocation":1677},"/sales/","talk to sales",{"text":2010,"config":2011},"Support portal",{"href":2012,"dataGaName":2013,"dataGaLocation":1677},"https://support.gitlab.com/hc/en-us","support portal",{"text":2015,"config":2016},"Customer portal",{"href":2017,"dataGaName":2018,"dataGaLocation":1677},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":2020,"login":2021,"suggestions":2028},"Close",{"text":2022,"link":2023},"To search repositories and projects, login to",{"text":2024,"config":2025},"gitlab.com",{"href":1691,"dataGaName":2026,"dataGaLocation":2027},"search login","search",{"text":2029,"default":2030},"Suggestions",[2031,2033,2037,2039,2043,2047],{"text":1708,"config":2032},{"href":1713,"dataGaName":1708,"dataGaLocation":2027},{"text":2034,"config":2035},"Code Suggestions (AI)",{"href":2036,"dataGaName":2034,"dataGaLocation":2027},"/solutions/code-suggestions/",{"text":1744,"config":2038},{"href":1746,"dataGaName":1744,"dataGaLocation":2027},{"text":2040,"config":2041},"GitLab on AWS",{"href":2042,"dataGaName":2040,"dataGaLocation":2027},"/partners/technology-partners/aws/",{"text":2044,"config":2045},"GitLab on Google Cloud",{"href":2046,"dataGaName":2044,"dataGaLocation":2027},"/partners/technology-partners/google-cloud-platform/",{"text":2048,"config":2049},"Why GitLab?",{"href":1721,"dataGaName":2048,"dataGaLocation":2027},{"freeTrial":2051,"mobileIcon":2056,"desktopIcon":2061,"secondaryButton":2064},{"text":2052,"config":2053},"Start free trial",{"href":2054,"dataGaName":1682,"dataGaLocation":2055},"https://gitlab.com/-/trials/new/","nav",{"altText":2057,"config":2058},"Gitlab Icon",{"src":2059,"dataGaName":2060,"dataGaLocation":2055},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":2057,"config":2062},{"src":2063,"dataGaName":2060,"dataGaLocation":2055},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":2065,"config":2066},"Get Started",{"href":2067,"dataGaName":2068,"dataGaLocation":2055},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":2070,"mobileIcon":2074,"desktopIcon":2076},{"text":2071,"config":2072},"Learn more about GitLab Duo",{"href":1713,"dataGaName":2073,"dataGaLocation":2055},"gitlab duo",{"altText":2057,"config":2075},{"src":2059,"dataGaName":2060,"dataGaLocation":2055},{"altText":2057,"config":2077},{"src":2063,"dataGaName":2060,"dataGaLocation":2055},{"button":2079,"mobileIcon":2084,"desktopIcon":2086},{"text":2080,"config":2081},"/switch",{"href":2082,"dataGaName":2083,"dataGaLocation":2055},"#contact","switch",{"altText":2057,"config":2085},{"src":2059,"dataGaName":2060,"dataGaLocation":2055},{"altText":2057,"config":2087},{"src":2088,"dataGaName":2060,"dataGaLocation":2055},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":2090,"mobileIcon":2095,"desktopIcon":2097},{"text":2091,"config":2092},"Back to pricing",{"href":1825,"dataGaName":2093,"dataGaLocation":2055,"icon":2094},"back to pricing","GoBack",{"altText":2057,"config":2096},{"src":2059,"dataGaName":2060,"dataGaLocation":2055},{"altText":2057,"config":2098},{"src":2063,"dataGaName":2060,"dataGaLocation":2055},{"title":2100,"titleMobile":2101,"button":2102,"config":2107},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1719,"config":2103},{"href":2104,"dataGaName":2105,"dataGaLocation":2106},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":2108,"disabled":1659},"release",{"data":2110},{"text":2111,"source":2112,"edit":2118,"contribute":2123,"config":2128,"items":2133,"minimal":2342},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":2113,"config":2114},"View page source",{"href":2115,"dataGaName":2116,"dataGaLocation":2117},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":2119,"config":2120},"Edit this page",{"href":2121,"dataGaName":2122,"dataGaLocation":2117},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":2124,"config":2125},"Please contribute",{"href":2126,"dataGaName":2127,"dataGaLocation":2117},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":2129,"facebook":2130,"youtube":2131,"linkedin":2132},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[2134,2181,2234,2278,2310],{"title":1823,"links":2135,"subMenu":2150},[2136,2140,2145],{"text":2137,"config":2138},"View plans",{"href":1825,"dataGaName":2139,"dataGaLocation":2117},"view plans",{"text":2141,"config":2142},"Why Premium?",{"href":2143,"dataGaName":2144,"dataGaLocation":2117},"/pricing/premium/","why premium",{"text":2146,"config":2147},"Why Ultimate?",{"href":2148,"dataGaName":2149,"dataGaLocation":2117},"/pricing/ultimate/","why ultimate",[2151],{"title":2152,"links":2153},"Contact Us",[2154,2157,2159,2161,2166,2171,2176],{"text":2155,"config":2156},"Contact sales",{"href":2007,"dataGaName":1687,"dataGaLocation":2117},{"text":2010,"config":2158},{"href":2012,"dataGaName":2013,"dataGaLocation":2117},{"text":2015,"config":2160},{"href":2017,"dataGaName":2018,"dataGaLocation":2117},{"text":2162,"config":2163},"Status",{"href":2164,"dataGaName":2165,"dataGaLocation":2117},"https://status.gitlab.com/","status",{"text":2167,"config":2168},"Terms of use",{"href":2169,"dataGaName":2170,"dataGaLocation":2117},"/terms/","terms of use",{"text":2172,"config":2173},"Privacy statement",{"href":2174,"dataGaName":2175,"dataGaLocation":2117},"/privacy/","privacy statement",{"text":2177,"config":2178},"Cookie preferences",{"dataGaName":2179,"dataGaLocation":2117,"id":2180,"isOneTrustButton":352},"cookie preferences","ot-sdk-btn",{"title":1724,"links":2182,"subMenu":2190},[2183,2186],{"text":1668,"config":2184},{"href":1706,"dataGaName":2185,"dataGaLocation":2117},"devsecops platform",{"text":2187,"config":2188},"AI-Assisted Development",{"href":1713,"dataGaName":2189,"dataGaLocation":2117},"ai-assisted development",[2191],{"title":2192,"links":2193},"Topics",[2194,2199,2204,2209,2214,2219,2224,2229],{"text":2195,"config":2196},"CICD",{"href":2197,"dataGaName":2198,"dataGaLocation":2117},"/topics/ci-cd/","cicd",{"text":2200,"config":2201},"GitOps",{"href":2202,"dataGaName":2203,"dataGaLocation":2117},"/topics/gitops/","gitops",{"text":2205,"config":2206},"DevOps",{"href":2207,"dataGaName":2208,"dataGaLocation":2117},"/topics/devops/","devops",{"text":2210,"config":2211},"Version Control",{"href":2212,"dataGaName":2213,"dataGaLocation":2117},"/topics/version-control/","version control",{"text":2215,"config":2216},"DevSecOps",{"href":2217,"dataGaName":2218,"dataGaLocation":2117},"/topics/devsecops/","devsecops",{"text":2220,"config":2221},"Cloud Native",{"href":2222,"dataGaName":2223,"dataGaLocation":2117},"/topics/cloud-native/","cloud native",{"text":2225,"config":2226},"AI for Coding",{"href":2227,"dataGaName":2228,"dataGaLocation":2117},"/topics/devops/ai-for-coding/","ai for coding",{"text":2230,"config":2231},"Agentic AI",{"href":2232,"dataGaName":2233,"dataGaLocation":2117},"/topics/agentic-ai/","agentic ai",{"title":2235,"links":2236},"Solutions",[2237,2239,2241,2246,2250,2253,2257,2260,2262,2265,2268,2273],{"text":1768,"config":2238},{"href":1763,"dataGaName":1768,"dataGaLocation":2117},{"text":1757,"config":2240},{"href":1740,"dataGaName":1741,"dataGaLocation":2117},{"text":2242,"config":2243},"Agile development",{"href":2244,"dataGaName":2245,"dataGaLocation":2117},"/solutions/agile-delivery/","agile delivery",{"text":2247,"config":2248},"SCM",{"href":1753,"dataGaName":2249,"dataGaLocation":2117},"source code management",{"text":2195,"config":2251},{"href":1746,"dataGaName":2252,"dataGaLocation":2117},"continuous integration & delivery",{"text":2254,"config":2255},"Value stream management",{"href":1796,"dataGaName":2256,"dataGaLocation":2117},"value stream management",{"text":2200,"config":2258},{"href":2259,"dataGaName":2203,"dataGaLocation":2117},"/solutions/gitops/",{"text":1806,"config":2261},{"href":1809,"dataGaName":1810,"dataGaLocation":2117},{"text":2263,"config":2264},"Small business",{"href":1815,"dataGaName":1816,"dataGaLocation":2117},{"text":2266,"config":2267},"Public sector",{"href":1821,"dataGaName":1667,"dataGaLocation":2117},{"text":2269,"config":2270},"Education",{"href":2271,"dataGaName":2272,"dataGaLocation":2117},"/solutions/education/","education",{"text":2274,"config":2275},"Financial services",{"href":2276,"dataGaName":2277,"dataGaLocation":2117},"/solutions/finance/","financial services",{"title":1828,"links":2279},[2280,2282,2284,2286,2289,2291,2294,2296,2298,2300,2302,2304,2306,2308],{"text":1841,"config":2281},{"href":1843,"dataGaName":1844,"dataGaLocation":2117},{"text":1846,"config":2283},{"href":1848,"dataGaName":1849,"dataGaLocation":2117},{"text":1851,"config":2285},{"href":1853,"dataGaName":1854,"dataGaLocation":2117},{"text":1856,"config":2287},{"href":1858,"dataGaName":2288,"dataGaLocation":2117},"docs",{"text":1879,"config":2290},{"href":1881,"dataGaName":1882,"dataGaLocation":2117},{"text":2292,"config":2293},"What's new",{"href":1939,"dataGaName":1940,"dataGaLocation":2117},{"text":1874,"config":2295},{"href":1876,"dataGaName":1877,"dataGaLocation":2117},{"text":1893,"config":2297},{"href":1895,"dataGaName":1896,"dataGaLocation":2117},{"text":1901,"config":2299},{"href":1903,"dataGaName":1904,"dataGaLocation":2117},{"text":1906,"config":2301},{"href":1908,"dataGaName":1909,"dataGaLocation":2117},{"text":1911,"config":2303},{"href":1913,"dataGaName":1914,"dataGaLocation":2117},{"text":1916,"config":2305},{"href":1918,"dataGaName":1919,"dataGaLocation":2117},{"text":1921,"config":2307},{"href":1923,"dataGaName":1924,"dataGaLocation":2117},{"text":1926,"config":2309},{"href":1928,"dataGaName":1929,"dataGaLocation":2117},{"title":1942,"links":2311},[2312,2314,2316,2318,2320,2322,2326,2331,2333,2335,2337],{"text":1950,"config":2313},{"href":1952,"dataGaName":1944,"dataGaLocation":2117},{"text":1955,"config":2315},{"href":1957,"dataGaName":1958,"dataGaLocation":2117},{"text":1963,"config":2317},{"href":1965,"dataGaName":1966,"dataGaLocation":2117},{"text":1968,"config":2319},{"href":1970,"dataGaName":1971,"dataGaLocation":2117},{"text":1973,"config":2321},{"href":1975,"dataGaName":1976,"dataGaLocation":2117},{"text":2323,"config":2324},"Sustainability",{"href":2325,"dataGaName":2323,"dataGaLocation":2117},"/sustainability/",{"text":2327,"config":2328},"Diversity, inclusion and belonging (DIB)",{"href":2329,"dataGaName":2330,"dataGaLocation":2117},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1978,"config":2332},{"href":1980,"dataGaName":1981,"dataGaLocation":2117},{"text":1988,"config":2334},{"href":1990,"dataGaName":1991,"dataGaLocation":2117},{"text":1993,"config":2336},{"href":1995,"dataGaName":1996,"dataGaLocation":2117},{"text":2338,"config":2339},"Modern Slavery Transparency Statement",{"href":2340,"dataGaName":2341,"dataGaLocation":2117},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":2343},[2344,2347,2350],{"text":2345,"config":2346},"Terms",{"href":2169,"dataGaName":2170,"dataGaLocation":2117},{"text":2348,"config":2349},"Cookies",{"dataGaName":2179,"dataGaLocation":2117,"id":2180,"isOneTrustButton":352},{"text":2351,"config":2352},"Privacy",{"href":2174,"dataGaName":2175,"dataGaLocation":2117},[2354],{"id":2355,"title":7,"body":1654,"config":2356,"content":2358,"description":1654,"extension":2362,"meta":2363,"navigation":352,"path":2364,"seo":2365,"stem":2366,"__hash__":2367},"blogAuthors/en-us/blog/authors/fernando-diaz.yml",{"template":2357},"BlogAuthor",{"name":7,"config":2359},{"headshot":2360,"ctfId":2361},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659556/Blog/Author%20Headshots/fern_diaz.png","fjdiaz","yml",{},"/en-us/blog/authors/fernando-diaz",{},"en-us/blog/authors/fernando-diaz","lxRJIOydP4_yzYZvsPcuQevP9AYAKREF7i8QmmdnOWc",[2369,2377,2385],{"title":2370,"description":2371,"heroImage":2372,"category":1650,"date":2373,"authors":2374,"slug":2376,"externalUrl":1654},"How GitLab tracks vulnerabilities through refactors and reformatting","Learn how GitLab's improved Scope+Offset fingerprinting keeps vulnerability tracking stable across comments, blank lines, and reformatting.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1759320418/xjmqcozxzt4frx0hori3.png","2026-08-12",[2375],"Julian Thome","improved-scope-offset-fingerprinting",{"title":2378,"description":2379,"heroImage":2372,"category":1650,"date":2380,"authors":2381,"slug":2384,"externalUrl":1654},"GitLab Secrets Manager adds ESO, Terraform, API support","Simplify credential management across your stack. GitLab Secrets Manager provides secure retrieval in Kubernetes, Terraform, and external workflows.","2026-08-06",[2382,2383],"Erick Bajao","Joe Randazzo","gitlab-secrets-manager-add-eso-terraform-api-support",{"title":2386,"description":2387,"heroImage":2388,"category":1650,"date":2389,"authors":2390,"slug":2392,"externalUrl":1654},"Secure every commit to production with Claude and GitLab","Claude Security catches vulnerabilities inside a coding session. GitLab picks up from there, scanning, enforcing policy, and producing audit evidence for the software lifecycle. ","https://res.cloudinary.com/about-gitlab-com/image/upload/v1756122536/akivvcnafog9c4dhhzkp.png","2026-08-03",[2391],"Alisa Ho","claude-security-and-gitlab",{"promotions":2394},[2395,2409,2421,2432],{"id":2396,"categories":2397,"header":2399,"text":2400,"button":2401,"image":2406},"ai-modernization",[2398],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":2402,"config":2403},"Get your AI maturity score",{"href":2404,"dataGaName":2405,"dataGaLocation":1882},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":2407},{"src":2408},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":2410,"categories":2411,"header":2413,"text":2400,"button":2414,"image":2418},"devops-modernization",[2412,2218],"product","Are you just managing tools or shipping innovation?",{"text":2415,"config":2416},"Get your DevOps maturity score",{"href":2417,"dataGaName":2405,"dataGaLocation":1882},"/assessments/devops-modernization-assessment/",{"config":2419},{"src":2420},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":2422,"categories":2423,"header":2424,"text":2400,"button":2425,"image":2429},"security-modernization",[1650],"Are you trading speed for security?",{"text":2426,"config":2427},"Get your security maturity score",{"href":2428,"dataGaName":2405,"dataGaLocation":1882},"/assessments/security-modernization-assessment/",{"config":2430},{"src":2431},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":2433,"paths":2434,"header":2437,"text":2438,"button":2439,"image":2444},"github-azure-migration",[2435,2436],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":2440,"config":2441},"See how GitLab compares to GitHub",{"href":2442,"dataGaName":2443,"dataGaLocation":1882},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":2445},{"src":2420},{"header":2447,"blurb":2448,"button":2449,"secondaryButton":2454},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":2450,"config":2451},"Get your free trial",{"href":2452,"dataGaName":1682,"dataGaLocation":2453},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":2155,"config":2455},{"href":2007,"dataGaName":1687,"dataGaLocation":2453},1786803776065]