[{"data":1,"prerenderedAt":1571},["ShallowReactive",2],{"/blog/why-are-developers-vulnerable-to-driveby-attacks":3,"navigation-en-us":785,"banner-en-us":1213,"footer-en-us":1223,"blog-post-authors-en-us-Chris Moberly":1468,"blog-related-posts-en-us-why-are-developers-vulnerable-to-driveby-attacks":1483,"blog-promotions-en-us":1508,"next-steps-en-us":1561},{"id":4,"title":5,"authors":6,"body":8,"category":767,"date":768,"description":769,"extension":770,"externalUrl":771,"faq":771,"featured":772,"heroImage":773,"meta":774,"navigation":539,"path":775,"seo":776,"slug":780,"stem":781,"tags":782,"template":783,"updatedDate":771,"__hash__":784},"blogPosts/en-us/blog/why-are-developers-vulnerable-to-driveby-attacks.md","Why are developers so vulnerable to drive-by attacks?",[7],"Chris Moberly",{"type":9,"value":10,"toc":756},"minimark",[11,15,23,34,37,53,58,61,64,73,84,92,149,152,160,169,172,187,194,213,223,226,232,243,252,280,283,286,300,303,307,310,313,318,321,339,350,356,362,368,371,374,380,387,397,400,406,409,433,442,457,464,468,473,476,492,495,499,502,508,571,580,586,589,614,623,626,630,633,636,639,642,650,653,657,660,716,719,725,729,732,735,738,752],[12,13,14],"p",{},"As someone who spends a lot of time working with computers, I know how easy it is to grow over-confident with regards to security. My systems are patched, my firewall rules are tight, and I’m vigilant when it comes to just about anything that looks out of the ordinary.",[12,16,17,18,22],{},"No one’s hacking their way into ",[19,20,21],"em",{},"my"," workstation, that’s for sure.",[12,24,25,26,29,30,33],{},"But my experience working as a hacker myself has shown me that the opposite is often true. Those of us who are ",[19,27,28],{},"more"," technical are often ",[19,31,32],{},"much more"," vulnerable to an attack due to the complexity of our working environments.",[12,35,36],{},"In this blog, we’re going to dive into the anatomy of something called a “drive-by attack,” where malicious code hidden within a website uses your own browser to attack your computer.",[12,38,39,40,46,47,52],{},"As an example, I’ll show you how our own ",[41,42,45],"a",{"href":43,"rel":44},"https://handbook.gitlab.com/handbook/security/security-operations/red-team/",[],"Red Team"," was able to chain multiple vulnerabilities in the ",[41,48,51],{"href":49,"rel":50},"https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/README.md",[],"GitLab Development Kit"," (GDK) to achieve remote code execution (RCE) on developer laptops. And lastly, we’ll discuss steps you can take to reduce the risk of this happening to you.",[54,55,57],"h2",{"id":56},"how-drive-by-attacks-work","How drive-by attacks work",[12,59,60],{},"Drive-by attacks come in many forms. Each type of attack starts the same way - you visit a website that contains some malicious code (typically JavaScript). That code will then target a specific type of vulnerability, either in your browser itself or in some other network service that your browser can access. In this blog, we will focus on the latter.",[12,62,63],{},"What I find particularly fascinating about these attacks is that they completely bypass traditional protections like network firewalls and antivirus software. I think many are under the impression that a network service running on their localhost address cannot be targeted remotely. This is simply not true; in fact, this same technique can be used to target any service on your local network, even those without any outbound internet access at all!",[12,65,66,67,72],{},"Let’s say you are running a test webserver on your laptop on port 8000. You can simulate this running a simple ",[41,68,71],{"href":69,"rel":70},"https://en.wikipedia.org/wiki/Netcat",[],"netcat"," command:",[74,75,81],"pre",{"className":76,"code":78,"language":79,"meta":80},[77],"language-text","nc -lkp 8000\n","text","",[82,83,78],"code",{"__ignoreMap":80},[12,85,86,87,91],{},"Now let’s say you are browsing the internet while that test server is running locally. You visit a site that has been compromised with malicious JavaScript. We’ve set up a site at ",[41,88,89],{"href":89,"rel":90},"https://gitlab-com.gitlab.io/gl-security/security-operations/gl-redteam/simple-request",[]," that mimics a basic attack. The site contains the following JavaScript:",[74,93,97],{"className":94,"code":95,"language":96,"meta":80,"style":80},"language-xml shiki shiki-themes github-light","\u003Cscript>\n    fetch(\"http://localhost:8000\", {\n        method: 'post',\n        body: 'you\\'re under attack!',\n    })\n\u003C/script>\n","xml",[82,98,99,115,121,127,133,139],{"__ignoreMap":80},[100,101,104,108,112],"span",{"class":102,"line":103},"line",1,[100,105,107],{"class":106},"sgsFI","\u003C",[100,109,111],{"class":110},"shJU0","script",[100,113,114],{"class":106},">\n",[100,116,118],{"class":102,"line":117},2,[100,119,120],{"class":106},"    fetch(\"http://localhost:8000\", {\n",[100,122,124],{"class":102,"line":123},3,[100,125,126],{"class":106},"        method: 'post',\n",[100,128,130],{"class":102,"line":129},4,[100,131,132],{"class":106},"        body: 'you\\'re under attack!',\n",[100,134,136],{"class":102,"line":135},5,[100,137,138],{"class":106},"    })\n",[100,140,142,145,147],{"class":102,"line":141},6,[100,143,144],{"class":106},"\u003C/",[100,146,111],{"class":110},[100,148,114],{"class":106},[12,150,151],{},"When you open the site in your browser, you should see that a POST request has been executed against your simulated server, like the screenshot below.",[12,153,154,159],{},[155,156],"img",{"alt":157,"src":158},"file name","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398203/blog/Content%20Images/drive-by/firefox.png","\nHelp, I’m under attack!",[12,161,162,163,168],{},"When JavaScript attempts to interact with another website, the first thing your browser checks is whether or not the protocol, port, and domain all match between that other site and where the script was originally loaded from. This is called the ",[41,164,167],{"href":165,"rel":166},"https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy",[],"same-origin policy",": it's your browser’s first line of defense when it comes to these types of attacks.",[12,170,171],{},"In our example above, none of these items matched. That makes this a cross-origin request. Luckily, modern browsers have some mechanisms to restrict exactly what these types of requests can do.",[12,173,174,175,180,181,186],{},"One of these is called a “",[41,176,179],{"href":177,"rel":178},"https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request",[],"CORS preflight request",".” When some JavaScript asks your browser to perform complex actions on a cross-origin request, your browser will first send an HTTP OPTIONS request to the target. The target will respond with various HTTP headers that tell the browser what is allowed. The most common of these is the “",[41,182,185],{"href":183,"rel":184},"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin",[],"Access-Control-Allow-Origin","” header.",[12,188,189,190,193],{},"If this header is set to ",[82,191,192],{},"*"," or to the website containing the malicious code, then your browser will let the code perform complex HTTP requests and access the responses. This would include shipping results off to a remote server, or performing complex multi-step actions like logging in to a service or gaining access to the session token; basically the code will be interacting with it as if it were a human user.",[12,195,196,197,202,203,206,207,209,210,212],{},"Another header you may encounter is ",[41,198,201],{"href":199,"rel":200},"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#requests_with_credentials",[],"Access-Control-Allow-Credentials",". When set to ",[82,204,205],{},"true",", the origin specified in ",[82,208,185],{}," can perform credentialed requests utilizing the browser’s active sessions. When origin validation is not done properly and the requesting origin is blindly reflected in ",[82,211,185],{},", drive-by attacks against authenticated services become much more likely to succeed as they do not need to first guess the password and mimic a logon.",[12,214,215,216,219,220,222],{},"From my experience, the first example (",[82,217,218],{},"Access-Control-Allow-Origin: *",") is enabled quite often in development software and open-source projects. Even production-ready applications may intentionally set this header to ",[82,221,192],{}," when started with certain flags that tell them they are running in development mode.",[12,224,225],{},"What makes matters worse is that software run in development mode tends to have other relaxed security measures: verbose error logging, default passwords or even debuggers that allow web requests to execute commands on the host operating system. This makes it very easy for malicious JavaScript to turn basic cross-origin requests into full-on drive-by exploits that completely compromise your machine.",[12,227,228],{},[229,230,231],"strong",{},"To be very clear, if you are running a web server on your workstation with this header set, you are granting permission to any website you visit to fully interact with your application. If that application has the ability to run commands on your laptop, you could be granting any website you visit permission to run commands on your laptop.",[12,233,234,235,238,239,242],{},"“",[19,236,237],{},"Well, that’s fine",",” you might think. “",[19,240,241],{},"I’ll just remove that header and be good to go","”.",[12,244,245,246,251],{},"Unfortunately, it’s not that simple. The preflight check has a pretty big loophole via something called a “",[41,247,250],{"href":248,"rel":249},"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests",[],"simple request",".” Remote JavaScript is allowed to completely bypass the check if it follows some simple rules, like:",[253,254,255,259,274,277],"ul",{},[256,257,258],"li",{},"Must be only GET, HEAD, or POST",[256,260,261,262,265,266,269,270,273],{},"Must be one of three content types (",[82,263,264],{},"application/x-www-form-urlencoded",", ",[82,267,268],{},"multipart/form-data"," or ",[82,271,272],{},"text/plain",")",[256,275,276],{},"Must use only a specific set of HTTP headers",[256,278,279],{},"Cannot read the response from the target service",[12,281,282],{},"This is why we had no issues running the “you’re under attack!” example above. It followed the rules and was a simple request.",[12,284,285],{},"So, to reiterate:",[253,287,288,291,294],{},[256,289,290],{},"Any website on the internet can use your browser to attack any service you have access to as long as the attack follows certain rules.",[256,292,293],{},"Services that implement strong protections against Cross-Site Request Forgery (CSRF) can be more resilient to these attacks.",[256,295,296,297,299],{},"Services that specifically reduce these protections (like with the ",[82,298,185],{}," header) are vulnerable to any attack, whether they follow the rules or not.",[12,301,302],{},"How confident are you that every service you run and test locally has implemented strong CSRF protections and has not removed them while in development mode? And even if they have, how confident are you that they cannot still be exploited via the simple requests described above?",[54,304,306],{"id":305},"example-drive-by-rce-in-the-gitlab-gdk","Example: Drive-by RCE in the GitLab GDK",[12,308,309],{},"The GitLab GDK is a tool that helps GitLab contributors install a fully-functioning GitLab instance for development purposes.",[12,311,312],{},"In September of 2020, our Red Team was researching how our developers could be targeted by sophisticated attackers. We were able to chain multiple vulnerabilities in the GDK to conduct the exact type of attack described in this blog, demonstrating how developer workstations could be remotely compromised.",[12,314,315],{},[229,316,317],{},"These vulnerabilities were quickly patched, the community was asked to upgrade, and this specific risk no longer exists. Read on below about the specific issues and their fixes.",[12,319,320],{},"The attack targeted two components bundled with the GDK:",[253,322,323,331],{},[256,324,325,330],{},[41,326,329],{"href":327,"rel":328},"https://github.com/BetterErrors/better_errors",[],"Better Errors",": a Rails error debugging tool",[256,332,333,338],{},[41,334,337],{"href":335,"rel":336},"https://github.com/webpack/webpack-dev-server",[],"webpack-dev-server",": a development web server that provides static file access",[12,340,341,342,345,346,349],{},"When visited, the first thing the malicious website would do was to load the better_errors console in an invisible iframe. The result of this was a simple ",[82,343,344],{},"GET"," request from the browser to ",[82,347,348],{},"http://localhost:3000/__better_errors",".\nWhen this URL was loaded, the better_errors application would generate a unique error code (this is important later on) and then send an HTTP redirect code back to the browser inside the iframe. The URL that it redirected to would include the unique error code, like this:",[74,351,354],{"className":352,"code":353,"language":79,"meta":80},[77],"http://localhost:3000/__better_errors/[ERROR CODE]/eval\n",[82,355,353],{"__ignoreMap":80},[12,357,358,359,361],{},"Because better_errors did not have the dangerous ",[82,360,218],{}," header set, the malicious site could not actually view that response. However, the GDK keeps a lot of log files, including a record of every URL that has been accessed. This meant that the unique error code generated by better_errors was now stored in a log file on the workstation’s filesystem.",[12,363,364,365,367],{},"The next step targeted the webpack-dev-server. This ran on localhost on port 3808 and was configured with the overly-permissive CORS header ",[82,366,218],{},".  As discussed earlier in the blog, this header tells your browser that any website can interact freely with this service.",[12,369,370],{},"webpack-dev-server was configured to serve the contents of the log directory, so our malicious JavaScript could literally download and parse the current log file to extract the unique error code generated above.",[12,372,373],{},"Using this error code, the script would then create a specially-crafted HTTP POST request to instruct better_errors to evaluate arbitrary Ruby code. And, of course, with Ruby we can encapsulate operating system commands in backticks to execute any command we wanted to on the host. That request looked like this:",[74,375,378],{"className":376,"code":377,"language":79,"meta":80},[77],"POST http://localhost:3000/__better_errors/[ERROR CODE]/eval\nContent-Type: text/plain\nAccept: text/html\n\n{\"index\":\"0\",\"source\":\"`touch /tmp/itworked`\"}\n",[82,379,377],{"__ignoreMap":80},[12,381,382,383,386],{},"It is worth noting that better_errors actually ",[229,384,385],{},"did not"," have an overly-permissive CORS header. So, technically, we should not have been able to send the above command. Because the content being sent was actually JSON, it would not have qualified as a “simple request” and would have had to pass a CORS preflight check, which would have failed.",[12,388,389,390,393,394,396],{},"However, the ",[82,391,392],{},"Content-type"," header was not being validated properly. We were able to bypass the preflight check by incorrectly setting the content type to ",[82,395,272],{}," while still providing a JSON payload in the request body.",[12,398,399],{},"When the malicious website instructed the browser to send that final request, the command would be executed and the host would be compromised.",[12,401,402,405],{},[155,403],{"alt":157,"src":404},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398203/blog/Content%20Images/drive-by/driveby.png","\nThe original PoC in action.",[12,407,408],{},"To summarize the issues that made this possible:",[253,410,411],{},[256,412,413,414],{},"Better Errors:\n",[253,415,416,419,422,428],{},[256,417,418],{},"Improper validation of content type header",[256,420,421],{},"Lack of robust cross-site request forgery protection (CSRF tokens)  * webpack-dev-server:",[256,423,424,425,273],{},"Was configured to serve the entire GitLab directory (via ",[82,426,427],{},"contentBase: true",[256,429,430,431,273],{},"Overly-permissive CORS header (",[82,432,218],{},[12,434,435,436,441],{},"While GitLab ended up completely removing Better Errors from the GDK, we did reach out to its author who was incredibly responsive and very quickly ",[41,437,440],{"href":438,"rel":439},"https://github.com/BetterErrors/better_errors/pull/474",[],"implemented robust protection"," for the issues we disclosed.",[12,443,444,445,450,451,456],{},"The GDK still uses webpack-dev-server, but it has been configured to ",[41,446,449],{"href":447,"rel":448},"https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41841",[],"stop serving the installation directory"," and to ",[41,452,455],{"href":453,"rel":454},"https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46459",[],"stop sending the overly-permissive CORS header",".",[12,458,459,460,456],{},"You can view the source code for the original PoC exploit at ",[41,461,462],{"href":462,"rel":463},"https://gitlab.com/gitlab-com/gl-security/security-operations/gl-redteam/gdk-driveby-poc-public",[],[54,465,467],{"id":466},"how-to-protect-yourself-from-drive-by-attacks","How to protect yourself from drive-by attacks",[469,470,472],"h3",{"id":471},"secure-your-code-from-cross-origin-attacks","Secure your code from cross-origin attacks",[12,474,475],{},"If you are a developer looking to strengthen your own application, here are two great resources to get you started:",[253,477,478,485],{},[256,479,480],{},[41,481,484],{"href":482,"rel":483},"https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html",[],"OWASP Cross-Site Request Forgery Prevention Cheat Sheet",[256,486,487],{},[41,488,491],{"href":489,"rel":490},"https://portswigger.net/web-security/cors",[],"Portswigger: What is CORS?",[12,493,494],{},"Do not make the mistake of thinking that your application does not require protection just because it is never exposed to the internet. Any application that listens for requests on a network port can be attacked, even if it only ever runs on localhost for testing purposes.",[469,496,498],{"id":497},"inspect-your-own-network","Inspect your own network",[12,500,501],{},"As users of software in general, we need to be aware of the increased attack surface that comes with every piece of software we install.",[12,503,504,507],{},[229,505,506],{},"How many network services do you have running locally on your workstation right now?"," Try one of the following commands, you might be surprised by the results:",[74,509,513],{"className":510,"code":511,"language":512,"meta":80,"style":80},"language-shell shiki shiki-themes github-light","# Linux systems\nsudo ss -tlpa\n\n# MacOS systems\nsudo lsof -i -P | grep -i \"listen\"\n","shell",[82,514,515,521,535,541,546],{"__ignoreMap":80},[100,516,517],{"class":102,"line":103},[100,518,520],{"class":519},"sAwPA","# Linux systems\n",[100,522,523,527,531],{"class":102,"line":117},[100,524,526],{"class":525},"s7eDp","sudo",[100,528,530],{"class":529},"sYBdl"," ss",[100,532,534],{"class":533},"sYu0t"," -tlpa\n",[100,536,537],{"class":102,"line":123},[100,538,540],{"emptyLinePlaceholder":539},true,"\n",[100,542,543],{"class":102,"line":129},[100,544,545],{"class":519},"# MacOS systems\n",[100,547,548,550,553,556,559,563,566,568],{"class":102,"line":135},[100,549,526],{"class":525},[100,551,552],{"class":529}," lsof",[100,554,555],{"class":533}," -i",[100,557,558],{"class":533}," -P",[100,560,562],{"class":561},"sD7c4"," |",[100,564,565],{"class":525}," grep",[100,567,555],{"class":533},[100,569,570],{"class":529}," \"listen\"\n",[12,572,573,574,579],{},"How about on your home network? Those are also potential targets for a drive-by attack. If your browser can access them, it can be used to attack them. You can get a quick view using ",[41,575,578],{"href":576,"rel":577},"https://nmap.org/",[],"nmap"," like this:",[74,581,584],{"className":582,"code":583,"language":79,"meta":80},[77],"# Assuming your LAN is 192.168.1.0/24. Change as needed.\nnmap -sV 192.168.1.0/24\n",[82,585,583],{"__ignoreMap":80},[12,587,588],{},"If you uncover anything that looks like a web service, try to inspect the default HTTP response headers with a command like this:",[74,590,592],{"className":510,"code":591,"language":512,"meta":80,"style":80},"curl -vv -H \"Origin: http://attacker.com\" http://[IP ADDRESS]\n",[82,593,594],{"__ignoreMap":80},[100,595,596,599,602,605,608,611],{"class":102,"line":103},[100,597,598],{"class":525},"curl",[100,600,601],{"class":533}," -vv",[100,603,604],{"class":533}," -H",[100,606,607],{"class":529}," \"Origin: http://attacker.com\"",[100,609,610],{"class":529}," http://[IP",[100,612,613],{"class":529}," ADDRESS]\n",[12,615,616,617,269,619,622],{},"If the response headers include something like ",[82,618,218],{},[82,620,621],{},"Access-Control-Allow-Origin: http://attacker.com",", then you know right away that there is a high chance it is vulnerable to a drive-by attack.",[12,624,625],{},"However, as demonstrated in our example above, even services with properly configured CORS headers can be targeted by drive-by attacks under the right conditions.",[469,627,629],{"id":628},"reducing-potential-impact-and-risk","Reducing potential impact and risk",[12,631,632],{},"When testing and developing software, we end up executing a lot of code via libraries and dependencies. It’s unlikely that we have the time and resources to personally audit every single line of that code. To make matters worse, we often run local environments with intentionally relaxed security controls because it is just too cumbersome to emulate full production environments on our workstations.",[12,634,635],{},"Eliminating these risks totally might be unrealistic, but we can at least make an effort to reduce the potential impact should one of these environments be compromised.",[12,637,638],{},"If you were to fall victim to a drive-by attack while running an insecure server on your workstation, you would be in for a very bad day. An attacker with a shell on your system can take over every authenticated web session you have, access all of your local data, and potentially compromise any other remote system you have access to.",[12,640,641],{},"The most obvious way to reduce risk would be to not run potentially risky software directly on your workstation. Some easy ways to do this would be:",[253,643,644,647],{},[256,645,646],{},"Use temporary virtual machines (in the cloud or with local virtualization software) that are reverted to “known good” snapshots often. Ensure these machines contain no sensitive data.",[256,648,649],{},"Use container technology (LXD, Docker, etc) for launching temporary test environments. Follow best practices to make container escapes more difficult.",[12,651,652],{},"Neither of the above are iron-clad protections. Attackers can still target VMs and containers using your workstation’s browser. Sophisticated attackers may even find their way out of that restricted environment and back onto your workstation. But these methods do add another layer between potentially insecure code and your sensitive data.",[469,654,656],{"id":655},"secure-your-browser","Secure your browser",[12,658,659],{},"Additional layers of security can also be implemented around the browser, by segmenting it or restricting what it can do. Remember, your browser is what a drive-by attack abuses to gain access to local services. Here are some ideas to consider:",[253,661,662,677,698,701],{},[256,663,664,665,670,671,676],{},"Use the ",[41,666,669],{"href":667,"rel":668},"https://www.torproject.org/",[],"Tor Browser",". Besides coming with enhanced security features enabled by default, it literally ",[41,672,675],{"href":673,"rel":674},"https://gitlab.torproject.org/legacy/trac/-/issues/10419",[],"cannot access localhost"," or your LAN.",[256,678,679,680,685,686,691,692,697],{},"In your normal browser, plugins like ",[41,681,684],{"href":682,"rel":683},"https://github.com/gorhill/uBlock",[],"uBlock Origin"," can limit the ability of JavaScript to execute (see ",[41,687,690],{"href":688,"rel":689},"https://github.com/gorhill/uBlock/wiki/Blocking-mode",[],"blocking modes",") and block sites from accessing local IP addresses (enable the \"block access to LAN\" ",[41,693,696],{"href":694,"rel":695},"https://github.com/gorhill/uBlock/wiki/Dashboard:-Filter-lists",[],"filter-list",").",[256,699,700],{},"Some attacks may use a DNS name that resolves to a local IP address, which would bypass the filter list described above. See if your provider supports something called \"DNS rebind protection\" (available in dnsmasq, pihole, and services like NextDNS).",[256,702,703,704,709,710,715],{},"You can run a web browser inside a virtual machine with limited access to your workstation and/or your LAN. This can be done manually or via products like ",[41,705,708],{"href":706,"rel":707},"https://www.qubes-os.org/",[],"QubesOS"," and/or ",[41,711,714],{"href":712,"rel":713},"https://www.whonix.org/",[],"Whonix",". Use this segmented browser when accessing sites that you do not trust completely. Revert the browser VMs back to a known good state often.",[12,717,718],{},"Some of the ideas above, such as using the Tor Browser or a virtual machine, may not be particularly convenient for 100% of your tasks. You can use them selectively when accessing sites that you have specific concerns with (like while conducting incident response or security research).",[12,720,721,724],{},[155,722],{"alt":157,"src":723},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1782398203/blog/Content%20Images/drive-by/tor-browser.png","\nTor Browser to the rescue!",[54,726,728],{"id":727},"understand-and-protect-your-attack-surface","Understand and protect your attack surface",[12,730,731],{},"If you are running software on your computer that listens on a local network port, you are running a server. That server can be accessed and attacked by any website you visit. Because software developers frequently test less-secure services on their local machines, they are at an increased risk of compromise by these types of attacks.",[12,733,734],{},"Understanding this attack surface is important, as it lets you make decisions about what additional layers of security you can use to protect yourself. If you have any tips of your own to share, please do so in the comments below.",[12,736,737],{},"Thanks for reading!",[12,739,740,741,746,747],{},"Cover image by ",[41,742,745],{"href":743,"rel":744},"https://www.pexels.com/@pixabay",[],"Pixabay"," on ",[41,748,751],{"href":749,"rel":750},"https://www.pexels.com/photo/action-asphalt-back-light-cars-434450/",[],"Pexels",[753,754,755],"style",{},"html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}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 .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}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":80,"searchDepth":117,"depth":117,"links":757},[758,759,760,766],{"id":56,"depth":117,"text":57},{"id":305,"depth":117,"text":306},{"id":466,"depth":117,"text":467,"children":761},[762,763,764,765],{"id":471,"depth":123,"text":472},{"id":497,"depth":123,"text":498},{"id":628,"depth":123,"text":629},{"id":655,"depth":123,"text":656},{"id":727,"depth":117,"text":728},"security","2021-09-07","The complexity of developer working environments make them more likely to be vulnerable to a drive-by attack. We talk about why and walk you through a real-life example from a recent disclosure here at GitLab, and provide tips to reduce the risk and impact of drive-by attacks.","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749682986/Blog/Hero%20Images/pexels-pixabay-434450.jpg",{},"/en-us/blog/why-are-developers-vulnerable-to-driveby-attacks",{"title":5,"description":769,"ogTitle":5,"ogDescription":769,"noIndex":772,"ogImage":773,"ogUrl":777,"ogSiteName":778,"ogType":779,"canonicalUrls":777},"https://about.gitlab.com/blog/why-are-developers-vulnerable-to-driveby-attacks","https://about.gitlab.com","article","why-are-developers-vulnerable-to-driveby-attacks","en-us/blog/why-are-developers-vulnerable-to-driveby-attacks",[767],"BlogPost","OD94LxvKkq0kCr-ViUez0z2sY_5u1bUHNiqyGnFqd7s",{"logo":786,"freeTrial":791,"sales":796,"login":801,"items":806,"search":1133,"minimal":1164,"duo":1183,"switchNav":1192,"pricingDeployment":1203},{"config":787},{"href":788,"dataGaName":789,"dataGaLocation":790},"/","gitlab logo","header",{"text":792,"config":793},"Get free trial",{"href":794,"dataGaName":795,"dataGaLocation":790},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":797,"config":798},"Request a demo",{"href":799,"dataGaName":800,"dataGaLocation":790},"/sales/?contact-topic=request-demo","sales",{"text":802,"config":803},"Sign in",{"href":804,"dataGaName":805,"dataGaLocation":790},"https://gitlab.com/users/sign_in/","sign in",[807,836,936,941,1055,1111],{"text":808,"config":809,"menu":811},"Platform",{"dataNavLevelOne":810},"platform",{"type":812,"columns":813},"cards",[814,820,828],{"title":808,"description":815,"link":816},"The intelligent orchestration platform for DevSecOps",{"text":817,"config":818},"Explore our Platform",{"href":819,"dataGaName":810,"dataGaLocation":790},"/platform/",{"title":821,"description":822,"link":823},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":824,"config":825},"Meet GitLab Duo",{"href":826,"dataGaName":827,"dataGaLocation":790},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":829,"description":830,"link":831},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":832,"config":833},"Learn more",{"href":834,"dataGaName":835,"dataGaLocation":790},"/why-gitlab/","why gitlab",{"text":837,"left":539,"config":838,"menu":840},"Product",{"dataNavLevelOne":839},"solutions",{"type":841,"link":842,"columns":846,"feature":915},"lists",{"text":843,"config":844},"View all Solutions",{"href":845,"dataGaName":839,"dataGaLocation":790},"/solutions/",[847,871,894],{"title":848,"description":849,"link":850,"items":855},"Automation","CI/CD and automation to accelerate deployment",{"config":851},{"icon":852,"href":853,"dataGaName":854,"dataGaLocation":790},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[856,860,863,867],{"text":857,"config":858},"CI/CD",{"href":859,"dataGaLocation":790,"dataGaName":857},"/solutions/continuous-integration/",{"text":821,"config":861},{"href":826,"dataGaLocation":790,"dataGaName":862},"gitlab duo agent platform - product menu",{"text":864,"config":865},"Source Code Management",{"href":866,"dataGaLocation":790,"dataGaName":864},"/solutions/source-code-management/",{"text":868,"config":869},"Automated Software Delivery",{"href":853,"dataGaLocation":790,"dataGaName":870},"Automated software delivery",{"title":872,"description":873,"link":874,"items":879},"Security","Deliver code faster without compromising security",{"config":875},{"href":876,"dataGaName":877,"dataGaLocation":790,"icon":878},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[880,884,889],{"text":881,"config":882},"Application Security Testing",{"href":876,"dataGaName":883,"dataGaLocation":790},"Application security testing",{"text":885,"config":886},"Software Supply Chain Security",{"href":887,"dataGaLocation":790,"dataGaName":888},"/solutions/supply-chain/","Software supply chain security",{"text":890,"config":891},"Software Compliance",{"href":892,"dataGaName":893,"dataGaLocation":790},"/solutions/software-compliance/","software compliance",{"title":895,"link":896,"items":901},"Measurement",{"config":897},{"icon":898,"href":899,"dataGaName":900,"dataGaLocation":790},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[902,906,910],{"text":903,"config":904},"Visibility & Measurement",{"href":899,"dataGaLocation":790,"dataGaName":905},"Visibility and Measurement",{"text":907,"config":908},"Value Stream Management",{"href":909,"dataGaLocation":790,"dataGaName":907},"/solutions/value-stream-management/",{"text":911,"config":912},"Analytics & Insights",{"href":913,"dataGaLocation":790,"dataGaName":914},"/solutions/analytics-and-insights/","Analytics and insights",{"title":916,"type":841,"items":917},"GitLab for",[918,924,930],{"text":919,"config":920},"Enterprise",{"icon":921,"href":922,"dataGaLocation":790,"dataGaName":923},"Building","/enterprise/","enterprise",{"text":925,"config":926},"Small Business",{"icon":927,"href":928,"dataGaLocation":790,"dataGaName":929},"Work","/small-business/","small business",{"text":931,"config":932},"Public Sector",{"icon":933,"href":934,"dataGaLocation":790,"dataGaName":935},"Organization","/solutions/public-sector/","public sector",{"text":937,"config":938},"Pricing",{"href":939,"dataGaName":940,"dataGaLocation":790,"dataNavLevelOne":940},"/pricing/","pricing",{"text":942,"config":943,"menu":945},"Resources",{"dataNavLevelOne":944},"resources",{"type":841,"link":946,"columns":950,"feature":1044},{"text":947,"config":948},"View all resources",{"href":949,"dataGaName":944,"dataGaLocation":790},"/resources/",[951,984,1011],{"title":952,"items":953},"Getting started",[954,959,964,969,974,979],{"text":955,"config":956},"Install",{"href":957,"dataGaName":958,"dataGaLocation":790},"/install/","install",{"text":960,"config":961},"Quick start guides",{"href":962,"dataGaName":963,"dataGaLocation":790},"/get-started/","quick setup checklists",{"text":965,"config":966},"Learn",{"href":967,"dataGaLocation":790,"dataGaName":968},"https://university.gitlab.com/","learn",{"text":970,"config":971},"Product documentation",{"href":972,"dataGaName":973,"dataGaLocation":790},"https://docs.gitlab.com/","product documentation",{"text":975,"config":976},"Best practice videos",{"href":977,"dataGaName":978,"dataGaLocation":790},"/getting-started-videos/","best practice videos",{"text":980,"config":981},"Integrations",{"href":982,"dataGaName":983,"dataGaLocation":790},"/integrations/","integrations",{"title":985,"items":986},"Discover",[987,992,997,1002,1006],{"text":988,"config":989},"Customer success stories",{"href":990,"dataGaName":991,"dataGaLocation":790},"/customers/","customer success stories",{"text":993,"config":994},"Blog",{"href":995,"dataGaName":996,"dataGaLocation":790},"/blog/","blog",{"text":998,"config":999},"Demo Hub",{"href":1000,"dataGaName":1001,"dataGaLocation":790},"/demo-hub/","demo hub",{"text":1003,"config":1004},"The Source",{"href":1005,"dataGaName":996,"dataGaLocation":790},"/the-source/",{"text":1007,"config":1008},"Remote",{"href":1009,"dataGaName":1010,"dataGaLocation":790},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1012,"items":1013},"Connect",[1014,1019,1024,1029,1034,1039],{"text":1015,"config":1016},"GitLab Services",{"href":1017,"dataGaName":1018,"dataGaLocation":790},"/services/","services",{"text":1020,"config":1021},"Contribute",{"href":1022,"dataGaName":1023,"dataGaLocation":790},"https://contributors.gitlab.com","contribute",{"text":1025,"config":1026},"Community",{"href":1027,"dataGaName":1028,"dataGaLocation":790},"/community/","community",{"text":1030,"config":1031},"Forum",{"href":1032,"dataGaName":1033,"dataGaLocation":790},"https://forum.gitlab.com/","forum",{"text":1035,"config":1036},"Events",{"href":1037,"dataGaName":1038,"dataGaLocation":790},"/events/","events",{"text":1040,"config":1041},"Partners",{"href":1042,"dataGaName":1043,"dataGaLocation":790},"/partners/","partners",{"config":1045,"title":1048,"text":1049,"link":1050},{"background":1046,"textColor":1047},"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":1051,"config":1052},"Read the latest",{"href":1053,"dataGaName":1054,"dataGaLocation":790},"/whats-new/","whats new",{"text":1056,"config":1057,"menu":1059},"Company",{"dataNavLevelOne":1058},"company",{"type":841,"columns":1060},[1061],{"items":1062},[1063,1068,1074,1076,1081,1086,1091,1096,1101,1106],{"text":1064,"config":1065},"About",{"href":1066,"dataGaName":1067,"dataGaLocation":790},"/company/","about",{"text":1069,"config":1070,"footerGa":1073},"Jobs",{"href":1071,"dataGaName":1072,"dataGaLocation":790},"/jobs/","jobs",{"dataGaName":1072},{"text":1035,"config":1075},{"href":1037,"dataGaName":1038,"dataGaLocation":790},{"text":1077,"config":1078},"Leadership",{"href":1079,"dataGaName":1080,"dataGaLocation":790},"/company/team/e-group/","leadership",{"text":1082,"config":1083},"Handbook",{"href":1084,"dataGaName":1085,"dataGaLocation":790},"https://handbook.gitlab.com/","handbook",{"text":1087,"config":1088},"Investor relations",{"href":1089,"dataGaName":1090,"dataGaLocation":790},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1092,"config":1093},"Trust Center",{"href":1094,"dataGaName":1095,"dataGaLocation":790},"/security/","trust center",{"text":1097,"config":1098},"AI Transparency Center",{"href":1099,"dataGaName":1100,"dataGaLocation":790},"/ai-transparency-center/","ai transparency center",{"text":1102,"config":1103},"Newsletter",{"href":1104,"dataGaName":1105,"dataGaLocation":790},"/company/contact/#contact-forms","newsletter",{"text":1107,"config":1108},"Press",{"href":1109,"dataGaName":1110,"dataGaLocation":790},"/press/","press",{"text":1112,"config":1113,"menu":1114},"Contact us",{"dataNavLevelOne":1058},{"type":841,"columns":1115},[1116],{"items":1117},[1118,1123,1128],{"text":1119,"config":1120},"Talk to sales",{"href":1121,"dataGaName":1122,"dataGaLocation":790},"/sales/","talk to sales",{"text":1124,"config":1125},"Support portal",{"href":1126,"dataGaName":1127,"dataGaLocation":790},"https://support.gitlab.com/hc/en-us","support portal",{"text":1129,"config":1130},"Customer portal",{"href":1131,"dataGaName":1132,"dataGaLocation":790},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1134,"login":1135,"suggestions":1142},"Close",{"text":1136,"link":1137},"To search repositories and projects, login to",{"text":1138,"config":1139},"gitlab.com",{"href":804,"dataGaName":1140,"dataGaLocation":1141},"search login","search",{"text":1143,"default":1144},"Suggestions",[1145,1147,1151,1153,1157,1161],{"text":821,"config":1146},{"href":826,"dataGaName":821,"dataGaLocation":1141},{"text":1148,"config":1149},"Code Suggestions (AI)",{"href":1150,"dataGaName":1148,"dataGaLocation":1141},"/solutions/code-suggestions/",{"text":857,"config":1152},{"href":859,"dataGaName":857,"dataGaLocation":1141},{"text":1154,"config":1155},"GitLab on AWS",{"href":1156,"dataGaName":1154,"dataGaLocation":1141},"/partners/technology-partners/aws/",{"text":1158,"config":1159},"GitLab on Google Cloud",{"href":1160,"dataGaName":1158,"dataGaLocation":1141},"/partners/technology-partners/google-cloud-platform/",{"text":1162,"config":1163},"Why GitLab?",{"href":834,"dataGaName":1162,"dataGaLocation":1141},{"freeTrial":1165,"mobileIcon":1170,"desktopIcon":1175,"secondaryButton":1178},{"text":1166,"config":1167},"Start free trial",{"href":1168,"dataGaName":795,"dataGaLocation":1169},"https://gitlab.com/-/trials/new/","nav",{"altText":1171,"config":1172},"Gitlab Icon",{"src":1173,"dataGaName":1174,"dataGaLocation":1169},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1171,"config":1176},{"src":1177,"dataGaName":1174,"dataGaLocation":1169},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1179,"config":1180},"Get Started",{"href":1181,"dataGaName":1182,"dataGaLocation":1169},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1184,"mobileIcon":1188,"desktopIcon":1190},{"text":1185,"config":1186},"Learn more about GitLab Duo",{"href":826,"dataGaName":1187,"dataGaLocation":1169},"gitlab duo",{"altText":1171,"config":1189},{"src":1173,"dataGaName":1174,"dataGaLocation":1169},{"altText":1171,"config":1191},{"src":1177,"dataGaName":1174,"dataGaLocation":1169},{"button":1193,"mobileIcon":1198,"desktopIcon":1200},{"text":1194,"config":1195},"/switch",{"href":1196,"dataGaName":1197,"dataGaLocation":1169},"#contact","switch",{"altText":1171,"config":1199},{"src":1173,"dataGaName":1174,"dataGaLocation":1169},{"altText":1171,"config":1201},{"src":1202,"dataGaName":1174,"dataGaLocation":1169},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1204,"mobileIcon":1209,"desktopIcon":1211},{"text":1205,"config":1206},"Back to pricing",{"href":939,"dataGaName":1207,"dataGaLocation":1169,"icon":1208},"back to pricing","GoBack",{"altText":1171,"config":1210},{"src":1173,"dataGaName":1174,"dataGaLocation":1169},{"altText":1171,"config":1212},{"src":1177,"dataGaName":1174,"dataGaLocation":1169},{"title":1214,"titleMobile":1215,"button":1216,"config":1221},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":832,"config":1217},{"href":1218,"dataGaName":1219,"dataGaLocation":1220},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1222,"disabled":772},"release",{"data":1224},{"text":1225,"source":1226,"edit":1232,"contribute":1237,"config":1242,"items":1247,"minimal":1457},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1227,"config":1228},"View page source",{"href":1229,"dataGaName":1230,"dataGaLocation":1231},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1233,"config":1234},"Edit this page",{"href":1235,"dataGaName":1236,"dataGaLocation":1231},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1238,"config":1239},"Please contribute",{"href":1240,"dataGaName":1241,"dataGaLocation":1231},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1243,"facebook":1244,"youtube":1245,"linkedin":1246},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1248,1295,1349,1393,1425],{"title":937,"links":1249,"subMenu":1264},[1250,1254,1259],{"text":1251,"config":1252},"View plans",{"href":939,"dataGaName":1253,"dataGaLocation":1231},"view plans",{"text":1255,"config":1256},"Why Premium?",{"href":1257,"dataGaName":1258,"dataGaLocation":1231},"/pricing/premium/","why premium",{"text":1260,"config":1261},"Why Ultimate?",{"href":1262,"dataGaName":1263,"dataGaLocation":1231},"/pricing/ultimate/","why ultimate",[1265],{"title":1266,"links":1267},"Contact Us",[1268,1271,1273,1275,1280,1285,1290],{"text":1269,"config":1270},"Contact sales",{"href":1121,"dataGaName":800,"dataGaLocation":1231},{"text":1124,"config":1272},{"href":1126,"dataGaName":1127,"dataGaLocation":1231},{"text":1129,"config":1274},{"href":1131,"dataGaName":1132,"dataGaLocation":1231},{"text":1276,"config":1277},"Status",{"href":1278,"dataGaName":1279,"dataGaLocation":1231},"https://status.gitlab.com/","status",{"text":1281,"config":1282},"Terms of use",{"href":1283,"dataGaName":1284,"dataGaLocation":1231},"/terms/","terms of use",{"text":1286,"config":1287},"Privacy statement",{"href":1288,"dataGaName":1289,"dataGaLocation":1231},"/privacy/","privacy statement",{"text":1291,"config":1292},"Cookie preferences",{"dataGaName":1293,"dataGaLocation":1231,"id":1294,"isOneTrustButton":539},"cookie preferences","ot-sdk-btn",{"title":837,"links":1296,"subMenu":1305},[1297,1301],{"text":1298,"config":1299},"DevSecOps platform",{"href":819,"dataGaName":1300,"dataGaLocation":1231},"devsecops platform",{"text":1302,"config":1303},"AI-Assisted Development",{"href":826,"dataGaName":1304,"dataGaLocation":1231},"ai-assisted development",[1306],{"title":1307,"links":1308},"Topics",[1309,1314,1319,1324,1329,1334,1339,1344],{"text":1310,"config":1311},"CICD",{"href":1312,"dataGaName":1313,"dataGaLocation":1231},"/topics/ci-cd/","cicd",{"text":1315,"config":1316},"GitOps",{"href":1317,"dataGaName":1318,"dataGaLocation":1231},"/topics/gitops/","gitops",{"text":1320,"config":1321},"DevOps",{"href":1322,"dataGaName":1323,"dataGaLocation":1231},"/topics/devops/","devops",{"text":1325,"config":1326},"Version Control",{"href":1327,"dataGaName":1328,"dataGaLocation":1231},"/topics/version-control/","version control",{"text":1330,"config":1331},"DevSecOps",{"href":1332,"dataGaName":1333,"dataGaLocation":1231},"/topics/devsecops/","devsecops",{"text":1335,"config":1336},"Cloud Native",{"href":1337,"dataGaName":1338,"dataGaLocation":1231},"/topics/cloud-native/","cloud native",{"text":1340,"config":1341},"AI for Coding",{"href":1342,"dataGaName":1343,"dataGaLocation":1231},"/topics/devops/ai-for-coding/","ai for coding",{"text":1345,"config":1346},"Agentic AI",{"href":1347,"dataGaName":1348,"dataGaLocation":1231},"/topics/agentic-ai/","agentic ai",{"title":1350,"links":1351},"Solutions",[1352,1354,1356,1361,1365,1368,1372,1375,1377,1380,1383,1388],{"text":881,"config":1353},{"href":876,"dataGaName":881,"dataGaLocation":1231},{"text":870,"config":1355},{"href":853,"dataGaName":854,"dataGaLocation":1231},{"text":1357,"config":1358},"Agile development",{"href":1359,"dataGaName":1360,"dataGaLocation":1231},"/solutions/agile-delivery/","agile delivery",{"text":1362,"config":1363},"SCM",{"href":866,"dataGaName":1364,"dataGaLocation":1231},"source code management",{"text":1310,"config":1366},{"href":859,"dataGaName":1367,"dataGaLocation":1231},"continuous integration & delivery",{"text":1369,"config":1370},"Value stream management",{"href":909,"dataGaName":1371,"dataGaLocation":1231},"value stream management",{"text":1315,"config":1373},{"href":1374,"dataGaName":1318,"dataGaLocation":1231},"/solutions/gitops/",{"text":919,"config":1376},{"href":922,"dataGaName":923,"dataGaLocation":1231},{"text":1378,"config":1379},"Small business",{"href":928,"dataGaName":929,"dataGaLocation":1231},{"text":1381,"config":1382},"Public sector",{"href":934,"dataGaName":935,"dataGaLocation":1231},{"text":1384,"config":1385},"Education",{"href":1386,"dataGaName":1387,"dataGaLocation":1231},"/solutions/education/","education",{"text":1389,"config":1390},"Financial services",{"href":1391,"dataGaName":1392,"dataGaLocation":1231},"/solutions/finance/","financial services",{"title":942,"links":1394},[1395,1397,1399,1401,1404,1406,1409,1411,1413,1415,1417,1419,1421,1423],{"text":955,"config":1396},{"href":957,"dataGaName":958,"dataGaLocation":1231},{"text":960,"config":1398},{"href":962,"dataGaName":963,"dataGaLocation":1231},{"text":965,"config":1400},{"href":967,"dataGaName":968,"dataGaLocation":1231},{"text":970,"config":1402},{"href":972,"dataGaName":1403,"dataGaLocation":1231},"docs",{"text":993,"config":1405},{"href":995,"dataGaName":996,"dataGaLocation":1231},{"text":1407,"config":1408},"What's new",{"href":1053,"dataGaName":1054,"dataGaLocation":1231},{"text":988,"config":1410},{"href":990,"dataGaName":991,"dataGaLocation":1231},{"text":1007,"config":1412},{"href":1009,"dataGaName":1010,"dataGaLocation":1231},{"text":1015,"config":1414},{"href":1017,"dataGaName":1018,"dataGaLocation":1231},{"text":1020,"config":1416},{"href":1022,"dataGaName":1023,"dataGaLocation":1231},{"text":1025,"config":1418},{"href":1027,"dataGaName":1028,"dataGaLocation":1231},{"text":1030,"config":1420},{"href":1032,"dataGaName":1033,"dataGaLocation":1231},{"text":1035,"config":1422},{"href":1037,"dataGaName":1038,"dataGaLocation":1231},{"text":1040,"config":1424},{"href":1042,"dataGaName":1043,"dataGaLocation":1231},{"title":1056,"links":1426},[1427,1429,1431,1433,1435,1437,1441,1446,1448,1450,1452],{"text":1064,"config":1428},{"href":1066,"dataGaName":1058,"dataGaLocation":1231},{"text":1069,"config":1430},{"href":1071,"dataGaName":1072,"dataGaLocation":1231},{"text":1077,"config":1432},{"href":1079,"dataGaName":1080,"dataGaLocation":1231},{"text":1082,"config":1434},{"href":1084,"dataGaName":1085,"dataGaLocation":1231},{"text":1087,"config":1436},{"href":1089,"dataGaName":1090,"dataGaLocation":1231},{"text":1438,"config":1439},"Sustainability",{"href":1440,"dataGaName":1438,"dataGaLocation":1231},"/sustainability/",{"text":1442,"config":1443},"Diversity, inclusion and belonging (DIB)",{"href":1444,"dataGaName":1445,"dataGaLocation":1231},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1092,"config":1447},{"href":1094,"dataGaName":1095,"dataGaLocation":1231},{"text":1102,"config":1449},{"href":1104,"dataGaName":1105,"dataGaLocation":1231},{"text":1107,"config":1451},{"href":1109,"dataGaName":1110,"dataGaLocation":1231},{"text":1453,"config":1454},"Modern Slavery Transparency Statement",{"href":1455,"dataGaName":1456,"dataGaLocation":1231},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1458},[1459,1462,1465],{"text":1460,"config":1461},"Terms",{"href":1283,"dataGaName":1284,"dataGaLocation":1231},{"text":1463,"config":1464},"Cookies",{"dataGaName":1293,"dataGaLocation":1231,"id":1294,"isOneTrustButton":539},{"text":1466,"config":1467},"Privacy",{"href":1288,"dataGaName":1289,"dataGaLocation":1231},[1469],{"id":1470,"title":7,"body":771,"config":1471,"content":1473,"description":771,"extension":1477,"meta":1478,"navigation":539,"path":1479,"seo":1480,"stem":1481,"__hash__":1482},"blogAuthors/en-us/blog/authors/chris-moberly.yml",{"template":1472},"BlogAuthor",{"name":7,"config":1474},{"headshot":1475,"ctfId":1476},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664235/Blog/Author%20Headshots/cmoberly-headshot.jpg","cmoberly","yml",{},"/en-us/blog/authors/chris-moberly",{},"en-us/blog/authors/chris-moberly","v83w571hHQ-Pp6FRXLR8j4NJ3-1mcNhD7eif5Q962QY",[1484,1492,1500],{"title":1485,"description":1486,"heroImage":1487,"category":767,"date":1488,"authors":1489,"slug":1491,"externalUrl":771},"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",[1490],"Julian Thome","improved-scope-offset-fingerprinting",{"title":1493,"description":1494,"heroImage":1487,"category":767,"date":1495,"authors":1496,"slug":1499,"externalUrl":771},"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",[1497,1498],"Erick Bajao","Joe Randazzo","gitlab-secrets-manager-add-eso-terraform-api-support",{"title":1501,"description":1502,"heroImage":1503,"category":767,"date":1504,"authors":1505,"slug":1507,"externalUrl":771},"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",[1506],"Alisa Ho","claude-security-and-gitlab",{"promotions":1509},[1510,1524,1536,1547],{"id":1511,"categories":1512,"header":1514,"text":1515,"button":1516,"image":1521},"ai-modernization",[1513],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1517,"config":1518},"Get your AI maturity score",{"href":1519,"dataGaName":1520,"dataGaLocation":996},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1522},{"src":1523},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1525,"categories":1526,"header":1528,"text":1515,"button":1529,"image":1533},"devops-modernization",[1527,1333],"product","Are you just managing tools or shipping innovation?",{"text":1530,"config":1531},"Get your DevOps maturity score",{"href":1532,"dataGaName":1520,"dataGaLocation":996},"/assessments/devops-modernization-assessment/",{"config":1534},{"src":1535},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1537,"categories":1538,"header":1539,"text":1515,"button":1540,"image":1544},"security-modernization",[767],"Are you trading speed for security?",{"text":1541,"config":1542},"Get your security maturity score",{"href":1543,"dataGaName":1520,"dataGaLocation":996},"/assessments/security-modernization-assessment/",{"config":1545},{"src":1546},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1548,"paths":1549,"header":1552,"text":1553,"button":1554,"image":1559},"github-azure-migration",[1550,1551],"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":1555,"config":1556},"See how GitLab compares to GitHub",{"href":1557,"dataGaName":1558,"dataGaLocation":996},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1560},{"src":1535},{"header":1562,"blurb":1563,"button":1564,"secondaryButton":1569},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1565,"config":1566},"Get your free trial",{"href":1567,"dataGaName":795,"dataGaLocation":1568},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1269,"config":1570},{"href":1121,"dataGaName":800,"dataGaLocation":1568},1786803767351]