[{"data":1,"prerenderedAt":1517},["ShallowReactive",2],{"/blog/american-fuzzy-lop-on-gitlab":3,"navigation-en-us":733,"banner-en-us":1161,"footer-en-us":1171,"blog-post-authors-en-us-Luka Trbojevic":1415,"blog-related-posts-en-us-american-fuzzy-lop-on-gitlab":1429,"blog-promotions-en-us":1454,"next-steps-en-us":1507},{"id":4,"title":5,"authors":6,"body":8,"category":712,"date":713,"description":714,"extension":715,"externalUrl":716,"faq":716,"featured":717,"heroImage":718,"meta":719,"navigation":720,"path":721,"seo":722,"slug":727,"stem":728,"tags":729,"template":731,"updatedDate":716,"__hash__":732},"blogPosts/en-us/blog/american-fuzzy-lop-on-gitlab.md","American Fuzzy Lop on GitLab: Automating instrumented fuzzing using pipelines",[7],"Luka Trbojevic",{"type":9,"value":10,"toc":699},"minimark",[11,33,36,44,47,50,71,83,88,97,100,106,117,122,129,134,137,147,150,154,163,167,178,275,282,287,296,300,306,317,334,352,358,365,371,377,383,393,399,405,411,414,421,431,435,441,469,489,495,521,524,530,534,543,553,566,570,573,587,590,593,644,659,663,666,669,673,681,695],[12,13,14,15,21,22,26,27,32],"p",{},"This year at ",[16,17,20],"a",{"href":18,"rel":19},"https://2019.bsideskc.org/",[],"BSides Kansas City",", many of my conversations were about fuzzing and integrating security into the ",[16,23,25],{"href":24},"/topics/devops/","DevOps process",". Fuzzing has been around for a very long time. Back in 2006, I wrote my first (very simple) fuzzer to mutate .zip files and pass them to anti-virus programs; even at that time, the case for fuzzing had been made many years prior. Today, ",[16,28,31],{"href":29,"rel":30},"http://lcamtuf.coredump.cx/afl/",[],"American Fuzzy Lop (AFL)",", written by Michal Zalewski, stands as one of the best fuzzers available, and is one of my favorite tools.",[12,34,35],{},"Anecdotally, I've been seeing good arguments made for the adoption of fuzzing as part of the software security lifecycle more frequently than ever before. At BSides Kansas City, I listened to an interesting conversation at the speakers' dinner where the case was made that fuzzing is reduced to a niche, nice-to-have, wishlist item incorporated into workflows by exploit developers and only the largest of enterprises. I largely agree, but I like to think of why that's the case.",[12,37,38,39,43],{},"My general sense is that instrumented fuzzing, as a function of the software lifecycle, is still fraught with too much friction for widespread adoption. For something to take hold at scale, be useful to a large number of people, and have its benefits passed down to consumers, it needs to be quick and simple. Right now, fuzzing as something an ",[40,41,42],"strong",{},"organization"," does as part of its standard practice is not quick or simple. So, even if you have someone well-versed in fuzzing and exploit development, chances are fuzzing won’t survive as an organizational function.",[12,45,46],{},"In the hope that we can move the conversation forward, I wanted to give back something actionable – yet simple – to help folks incorporate fuzzing into their workflows. I’ve always found practical, hands-on examples to be the most helpful, so I put together a baseline sample showing how fuzzing with AFL can be automated as part of a pipeline.",[12,48,49],{},"Two important notes:",[51,52,53,57],"ul",{},[54,55,56],"li",{},"This blog isn’t an introduction to instrumented fuzzing and assumes you have a good understanding of it already, including what a test harness is and how to write one.",[54,58,59,64,65,70],{},[16,60,63],{"href":61,"rel":62},"https://gitlab.com/gitlab-org/gitlab-ee/issues/10852",[],"Fuzzing as a feature of GitLab is in the works",", but it's not here just yet. Also, the ",[16,66,69],{"href":67,"rel":68},"https://gitlab.com/gitlab-org/gitlab-ee/issues/8453",[],"first iteration"," doesn't seem to include instrumented fuzzing.",[12,72,73,74,79,80],{},"You can find all code, including the Dockerfile, and detailed setup/modification instructions in the ",[16,75,78],{"href":76,"rel":77},"https://gitlab.com/ltrbojevic/afl-gitlab",[],"AFL-GitLab repository",". ",[40,81,82],{},"Please familiarize yourself with the background in the repository first!",[84,85,87],"h2",{"id":86},"docker-image-setup","Docker image setup",[12,89,90,91,96],{},"I prefer to work with Docker images, so I’ve used the ",[16,92,95],{"href":93,"rel":94},"https://docs.gitlab.com/runner/executors/docker/",[],"Docker executor",". AFL, your code, the test harness (if applicable), and the controlling Python script (more on that below) are in your Docker image.",[12,98,99],{},"For this example, we’re using Ubuntu 16.04. You can use any operating system you prefer. I run Ubuntu 16.04 for my fuzzing jobs, which is why I’ve used it here:",[12,101,102],{},[103,104,105],"code",{},"FROM ubuntu:16.04",[12,107,108,109,112,113,116],{},"I copy a local ",[103,110,111],{},"fuzzing/"," folder with all of my files to ",[103,114,115],{},"/usr/src/"," in the Docker image. This can be changed to whatever works for you:",[12,118,119],{},[103,120,121],{},"COPY fuzzing/ /usr/src/",[12,123,124,125,128],{},"I set the user as ",[103,126,127],{},"root"," because I just want it to work. Customize this per your operating system, threat model, and risk tolerance:",[12,130,131],{},[103,132,133],{},"USER root",[12,135,136],{},"Then just install whatever packages you need:",[138,139,145],"pre",{"className":140,"code":142,"language":143,"meta":144},[141],"language-text","RUN apt-get update && apt-get install -y \\\n  sudo \\\n  software-properties-common \\\n  build-essential\n\n","text","",[103,146,142],{"__ignoreMap":144},[12,148,149],{},"Note that this image is optimized for compatibility and efficiency only.",[84,151,153],{"id":152},"our-sample-target-program","Our sample target program",[12,155,156,157,162],{},"For this example, we’re going to be fuzzing ",[16,158,161],{"href":159,"rel":160},"https://gitlab.com/ltrbojevic/afl-gitlab/blob/master/fuzzing/afl-gitlab/vulnerable.c",[],"vulnerable.c",". It features a total absence of security and C best practice and is designed to intentionally generate at least one unique crash within the first few seconds of fuzzing. It’s a quick and simple way to verify everything else is working.",[84,164,166],{"id":165},"setting-up-afl","Setting up AFL",[12,168,169,170,173,174,177],{},"Instrumenting your program is done within the ",[103,171,172],{},".gitlab-ci.yml"," file as part of the ",[103,175,176],{},"before_script"," parameter:",[138,179,183],{"className":180,"code":181,"language":182,"meta":144,"style":144},"language-yaml shiki shiki-themes github-light","run-afl:\nstage: run-afl\nbefore_script:\n- cd /usr/src/afl-2.52b\n- make\n- make install\n- cd /usr/src/afl-gitlab\n- CC=/usr/src/afl-2.52b/afl-gcc AFL_HARDEN=1 make\n- echo core >/proc/sys/kernel/core_pattern\n- echo $CI_PROJECT_DIR\n","yaml",[103,184,185,198,211,218,227,235,243,251,259,267],{"__ignoreMap":144},[186,187,190,194],"span",{"class":188,"line":189},"line",1,[186,191,193],{"class":192},"shJU0","run-afl",[186,195,197],{"class":196},"sgsFI",":\n",[186,199,201,204,207],{"class":188,"line":200},2,[186,202,203],{"class":192},"stage",[186,205,206],{"class":196},": ",[186,208,210],{"class":209},"sYBdl","run-afl\n",[186,212,214,216],{"class":188,"line":213},3,[186,215,176],{"class":192},[186,217,197],{"class":196},[186,219,221,224],{"class":188,"line":220},4,[186,222,223],{"class":196},"- ",[186,225,226],{"class":209},"cd /usr/src/afl-2.52b\n",[186,228,230,232],{"class":188,"line":229},5,[186,231,223],{"class":196},[186,233,234],{"class":209},"make\n",[186,236,238,240],{"class":188,"line":237},6,[186,239,223],{"class":196},[186,241,242],{"class":209},"make install\n",[186,244,246,248],{"class":188,"line":245},7,[186,247,223],{"class":196},[186,249,250],{"class":209},"cd /usr/src/afl-gitlab\n",[186,252,254,256],{"class":188,"line":253},8,[186,255,223],{"class":196},[186,257,258],{"class":209},"CC=/usr/src/afl-2.52b/afl-gcc AFL_HARDEN=1 make\n",[186,260,262,264],{"class":188,"line":261},9,[186,263,223],{"class":196},[186,265,266],{"class":209},"echo core >/proc/sys/kernel/core_pattern\n",[186,268,270,272],{"class":188,"line":269},10,[186,271,223],{"class":196},[186,273,274],{"class":209},"echo $CI_PROJECT_DIR\n",[12,276,277,278,281],{},"I include ",[103,279,280],{},"echo $CI_PROJECT_DIR"," as a troubleshooting measure (more below).",[283,284,286],"h3",{"id":285},"a-note-on-performance","A note on performance",[12,288,289,290,295],{},"This specific example uses GitLab.com ",[16,291,294],{"href":292,"rel":293},"https://docs.gitlab.com/ci/runners/#shared-runners",[],"Shared Runners"," for demonstration’s sake. The performance limitations of Shared Runners in the context of fuzzing make it infeasible to run instrumented fuzzing jobs in a performant way. Instead, you could consider using a self-hosted runner.",[84,297,299],{"id":298},"initializing-afl","Initializing AFL",[12,301,302,303,305],{},"The problem with initiating AFL in ",[103,304,172],{}," is AFL will continue to run until interrupted, so it must be stopped programmatically and that stop must be configurable to only run after a defined amount of time.",[12,307,308,309,312,313,316],{},"To solve this problem, we can have the pipeline run a script to manage the execution and handling of AFL. I prefer to use Python, but you can use any language you like. In Python, we can use the ",[103,310,311],{},"time.sleep()"," function. The Python script will initiate AFL and ",[103,314,315],{},"sleep()"," will be used to run AFL for whatever length of time you set. Afterwards, AFL will be stopped.",[12,318,319,320,323,324,327,328,330,331,177],{},"In ",[103,321,322],{},".gitlab.ci-yml",", we run this script ",[40,325,326],{},"after"," AFL is installed and our program is instrumented. We do this by doing the instrumentation using the ",[103,329,176],{}," parameter and running the Python script using the ",[103,332,333],{},"script",[138,335,337],{"className":180,"code":336,"language":182,"meta":144,"style":144},"script:\n- python3 /usr/src/fuzzing/afl-gitlab/afl-gitlab.py\n",[103,338,339,345],{"__ignoreMap":144},[186,340,341,343],{"class":188,"line":189},[186,342,333],{"class":192},[186,344,197],{"class":196},[186,346,347,349],{"class":188,"line":200},[186,348,223],{"class":196},[186,350,351],{"class":209},"python3 /usr/src/fuzzing/afl-gitlab/afl-gitlab.py\n",[12,353,354,357],{},[103,355,356],{},"afl-gitlab.py"," is where the magic happens and it serves as the control center where the handling and synchronization of the different events that need to happen are managed and customized.",[12,359,360,361,364],{},"To start AFL, we use ",[103,362,363],{},"subprocess.Popen()"," to run the command:",[138,366,369],{"className":367,"code":368,"language":143,"meta":144},[141],"subprocess.Popen([\"afl-fuzz\", \"-i\", \"inputs\", \"-o\", \"outputs\",\n\"./vulnerable\"])\n",[103,370,368],{"__ignoreMap":144},[12,372,373,374,376],{},"To control exactly how long AFL will run, we use ",[103,375,311],{}," -- in this example, it’s 30 seconds:",[138,378,381],{"className":379,"code":380,"language":143,"meta":144},[141],"time.sleep(30)\n",[103,382,380],{"__ignoreMap":144},[12,384,385,386,389,390,392],{},"After that, we need to stop AFL in a way that doesn’t cause the pipeline to fail. If you exit ",[103,387,388],{},"afl-python.py"," itself like you might do locally, the job will fail. To get around this, we use ",[103,391,363],{}," to stop AFL:",[138,394,397],{"className":395,"code":396,"language":143,"meta":144},[141],"subprocess.Popen([\"pkill\", \"-f\", \"afl\"])\n",[103,398,396],{"__ignoreMap":144},[12,400,401,402,404],{},"Lastly, we exit the ",[103,403,388],{}," in a way that doesn’t cause the job to fail:",[138,406,409],{"className":407,"code":408,"language":143,"meta":144},[141],"os._exit(0)\n",[103,410,408],{"__ignoreMap":144},[12,412,413],{},"It’s important your script doesn’t cause the job to fail because everything else that needs to happen, won’t:",[12,415,416],{},[417,418],"img",{"alt":419,"src":420},"job fail message","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398586/blog/Content%20Images/jobfail.png",[12,422,423,424,427,428,430],{},"Just in case the job fails and you don’t want your entire pipeline to fail, I set ",[103,425,426],{},"allow_failure: true"," in the ",[103,429,172],{}," file.",[84,432,434],{"id":433},"collecting-afl-output-as-a-pipeline-artifact","Collecting AFL output as a pipeline artifact",[12,436,437,438,430],{},"Running AFL has no value if the output can’t be collected in a workflow-friendly way, so we’ll use pipeline artifacts. The entire artifact collection process can be defined in the ",[103,439,440],{},".gitlab-ci-yml",[12,442,443,444,447,448,450,451,454,455,458,459,462,463,468],{},"First, using the ",[103,445,446],{},"after_scripts"," parameter, which will run after ",[103,449,356],{}," exits, we copy the ",[103,452,453],{},"outputs"," folder to a location in ",[103,456,457],{},"$CI_PROJECT_DIR"," (thus the ",[103,460,461],{},"echo $CI_PROJECT_DIR done earlier","). This is important because you may run into ",[16,464,467],{"href":465,"rel":466},"https://stackoverflow.com/questions/47490688/gitlab-ci-artifacts-not-found",[],"artifact not found issues",":",[138,470,472],{"className":180,"code":471,"language":182,"meta":144,"style":144},"after_script:\n  - cp -a /usr/src/afl-gitlab/outputs $CI_PROJECT_DIR\n",[103,473,474,481],{"__ignoreMap":144},[186,475,476,479],{"class":188,"line":189},[186,477,478],{"class":192},"after_script",[186,480,197],{"class":196},[186,482,483,486],{"class":188,"line":200},[186,484,485],{"class":196},"  - ",[186,487,488],{"class":209},"cp -a /usr/src/afl-gitlab/outputs $CI_PROJECT_DIR\n",[12,490,491,492,494],{},"Then we simply collect the ",[103,493,453],{}," folder as an artifact:",[138,496,498],{"className":180,"code":497,"language":182,"meta":144,"style":144},"artifacts:\npaths:\n- $CI_PROJECT_DIR/outputs\n",[103,499,500,507,514],{"__ignoreMap":144},[186,501,502,505],{"class":188,"line":189},[186,503,504],{"class":192},"artifacts",[186,506,197],{"class":196},[186,508,509,512],{"class":188,"line":200},[186,510,511],{"class":192},"paths",[186,513,197],{"class":196},[186,515,516,518],{"class":188,"line":213},[186,517,223],{"class":196},[186,519,520],{"class":209},"$CI_PROJECT_DIR/outputs\n",[12,522,523],{},"Your output will then be viewable like any other pipeline artifact:",[12,525,526],{},[417,527],{"alt":528,"src":529},"output artifact","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398794/blog/Content%20Images/output-artifact.png",[84,531,533],{"id":532},"creating-issues-for-every-unique-crash","Creating issues for every unique crash",[12,535,536,537,542],{},"To make this a truly automated workflow, you could use the ",[16,538,541],{"href":539,"rel":540},"https://docs.gitlab.com/api/",[],"GitLab API"," to create an issue for every unique crash. At this time, I haven’t had the time to invest heavily in this, but I’ll have to circle back when I do.",[12,544,545,546,548,549,552],{},"Having played with the artifacts API for only a few brief moments, the path of least resistance seems to be adding the logic to ",[103,547,356],{}," ",[40,550,551],{},"prior"," to the artifact collection.",[12,554,555,556,559,560,565],{},"For a specific example on how to use ",[103,557,558],{},"python-gitlab"," to create issues, check out ",[16,561,564],{"href":562,"rel":563},"https://gitlab.com/ltrbojevic/hipaa-audit-protocol-issue-generator",[],"an issue generator script I wrote for the HIPAA Audit Protocol",".",[84,567,569],{"id":568},"distributed-fuzzing-and-multi-system-parallelization","Distributed fuzzing and multi-system parallelization",[12,571,572],{},"The basic principles of multi-system parallelization apply whether you're running distributed fuzzing jobs manually or automating them on GitLab. While I haven't had a chance to port my personal workflows to GitLab yet, a quick glance tells me it’s likely possible.",[12,574,575,576,578,579,582,583,586],{},"Using ",[103,577,356],{},", you could run a separate script to handle the deployment, configuration, and de-provisioning of -S mode instances. My initial preference would be to run a second Python script – let's call it ",[103,580,581],{},"afl-gitlab-s.py","  that would use ",[103,584,585],{},"python-terraform"," to provision and deprovision the infrastructure. Fabric can be used to configure the instances, start AFL, and so on.",[12,588,589],{},"There would have to be some thought put into the timing and orchestration between the two scripts. It's also important to note: your synchronization scripts have to be timed so as not to de-provision -S mode instances before a synchronization event occurs; especially if you opt for staged synchronization.",[12,591,592],{},"Lists make the most sense to me, so in other words:",[594,595,596,601,608,616,624,629,634,639],"ol",{},[54,597,598,599],{},"A Runner job runs ",[103,600,356],{},[54,602,603,605,606],{},[103,604,356],{}," starts a second script, ",[103,607,581],{},[54,609,610,612,613,615],{},[103,611,581],{}," does a short sleep to allow ",[103,614,356],{}," to run the -M mode instance",[54,617,618,620,621,623],{},[103,619,581],{}," uses ",[103,622,585],{}," to provision -S mode instances",[54,625,626,628],{},[103,627,581],{}," then uses Fabric to configure the -S mode instances (e.g., set up synchronization scripts) and start AFL",[54,630,631,633],{},[103,632,581],{}," sleeps for 1:55 hrs",[54,635,636,638],{},[103,637,581],{}," de-provisions the -S mode instances",[54,640,641,643],{},[103,642,356],{}," ends the -M mode instance fuzzing",[12,645,646,647,650,651,654,655,658],{},"Note that I'm assuming you've modified your synchronization scripts to transfer ",[103,648,649],{},"crashes"," and ",[103,652,653],{},"hangs"," to the -M mode instance. Please remember that the out-of-the-box synchronization scripts transfer ",[103,656,657],{},"queue",", so unless you've modified your script to transfer other folder contents as well, you may lose findings when the -S mode instances are de-provisioned.",[84,660,662],{"id":661},"automating-advanced-output-triage-and-analysis","Automating advanced output triage and analysis",[12,664,665],{},"Many triage and initial analysis workflows can be, and are, automated. My personal workflow includes a combination AFL's crash explorer, pwndbg, and radare2. I’ve condensed most of my initial triage to a single Python tool. The tool could be run as a Runner job, either on the Runner instance itself or, as above with the -S mode instances, offloaded to another box with the results returned to the Runner instance. Given that, and regardless of the language of your toolset, automating output triage and initial analysis seems to be doable with some tinkering.",[12,667,668],{},"Much like automatically creating an issue for every unique crash found, I’ve not yet had the time to focus on this and give it a go, but I’ll circle back and add it when I can.",[84,670,672],{"id":671},"some-final-thoughts","Some final thoughts",[12,674,675,676,680],{},"There's a whole bunch we could automate and make more accessible in the fuzzing space. In the interest of reaching and benefiting the largest number of people, I’d love to see GitLab have mature fuzzing features that are helpful to developers and security folk alike. To help move that forward, I think community involvement in key. If you have the inclination please contribute to our ",[16,677,679],{"href":61,"rel":678},[],"direction",". And if, instead, you want to take this example and expand it outside of the GitLab ecosystem, please do and tell us how it went!",[12,682,683,684,689,690],{},"Photo by ",[16,685,688],{"href":686,"rel":687},"https://www.pexels.com/@tomfisk?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels",[],"Tom Fisk"," on ",[16,691,694],{"href":692,"rel":693},"https://www.pexels.com",[],"Pexels",[696,697,698],"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);}",{"title":144,"searchDepth":200,"depth":200,"links":700},[701,702,703,706,707,708,709,710,711],{"id":86,"depth":200,"text":87},{"id":152,"depth":200,"text":153},{"id":165,"depth":200,"text":166,"children":704},[705],{"id":285,"depth":213,"text":286},{"id":298,"depth":200,"text":299},{"id":433,"depth":200,"text":434},{"id":532,"depth":200,"text":533},{"id":568,"depth":200,"text":569},{"id":661,"depth":200,"text":662},{"id":671,"depth":200,"text":672},"security","2019-08-14","An example of how to automate instrumented fuzzing with American Fuzzy Lop using pipelines.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749680723/Blog/Hero%20Images/aerial-shot-birds-eye-view.jpg",{},true,"/en-us/blog/american-fuzzy-lop-on-gitlab",{"title":723,"description":714,"ogTitle":723,"ogDescription":714,"noIndex":717,"ogImage":718,"ogUrl":724,"ogSiteName":725,"ogType":726,"canonicalUrls":724},"GitLab automates instrumented fuzzing via American Fuzzy Lop","https://about.gitlab.com/blog/american-fuzzy-lop-on-gitlab","https://about.gitlab.com","article","american-fuzzy-lop-on-gitlab","en-us/blog/american-fuzzy-lop-on-gitlab",[730,712],"inside GitLab","BlogPost","n63kKvSeHKV-OURlOBiLEM7Xfd6lPifbs-WZ5z3Keek",{"logo":734,"freeTrial":739,"sales":744,"login":749,"items":754,"search":1081,"minimal":1112,"duo":1131,"switchNav":1140,"pricingDeployment":1151},{"config":735},{"href":736,"dataGaName":737,"dataGaLocation":738},"/","gitlab logo","header",{"text":740,"config":741},"Get free trial",{"href":742,"dataGaName":743,"dataGaLocation":738},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":745,"config":746},"Request a demo",{"href":747,"dataGaName":748,"dataGaLocation":738},"/sales/?contact-topic=request-demo","sales",{"text":750,"config":751},"Sign in",{"href":752,"dataGaName":753,"dataGaLocation":738},"https://gitlab.com/users/sign_in/","sign in",[755,784,884,889,1003,1059],{"text":756,"config":757,"menu":759},"Platform",{"dataNavLevelOne":758},"platform",{"type":760,"columns":761},"cards",[762,768,776],{"title":756,"description":763,"link":764},"The intelligent orchestration platform for DevSecOps",{"text":765,"config":766},"Explore our Platform",{"href":767,"dataGaName":758,"dataGaLocation":738},"/platform/",{"title":769,"description":770,"link":771},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":772,"config":773},"Meet GitLab Duo",{"href":774,"dataGaName":775,"dataGaLocation":738},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":777,"description":778,"link":779},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":780,"config":781},"Learn more",{"href":782,"dataGaName":783,"dataGaLocation":738},"/why-gitlab/","why gitlab",{"text":785,"left":720,"config":786,"menu":788},"Product",{"dataNavLevelOne":787},"solutions",{"type":789,"link":790,"columns":794,"feature":863},"lists",{"text":791,"config":792},"View all Solutions",{"href":793,"dataGaName":787,"dataGaLocation":738},"/solutions/",[795,819,842],{"title":796,"description":797,"link":798,"items":803},"Automation","CI/CD and automation to accelerate deployment",{"config":799},{"icon":800,"href":801,"dataGaName":802,"dataGaLocation":738},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[804,808,811,815],{"text":805,"config":806},"CI/CD",{"href":807,"dataGaLocation":738,"dataGaName":805},"/solutions/continuous-integration/",{"text":769,"config":809},{"href":774,"dataGaLocation":738,"dataGaName":810},"gitlab duo agent platform - product menu",{"text":812,"config":813},"Source Code Management",{"href":814,"dataGaLocation":738,"dataGaName":812},"/solutions/source-code-management/",{"text":816,"config":817},"Automated Software Delivery",{"href":801,"dataGaLocation":738,"dataGaName":818},"Automated software delivery",{"title":820,"description":821,"link":822,"items":827},"Security","Deliver code faster without compromising security",{"config":823},{"href":824,"dataGaName":825,"dataGaLocation":738,"icon":826},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[828,832,837],{"text":829,"config":830},"Application Security Testing",{"href":824,"dataGaName":831,"dataGaLocation":738},"Application security testing",{"text":833,"config":834},"Software Supply Chain Security",{"href":835,"dataGaLocation":738,"dataGaName":836},"/solutions/supply-chain/","Software supply chain security",{"text":838,"config":839},"Software Compliance",{"href":840,"dataGaName":841,"dataGaLocation":738},"/solutions/software-compliance/","software compliance",{"title":843,"link":844,"items":849},"Measurement",{"config":845},{"icon":846,"href":847,"dataGaName":848,"dataGaLocation":738},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[850,854,858],{"text":851,"config":852},"Visibility & Measurement",{"href":847,"dataGaLocation":738,"dataGaName":853},"Visibility and Measurement",{"text":855,"config":856},"Value Stream Management",{"href":857,"dataGaLocation":738,"dataGaName":855},"/solutions/value-stream-management/",{"text":859,"config":860},"Analytics & Insights",{"href":861,"dataGaLocation":738,"dataGaName":862},"/solutions/analytics-and-insights/","Analytics and insights",{"title":864,"type":789,"items":865},"GitLab for",[866,872,878],{"text":867,"config":868},"Enterprise",{"icon":869,"href":870,"dataGaLocation":738,"dataGaName":871},"Building","/enterprise/","enterprise",{"text":873,"config":874},"Small Business",{"icon":875,"href":876,"dataGaLocation":738,"dataGaName":877},"Work","/small-business/","small business",{"text":879,"config":880},"Public Sector",{"icon":881,"href":882,"dataGaLocation":738,"dataGaName":883},"Organization","/solutions/public-sector/","public sector",{"text":885,"config":886},"Pricing",{"href":887,"dataGaName":888,"dataGaLocation":738,"dataNavLevelOne":888},"/pricing/","pricing",{"text":890,"config":891,"menu":893},"Resources",{"dataNavLevelOne":892},"resources",{"type":789,"link":894,"columns":898,"feature":992},{"text":895,"config":896},"View all resources",{"href":897,"dataGaName":892,"dataGaLocation":738},"/resources/",[899,932,959],{"title":900,"items":901},"Getting started",[902,907,912,917,922,927],{"text":903,"config":904},"Install",{"href":905,"dataGaName":906,"dataGaLocation":738},"/install/","install",{"text":908,"config":909},"Quick start guides",{"href":910,"dataGaName":911,"dataGaLocation":738},"/get-started/","quick setup checklists",{"text":913,"config":914},"Learn",{"href":915,"dataGaLocation":738,"dataGaName":916},"https://university.gitlab.com/","learn",{"text":918,"config":919},"Product documentation",{"href":920,"dataGaName":921,"dataGaLocation":738},"https://docs.gitlab.com/","product documentation",{"text":923,"config":924},"Best practice videos",{"href":925,"dataGaName":926,"dataGaLocation":738},"/getting-started-videos/","best practice videos",{"text":928,"config":929},"Integrations",{"href":930,"dataGaName":931,"dataGaLocation":738},"/integrations/","integrations",{"title":933,"items":934},"Discover",[935,940,945,950,954],{"text":936,"config":937},"Customer success stories",{"href":938,"dataGaName":939,"dataGaLocation":738},"/customers/","customer success stories",{"text":941,"config":942},"Blog",{"href":943,"dataGaName":944,"dataGaLocation":738},"/blog/","blog",{"text":946,"config":947},"Demo Hub",{"href":948,"dataGaName":949,"dataGaLocation":738},"/demo-hub/","demo hub",{"text":951,"config":952},"The Source",{"href":953,"dataGaName":944,"dataGaLocation":738},"/the-source/",{"text":955,"config":956},"Remote",{"href":957,"dataGaName":958,"dataGaLocation":738},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":960,"items":961},"Connect",[962,967,972,977,982,987],{"text":963,"config":964},"GitLab Services",{"href":965,"dataGaName":966,"dataGaLocation":738},"/services/","services",{"text":968,"config":969},"Contribute",{"href":970,"dataGaName":971,"dataGaLocation":738},"https://contributors.gitlab.com","contribute",{"text":973,"config":974},"Community",{"href":975,"dataGaName":976,"dataGaLocation":738},"/community/","community",{"text":978,"config":979},"Forum",{"href":980,"dataGaName":981,"dataGaLocation":738},"https://forum.gitlab.com/","forum",{"text":983,"config":984},"Events",{"href":985,"dataGaName":986,"dataGaLocation":738},"/events/","events",{"text":988,"config":989},"Partners",{"href":990,"dataGaName":991,"dataGaLocation":738},"/partners/","partners",{"config":993,"title":996,"text":997,"link":998},{"background":994,"textColor":995},"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":999,"config":1000},"Read the latest",{"href":1001,"dataGaName":1002,"dataGaLocation":738},"/whats-new/","whats new",{"text":1004,"config":1005,"menu":1007},"Company",{"dataNavLevelOne":1006},"company",{"type":789,"columns":1008},[1009],{"items":1010},[1011,1016,1022,1024,1029,1034,1039,1044,1049,1054],{"text":1012,"config":1013},"About",{"href":1014,"dataGaName":1015,"dataGaLocation":738},"/company/","about",{"text":1017,"config":1018,"footerGa":1021},"Jobs",{"href":1019,"dataGaName":1020,"dataGaLocation":738},"/jobs/","jobs",{"dataGaName":1020},{"text":983,"config":1023},{"href":985,"dataGaName":986,"dataGaLocation":738},{"text":1025,"config":1026},"Leadership",{"href":1027,"dataGaName":1028,"dataGaLocation":738},"/company/team/e-group/","leadership",{"text":1030,"config":1031},"Handbook",{"href":1032,"dataGaName":1033,"dataGaLocation":738},"https://handbook.gitlab.com/","handbook",{"text":1035,"config":1036},"Investor relations",{"href":1037,"dataGaName":1038,"dataGaLocation":738},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1040,"config":1041},"Trust Center",{"href":1042,"dataGaName":1043,"dataGaLocation":738},"/security/","trust center",{"text":1045,"config":1046},"AI Transparency Center",{"href":1047,"dataGaName":1048,"dataGaLocation":738},"/ai-transparency-center/","ai transparency center",{"text":1050,"config":1051},"Newsletter",{"href":1052,"dataGaName":1053,"dataGaLocation":738},"/company/contact/#contact-forms","newsletter",{"text":1055,"config":1056},"Press",{"href":1057,"dataGaName":1058,"dataGaLocation":738},"/press/","press",{"text":1060,"config":1061,"menu":1062},"Contact us",{"dataNavLevelOne":1006},{"type":789,"columns":1063},[1064],{"items":1065},[1066,1071,1076],{"text":1067,"config":1068},"Talk to sales",{"href":1069,"dataGaName":1070,"dataGaLocation":738},"/sales/","talk to sales",{"text":1072,"config":1073},"Support portal",{"href":1074,"dataGaName":1075,"dataGaLocation":738},"https://support.gitlab.com/hc/en-us","support portal",{"text":1077,"config":1078},"Customer portal",{"href":1079,"dataGaName":1080,"dataGaLocation":738},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1082,"login":1083,"suggestions":1090},"Close",{"text":1084,"link":1085},"To search repositories and projects, login to",{"text":1086,"config":1087},"gitlab.com",{"href":752,"dataGaName":1088,"dataGaLocation":1089},"search login","search",{"text":1091,"default":1092},"Suggestions",[1093,1095,1099,1101,1105,1109],{"text":769,"config":1094},{"href":774,"dataGaName":769,"dataGaLocation":1089},{"text":1096,"config":1097},"Code Suggestions (AI)",{"href":1098,"dataGaName":1096,"dataGaLocation":1089},"/solutions/code-suggestions/",{"text":805,"config":1100},{"href":807,"dataGaName":805,"dataGaLocation":1089},{"text":1102,"config":1103},"GitLab on AWS",{"href":1104,"dataGaName":1102,"dataGaLocation":1089},"/partners/technology-partners/aws/",{"text":1106,"config":1107},"GitLab on Google Cloud",{"href":1108,"dataGaName":1106,"dataGaLocation":1089},"/partners/technology-partners/google-cloud-platform/",{"text":1110,"config":1111},"Why GitLab?",{"href":782,"dataGaName":1110,"dataGaLocation":1089},{"freeTrial":1113,"mobileIcon":1118,"desktopIcon":1123,"secondaryButton":1126},{"text":1114,"config":1115},"Start free trial",{"href":1116,"dataGaName":743,"dataGaLocation":1117},"https://gitlab.com/-/trials/new/","nav",{"altText":1119,"config":1120},"Gitlab Icon",{"src":1121,"dataGaName":1122,"dataGaLocation":1117},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1119,"config":1124},{"src":1125,"dataGaName":1122,"dataGaLocation":1117},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1127,"config":1128},"Get Started",{"href":1129,"dataGaName":1130,"dataGaLocation":1117},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1132,"mobileIcon":1136,"desktopIcon":1138},{"text":1133,"config":1134},"Learn more about GitLab Duo",{"href":774,"dataGaName":1135,"dataGaLocation":1117},"gitlab duo",{"altText":1119,"config":1137},{"src":1121,"dataGaName":1122,"dataGaLocation":1117},{"altText":1119,"config":1139},{"src":1125,"dataGaName":1122,"dataGaLocation":1117},{"button":1141,"mobileIcon":1146,"desktopIcon":1148},{"text":1142,"config":1143},"/switch",{"href":1144,"dataGaName":1145,"dataGaLocation":1117},"#contact","switch",{"altText":1119,"config":1147},{"src":1121,"dataGaName":1122,"dataGaLocation":1117},{"altText":1119,"config":1149},{"src":1150,"dataGaName":1122,"dataGaLocation":1117},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1152,"mobileIcon":1157,"desktopIcon":1159},{"text":1153,"config":1154},"Back to pricing",{"href":887,"dataGaName":1155,"dataGaLocation":1117,"icon":1156},"back to pricing","GoBack",{"altText":1119,"config":1158},{"src":1121,"dataGaName":1122,"dataGaLocation":1117},{"altText":1119,"config":1160},{"src":1125,"dataGaName":1122,"dataGaLocation":1117},{"title":1162,"titleMobile":1163,"button":1164,"config":1169},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":780,"config":1165},{"href":1166,"dataGaName":1167,"dataGaLocation":1168},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1170,"disabled":717},"release",{"data":1172},{"text":1173,"source":1174,"edit":1180,"contribute":1185,"config":1190,"items":1195,"minimal":1404},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1175,"config":1176},"View page source",{"href":1177,"dataGaName":1178,"dataGaLocation":1179},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1181,"config":1182},"Edit this page",{"href":1183,"dataGaName":1184,"dataGaLocation":1179},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1186,"config":1187},"Please contribute",{"href":1188,"dataGaName":1189,"dataGaLocation":1179},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1191,"facebook":1192,"youtube":1193,"linkedin":1194},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1196,1243,1296,1340,1372],{"title":885,"links":1197,"subMenu":1212},[1198,1202,1207],{"text":1199,"config":1200},"View plans",{"href":887,"dataGaName":1201,"dataGaLocation":1179},"view plans",{"text":1203,"config":1204},"Why Premium?",{"href":1205,"dataGaName":1206,"dataGaLocation":1179},"/pricing/premium/","why premium",{"text":1208,"config":1209},"Why Ultimate?",{"href":1210,"dataGaName":1211,"dataGaLocation":1179},"/pricing/ultimate/","why ultimate",[1213],{"title":1214,"links":1215},"Contact Us",[1216,1219,1221,1223,1228,1233,1238],{"text":1217,"config":1218},"Contact sales",{"href":1069,"dataGaName":748,"dataGaLocation":1179},{"text":1072,"config":1220},{"href":1074,"dataGaName":1075,"dataGaLocation":1179},{"text":1077,"config":1222},{"href":1079,"dataGaName":1080,"dataGaLocation":1179},{"text":1224,"config":1225},"Status",{"href":1226,"dataGaName":1227,"dataGaLocation":1179},"https://status.gitlab.com/","status",{"text":1229,"config":1230},"Terms of use",{"href":1231,"dataGaName":1232,"dataGaLocation":1179},"/terms/","terms of use",{"text":1234,"config":1235},"Privacy statement",{"href":1236,"dataGaName":1237,"dataGaLocation":1179},"/privacy/","privacy statement",{"text":1239,"config":1240},"Cookie preferences",{"dataGaName":1241,"dataGaLocation":1179,"id":1242,"isOneTrustButton":720},"cookie preferences","ot-sdk-btn",{"title":785,"links":1244,"subMenu":1253},[1245,1249],{"text":1246,"config":1247},"DevSecOps platform",{"href":767,"dataGaName":1248,"dataGaLocation":1179},"devsecops platform",{"text":1250,"config":1251},"AI-Assisted Development",{"href":774,"dataGaName":1252,"dataGaLocation":1179},"ai-assisted development",[1254],{"title":1255,"links":1256},"Topics",[1257,1262,1267,1271,1276,1281,1286,1291],{"text":1258,"config":1259},"CICD",{"href":1260,"dataGaName":1261,"dataGaLocation":1179},"/topics/ci-cd/","cicd",{"text":1263,"config":1264},"GitOps",{"href":1265,"dataGaName":1266,"dataGaLocation":1179},"/topics/gitops/","gitops",{"text":1268,"config":1269},"DevOps",{"href":24,"dataGaName":1270,"dataGaLocation":1179},"devops",{"text":1272,"config":1273},"Version Control",{"href":1274,"dataGaName":1275,"dataGaLocation":1179},"/topics/version-control/","version control",{"text":1277,"config":1278},"DevSecOps",{"href":1279,"dataGaName":1280,"dataGaLocation":1179},"/topics/devsecops/","devsecops",{"text":1282,"config":1283},"Cloud Native",{"href":1284,"dataGaName":1285,"dataGaLocation":1179},"/topics/cloud-native/","cloud native",{"text":1287,"config":1288},"AI for Coding",{"href":1289,"dataGaName":1290,"dataGaLocation":1179},"/topics/devops/ai-for-coding/","ai for coding",{"text":1292,"config":1293},"Agentic AI",{"href":1294,"dataGaName":1295,"dataGaLocation":1179},"/topics/agentic-ai/","agentic ai",{"title":1297,"links":1298},"Solutions",[1299,1301,1303,1308,1312,1315,1319,1322,1324,1327,1330,1335],{"text":829,"config":1300},{"href":824,"dataGaName":829,"dataGaLocation":1179},{"text":818,"config":1302},{"href":801,"dataGaName":802,"dataGaLocation":1179},{"text":1304,"config":1305},"Agile development",{"href":1306,"dataGaName":1307,"dataGaLocation":1179},"/solutions/agile-delivery/","agile delivery",{"text":1309,"config":1310},"SCM",{"href":814,"dataGaName":1311,"dataGaLocation":1179},"source code management",{"text":1258,"config":1313},{"href":807,"dataGaName":1314,"dataGaLocation":1179},"continuous integration & delivery",{"text":1316,"config":1317},"Value stream management",{"href":857,"dataGaName":1318,"dataGaLocation":1179},"value stream management",{"text":1263,"config":1320},{"href":1321,"dataGaName":1266,"dataGaLocation":1179},"/solutions/gitops/",{"text":867,"config":1323},{"href":870,"dataGaName":871,"dataGaLocation":1179},{"text":1325,"config":1326},"Small business",{"href":876,"dataGaName":877,"dataGaLocation":1179},{"text":1328,"config":1329},"Public sector",{"href":882,"dataGaName":883,"dataGaLocation":1179},{"text":1331,"config":1332},"Education",{"href":1333,"dataGaName":1334,"dataGaLocation":1179},"/solutions/education/","education",{"text":1336,"config":1337},"Financial services",{"href":1338,"dataGaName":1339,"dataGaLocation":1179},"/solutions/finance/","financial services",{"title":890,"links":1341},[1342,1344,1346,1348,1351,1353,1356,1358,1360,1362,1364,1366,1368,1370],{"text":903,"config":1343},{"href":905,"dataGaName":906,"dataGaLocation":1179},{"text":908,"config":1345},{"href":910,"dataGaName":911,"dataGaLocation":1179},{"text":913,"config":1347},{"href":915,"dataGaName":916,"dataGaLocation":1179},{"text":918,"config":1349},{"href":920,"dataGaName":1350,"dataGaLocation":1179},"docs",{"text":941,"config":1352},{"href":943,"dataGaName":944,"dataGaLocation":1179},{"text":1354,"config":1355},"What's new",{"href":1001,"dataGaName":1002,"dataGaLocation":1179},{"text":936,"config":1357},{"href":938,"dataGaName":939,"dataGaLocation":1179},{"text":955,"config":1359},{"href":957,"dataGaName":958,"dataGaLocation":1179},{"text":963,"config":1361},{"href":965,"dataGaName":966,"dataGaLocation":1179},{"text":968,"config":1363},{"href":970,"dataGaName":971,"dataGaLocation":1179},{"text":973,"config":1365},{"href":975,"dataGaName":976,"dataGaLocation":1179},{"text":978,"config":1367},{"href":980,"dataGaName":981,"dataGaLocation":1179},{"text":983,"config":1369},{"href":985,"dataGaName":986,"dataGaLocation":1179},{"text":988,"config":1371},{"href":990,"dataGaName":991,"dataGaLocation":1179},{"title":1004,"links":1373},[1374,1376,1378,1380,1382,1384,1388,1393,1395,1397,1399],{"text":1012,"config":1375},{"href":1014,"dataGaName":1006,"dataGaLocation":1179},{"text":1017,"config":1377},{"href":1019,"dataGaName":1020,"dataGaLocation":1179},{"text":1025,"config":1379},{"href":1027,"dataGaName":1028,"dataGaLocation":1179},{"text":1030,"config":1381},{"href":1032,"dataGaName":1033,"dataGaLocation":1179},{"text":1035,"config":1383},{"href":1037,"dataGaName":1038,"dataGaLocation":1179},{"text":1385,"config":1386},"Sustainability",{"href":1387,"dataGaName":1385,"dataGaLocation":1179},"/sustainability/",{"text":1389,"config":1390},"Diversity, inclusion and belonging (DIB)",{"href":1391,"dataGaName":1392,"dataGaLocation":1179},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1040,"config":1394},{"href":1042,"dataGaName":1043,"dataGaLocation":1179},{"text":1050,"config":1396},{"href":1052,"dataGaName":1053,"dataGaLocation":1179},{"text":1055,"config":1398},{"href":1057,"dataGaName":1058,"dataGaLocation":1179},{"text":1400,"config":1401},"Modern Slavery Transparency Statement",{"href":1402,"dataGaName":1403,"dataGaLocation":1179},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1405},[1406,1409,1412],{"text":1407,"config":1408},"Terms",{"href":1231,"dataGaName":1232,"dataGaLocation":1179},{"text":1410,"config":1411},"Cookies",{"dataGaName":1241,"dataGaLocation":1179,"id":1242,"isOneTrustButton":720},{"text":1413,"config":1414},"Privacy",{"href":1236,"dataGaName":1237,"dataGaLocation":1179},[1416],{"id":1417,"title":7,"body":716,"config":1418,"content":1420,"description":716,"extension":1423,"meta":1424,"navigation":720,"path":1425,"seo":1426,"stem":1427,"__hash__":1428},"blogAuthors/en-us/blog/authors/luka-trbojevic.yml",{"template":1419},"BlogAuthor",{"name":7,"config":1421},{"headshot":144,"ctfId":1422},"ltrbojevic","yml",{},"/en-us/blog/authors/luka-trbojevic",{},"en-us/blog/authors/luka-trbojevic","MuQC6ZmkfmkdoNVm6SEahKlhvfTXmQZ9zfjexb0UXCY",[1430,1438,1446],{"title":1431,"description":1432,"heroImage":1433,"category":712,"date":1434,"authors":1435,"slug":1437,"externalUrl":716},"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",[1436],"Julian Thome","improved-scope-offset-fingerprinting",{"title":1439,"description":1440,"heroImage":1433,"category":712,"date":1441,"authors":1442,"slug":1445,"externalUrl":716},"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",[1443,1444],"Erick Bajao","Joe Randazzo","gitlab-secrets-manager-add-eso-terraform-api-support",{"title":1447,"description":1448,"heroImage":1449,"category":712,"date":1450,"authors":1451,"slug":1453,"externalUrl":716},"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",[1452],"Alisa Ho","claude-security-and-gitlab",{"promotions":1455},[1456,1470,1482,1493],{"id":1457,"categories":1458,"header":1460,"text":1461,"button":1462,"image":1467},"ai-modernization",[1459],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1463,"config":1464},"Get your AI maturity score",{"href":1465,"dataGaName":1466,"dataGaLocation":944},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1468},{"src":1469},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1471,"categories":1472,"header":1474,"text":1461,"button":1475,"image":1479},"devops-modernization",[1473,1280],"product","Are you just managing tools or shipping innovation?",{"text":1476,"config":1477},"Get your DevOps maturity score",{"href":1478,"dataGaName":1466,"dataGaLocation":944},"/assessments/devops-modernization-assessment/",{"config":1480},{"src":1481},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1483,"categories":1484,"header":1485,"text":1461,"button":1486,"image":1490},"security-modernization",[712],"Are you trading speed for security?",{"text":1487,"config":1488},"Get your security maturity score",{"href":1489,"dataGaName":1466,"dataGaLocation":944},"/assessments/security-modernization-assessment/",{"config":1491},{"src":1492},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1494,"paths":1495,"header":1498,"text":1499,"button":1500,"image":1505},"github-azure-migration",[1496,1497],"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":1501,"config":1502},"See how GitLab compares to GitHub",{"href":1503,"dataGaName":1504,"dataGaLocation":944},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1506},{"src":1481},{"header":1508,"blurb":1509,"button":1510,"secondaryButton":1515},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1511,"config":1512},"Get your free trial",{"href":1513,"dataGaName":743,"dataGaLocation":1514},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1217,"config":1516},{"href":1069,"dataGaName":748,"dataGaLocation":1514},1786803754004]