[{"data":1,"prerenderedAt":706},["ShallowReactive",2],{"/en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications/":3,"navigation-en-us":35,"banner-en-us":452,"footer-en-us":467,"Dennis Appelt":678,"next-steps-en-us":691},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":25,"_id":28,"_type":29,"title":30,"_source":31,"_file":32,"_stem":33,"_extension":34},"/en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"How to configure DAST full scans for complex web applications","Keep your DAST job within timeout limits and fine-tune job configurations for better results","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749679617/Blog/Hero%20Images/tuning-237454.jpg","https://about.gitlab.com/blog/how-to-configure-dast-full-scans-for-complex-web-applications","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to configure DAST full scans for complex web applications\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Dennis Appelt\"}],\n        \"datePublished\": \"2020-08-31\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Dennis Appelt","2020-08-31","\n\nShifting [Dynamic Application Security Testing](https://docs.gitlab.com/ee/user/application_security/dast/) (DAST) left can help to detect security vulnerabilities earlier in the software development lifecycle (SDLC). However, testing earlier and more often in the SDLC comes with its own set of challenges: an abundance of alerts from automated security tools and a high computational cost caused by frequent and long-running CI security jobs.\n\nIn this blog post, I’ll walk you through how we configured DAST for the internal pipeline that tests the GitLab web application. We’ll discuss some of the common challenges that you might encounter when testing large applications, such as: \n\n1. How to keep the duration of the DAST scan within an acceptable [job timeout](https://docs.gitlab.com/ee/ci/pipelines/settings.html#timeout): This matters because jobs that exceed timeouts will fail and no results will be displayed. We will review how to optimize scan duration by excluding low-risk parts of the application from being tested, by correctly seeding your application with test data, and by parallelizing the DAST job.\n\n2. How to get relevant results for your context: This is key – tuning job configurations to produce relevant results allows your engineers to focus on findings that matter and prevents [alert fatigue](https://en.wikipedia.org/wiki/Alarm_fatigue). In this area, we'll discuss criteria for identifing rules that are applicable to your application and we will explain how to disable irrelevant rules.\n\nThe discussed solutions are based on the DAST configuration that we use to test GitLab itself. If you are looking for inspiration on how to configure your own DAST jobs, feel free to take a look at our [configuration](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/dast.gitlab-ci.yml).\n\n## How to set up a simple DAST full scan\n\nKicking off a DAST full scan in GitLab CI is as easy as including the job template and setting a few variables in your `.gitlab-ci.yml` file:\n\n```yaml\ninclude:\n  - template: DAST.gitlab-ci.yml\n\nvariables:\n  DAST_WEBSITE: \"https://my-site.example\"\n  DAST_FULL_SCAN_ENABLED: \"true\"\n  DAST_AUTH_URL: \"https://my-site.example/signin\"\n  DAST_AUTH_USERNAME: “john”\n  DAST_AUTH_PASSWORD: “P@ssw0rd”\n```\nThe variable `DAST_WEBSITE` defines the target website tested by DAST. Setting `DAST_FULL_SCAN_ENABLED: true` instructs DAST to run a [full scan](https://www.zaproxy.org/docs/docker/full-scan/), which is more comprehensive than a [baseline scan](https://www.zaproxy.org/docs/docker/baseline-scan/) and potentially finds more vulnerabilities. There are also other config options that you likely want to define such as authentication-related options (`DAST_AUTH_*`) which are not discussed here. You can check out our DAST [user docs](https://docs.gitlab.com/ee/user/application_security/dast/#available-variables) for a refresher on these config options.\n\nWhen running a DAST full scan against a web application with many pages and input parameters, it is possible that the DAST job will not finish testing the application within the CI job timeout and fail. If this is the case for your DAST job, keep reading to learn about tweaking your job configuration to stay within the timeout.\n\n## How to optimize DAST scan duration\n\nIt is not uncommon that a DAST full scan can take 10 or more hours to complete testing in complex applications. To understand how we can reduce the scan duration, we need to take a closer look at how DAST works internally.\n\nDAST job execution is roughly separated into two phases: A spidering phase and a test execution phase. A DAST job starts with spidering, during which it will detect all pages a web application consists of and identify the input parameters on these pages. The spider recursively discovers all pages of an application by visiting the configured target URL (parameter `DAST_WEBSITE`) and by following all URLs found in the page source. These URLs are in turn also searched for URLs in their page source, any new URLs are followed and so on. In a DAST full scan, this procedure is typically repeated until all discovered URLs have been visited.\n\nIn the test execution phase, test rules are executed against the target application to find vulnerabilities. Most of the rules are executed for any of the discovered pages in the spidering phase, leading to a direct relation between the number of executed test cases and the number of discovered pages.\n\nSome rules check for specific CVEs such as [Heartbleed](https://www.zaproxy.org/docs/alerts/20015/) while others are only applicable to applications written in specific languages such as [Java](https://www.zaproxy.org/docs/alerts/90002/), [ASP.net](https://www.zaproxy.org/docs/alerts/10061/), and so on. A DAST full scan will, by default, execute all rules even if the target application’s tech stack is not affected by the vulnerability being tested for.\n\nTo summarize, you can use the following rule of thumb to estimate a DAST job’s scan duration: Number of Tested Pages **x** Number of Executed Rules. \n\nTo optimize scan duration, we will have to tweak these factors.\n\n### How to reduce the number of tested pages\n\nTo understand which pages of our application are tested we can refer to the job log. The URLs of all tested pages are listed like in the example below.\n\n```\n2020-08-01 00:25:34,454 The following 2903 URLs were scanned:\nGET https://gitlab-review.app\nGET https://gitlab-review.app/*/*.git\nGET https://gitlab-review.app/help\nGET https://gitlab.com/help/user/index.md\n...\n```\n\nBased on this information we can exclude low-risk pages from being tested. For example, for the GitLab web app we decided to [exclude](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/dast.gitlab-ci.yml#L30) any of the [help pages](https://gitlab.com/help). These pages are mostly static and the application code doesn’t process any user-controlled inputs, which rules out attack categories like SQL injection, XSS etc. Excluding these led to 899 URLs less being spidered and tested, reducing the scan duration significantly.\n\nTo exclude low-risk pages from being tested, you can use the environment variable [DAST_AUTH_EXCLUDE_URLS](https://docs.gitlab.com/ee/user/application_security/dast/#available-variables) as mapped out below:\n\n```yaml\nscript:\n  - 'export DAST_AUTH_EXCLUDE_URLS=\"https://gitlab-review.app/help/.*,https://gitlab-review.app/profile/two_factor_auth\"' \n```\n\n`DAST_AUTH_EXCLUDE_URLS` takes a comma-separated list of URLs to exclude. URLs can contain regular expressions, e.g. `https://gitlab-review.app/help/.*` will exclude any URL that starts with `https://gitlab-review.app/help/`.\n\n### How to populate your app with test data\n\nPopulating your application with test data is important because it allows DAST to discover and test all the functionality of your application. At the same time, you want to avoid adding redundant test data to your application, which would lead to DAST exercising the same code repeatedly.\n\nFor example, we can create multiple [projects](https://docs.gitlab.com/ee/user/project/) in a GitLab instance and each project will be accessible via a unique URL, e.g. `https://gitlab.example/awesome-project`, `https://gitlab.example/another-project`, etc. To DAST these look like unrelated pages and it will test each page separately. However, the application code that is processing requests to different projects is largely identical, leading to the same code being tested multiple times. This increases the scan duration and is unlikely to identify more vulnerabilities than testing only a single project would.\n\nIn every pipeline that runs DAST against GitLab, we spin up a fresh GitLab instance as a [review app](https://docs.gitlab.com/ee/ci/review_apps/) and populate it with the test data that we need for the DAST job. If you are looking for a similar solution, you might find the job that is [deploying the review app](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/review.gitlab-ci.yml#L53-83) and seeding it with [test data](https://gitlab.com/gitlab-org/gitlab/-/blob/8b1557c02fe5519ba952ea59c93b84912dd357b4/.gitlab/ci/review.gitlab-ci.yml#L83) interesting.\n\n### Identifying relevant rules for your DAST scan\n\nAs mentioned above, a DAST full scan runs, by default, all rules against any discovered page. Therefore, another way to reduce scan duration is to disable irrelevant rules or rules that you have determined are low-risk for your application context. To determine rule relevance, consider the following:\n\n- Does the rule apply to my web framework?\n- Does the rule apply to my web server?\n- Does the rule apply to my database server?\n- Does the type of vulnerability a rule tests for apply to my application?\n\nFor example, if your application is not built with Java, rules that test for [Java-specific vulnerabilities](https://www.zaproxy.org/docs/alerts/90002/) can be disabled. There are many rules that are specific to a web framework, server, or database being used like [Apache HTTP Server](https://www.zaproxy.org/docs/alerts/10053/), [ASP.NET](https://www.zaproxy.org/docs/alerts/10061/), [PostgreSQL](https://www.zaproxy.org/docs/alerts/40022/) etc. If in doubt around which rule(s) are applicable to which tech stack, you can find the information either in the [ZAP user docs](https://www.zaproxy.org/docs/alerts/) or directly in the [rule implementation](https://github.com/zaproxy/zap-extensions/blob/master/addOns/ascanrules/src/main/java/org/zaproxy/zap/extension/ascanrules/CodeInjectionScanRule.java#L86-L91):\n\n```java\npublic boolean targets(TechSet technologies) {\n    if (technologies.includes(Tech.ASP) || technologies.includes(Tech.PHP)) {\n        return true;\n    }\n    return false;\n}\n```\nNote: Most rules classes have a function `targets` that defines to which technologies a rule is applicable.\n\nAnother example of a rule that might not apply to your application is the [PII Disclosure](https://www.zaproxy.org/docs/alerts/10062/) rule if your application does not process any PII.\n\n### Excluding irrelevant rules\n\nThe execution time of individual rules varies substantially. To understand how much time a particular rule adds to the total scan duration and how much we could gain from disabling it, we turn again to the job log. Each rule prints its duration on completion, for example:\n\n```\n[zap.out] 3937350 [Thread-8] INFO org.parosproxy.paros.core.scanner.HostProcess - completed host/plugin https://gitlab-review.app | TestExternalRedirect in 2813.043s with 33151 message(s) sent and 0 alert\n```\n\nFrom this message we learn that rule `TestExternalRedirect` took 47 minutes to complete, hence disabling this rule reduces the scan duration by about 47 minutes.\n\nWe can disable individual rules with the environment variable `DAST_EXCLUDE_RULES`. Here is an example:\n\n```yaml\nvariables:\n  DAST_EXCLUDE_RULES=”41,42,43,10027,...,90019”\n```\n\n`DAST_EXCLUDE_RULES` takes a comma-separated list of rule ids. You can find the id of a particular rule in the summary printed to the job log:\n\n```\nPASS: External Redirect [20019]\n…\nSUMMARY - PASS: 106 | WARN: 2\n```\n\nWe can see from the log that rule External Redirect, which we found earlier to take 47 minutes, has rule id 20019. To disable this rule in addition to the rules from the previous example, we would need to add it to `DAST_EXCLUDE_RULES` like so: \n\n```yaml\nvariables:\n  DAST_EXCLUDE_RULES=”20019,41,42,43,10027,...,90019”\n```\n### Parallelizing DAST jobs to further reduce pipeline duration\n\nTo reduce the total duration of the pipeline that is running the DAST job, we can split up the rules that we want to execute into multiple DAST jobs and run the jobs in parallel. Below is an example that demonstrates how to split up the rules.\n\n```yaml\n# Any configuration that is shared between jobs goes here\n.dast-conf:\n  image:\n    name: \"registry.gitlab.com/gitlab-org/security-products/dast:1.22.1\"\n  services:\n  - name: \"gitlab/gitlab-ee:nightly\"\n    alias: gitlab\n  script:\n  - /analyze -t \"http://gitlab\"\n\n# First DAST job executing rules 6 to 10\ndast-1/2:\n  extends:\n  - .dast-conf\n  variables:\n    DAST_EXCLUDE_RULES: \"1,2,3,4,5\"\n\n# Second DAST job executing rules 1 to 5\ndast-2/2:\n  extends:\n  - .dast-conf\n  variables:\n    DAST_EXCLUDE_RULES: \"5,6,7,8,9\"\n```\n\nFor the sake of brevity, we assume in the example above that our DAST job runs rules with id 1 to 10. As described in the previous section, refer to the job log to find which rules were executed (we are working on printing a tidy [summary of executed rules](https://gitlab.com/gitlab-org/gitlab/-/issues/230893)). The example defines two DAST jobs `dast-1/2` and `dast-2/2`. `dast-1/2` is excluding rules 1 to 5 and, hence, executes rules 6 to 10. Vice versa, `dast-2/2` is excluding rules 6 to 10 and, hence, executes rules 1 to 5.\n\nFollowing the same pattern, you can split up the rules into as many jobs as necessary, keeping the rules executed in a job mutually exclusive with respect to all other jobs.\n\nNote that new releases of GitLab DAST may contain new rules, which will get executed if the rule ids are not manually added to `DAST_EXCLUDE_RULES`. In the example above, we pinned the version of the DAST image to a specific version using the `image` keyword. This allows us to review new releases manually and adjust `DAST_EXCLUDE_RULES` as necessary before upgrading to a new DAST version.\n\nWhen running multiple DAST jobs in parallel against the same target application, make sure that the application isn’t overloaded and becomes a bottleneck. If you observe connection timeouts in the DAST job logs, chances are your target site is overloaded. To mitigate this issue, consider spinning up additional instances of your target application and distribute the test load among the instances. GitLab CI offers, through the [`services`](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#what-is-a-service) keyword, a convenient way of creating a dedicated application instance for each DAST job. In the example above, we start a dedicated GitLab instance for each DAST job with:\n\n```yaml\n  services:\n  - name: \"gitlab/gitlab-ee:nightly\"\n    alias: gitlab\n```\n## Summary\n\nIn this blog post, we walked you through common challenges encountered when testing complex web applications with DAST and solutions that worked well for our internal projects at GitLab. \n\nAs we continue and broaden our use of DAST full scans within GitLab and our Security department, we’re excited to identify vulnerabilities in GitLab earlier in the SDLC and look forward to sharing interesting findings with the community. In addition, we take our lessons learned from setting up DAST full scans back to our engineering team to continue improving user experience. We also plan to explore additional dynamic testing techniques such as [fuzzing](https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/) to complement our DAST results.\n\nIs there a problem area that you’ve encountered or solution for fine-tuning DAST full scans we've missed that's worked well for you? We want to hear about it and would love your feedback below in the comments.\n\nCover image by [Pixabay](https://www.pexels.com/@pixabay) on [Pexels](https://www.pexels.com/photo/blur-bowed-stringed-instrument-classic-classical-237454/)\n{: .note}\n","security",[21,23,24],"security research","open source",{"slug":26,"featured":6,"template":27},"how-to-configure-dast-full-scans-for-complex-web-applications","BlogPost","content:en-us:blog:how-to-configure-dast-full-scans-for-complex-web-applications.yml","yaml","How To Configure Dast Full Scans For Complex Web Applications","content","en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications.yml","en-us/blog/how-to-configure-dast-full-scans-for-complex-web-applications","yml",{"_path":36,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":38,"_id":448,"_type":29,"title":449,"_source":31,"_file":450,"_stem":451,"_extension":34},"/shared/en-us/main-navigation","en-us",{"logo":39,"freeTrial":44,"sales":49,"login":54,"items":59,"search":389,"minimal":420,"duo":439},{"config":40},{"href":41,"dataGaName":42,"dataGaLocation":43},"/","gitlab logo","header",{"text":45,"config":46},"Get free trial",{"href":47,"dataGaName":48,"dataGaLocation":43},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":50,"config":51},"Talk to sales",{"href":52,"dataGaName":53,"dataGaLocation":43},"/sales/","sales",{"text":55,"config":56},"Sign in",{"href":57,"dataGaName":58,"dataGaLocation":43},"https://gitlab.com/users/sign_in/","sign in",[60,104,200,205,310,370],{"text":61,"config":62,"cards":64,"footer":87},"Platform",{"dataNavLevelOne":63},"platform",[65,71,79],{"title":61,"description":66,"link":67},"The most comprehensive AI-powered DevSecOps Platform",{"text":68,"config":69},"Explore our Platform",{"href":70,"dataGaName":63,"dataGaLocation":43},"/platform/",{"title":72,"description":73,"link":74},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":75,"config":76},"Meet GitLab Duo",{"href":77,"dataGaName":78,"dataGaLocation":43},"/gitlab-duo/","gitlab duo ai",{"title":80,"description":81,"link":82},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":83,"config":84},"Learn more",{"href":85,"dataGaName":86,"dataGaLocation":43},"/why-gitlab/","why gitlab",{"title":88,"items":89},"Get started with",[90,95,100],{"text":91,"config":92},"Platform Engineering",{"href":93,"dataGaName":94,"dataGaLocation":43},"/solutions/platform-engineering/","platform engineering",{"text":96,"config":97},"Developer Experience",{"href":98,"dataGaName":99,"dataGaLocation":43},"/developer-experience/","Developer experience",{"text":101,"config":102},"MLOps",{"href":103,"dataGaName":101,"dataGaLocation":43},"/topics/devops/the-role-of-ai-in-devops/",{"text":105,"left":106,"config":107,"link":109,"lists":113,"footer":182},"Product",true,{"dataNavLevelOne":108},"solutions",{"text":110,"config":111},"View all Solutions",{"href":112,"dataGaName":108,"dataGaLocation":43},"/solutions/",[114,139,161],{"title":115,"description":116,"link":117,"items":122},"Automation","CI/CD and automation to accelerate deployment",{"config":118},{"icon":119,"href":120,"dataGaName":121,"dataGaLocation":43},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[123,127,131,135],{"text":124,"config":125},"CI/CD",{"href":126,"dataGaLocation":43,"dataGaName":124},"/solutions/continuous-integration/",{"text":128,"config":129},"AI-Assisted Development",{"href":77,"dataGaLocation":43,"dataGaName":130},"AI assisted development",{"text":132,"config":133},"Source Code Management",{"href":134,"dataGaLocation":43,"dataGaName":132},"/solutions/source-code-management/",{"text":136,"config":137},"Automated Software Delivery",{"href":120,"dataGaLocation":43,"dataGaName":138},"Automated software delivery",{"title":140,"description":141,"link":142,"items":147},"Security","Deliver code faster without compromising security",{"config":143},{"href":144,"dataGaName":145,"dataGaLocation":43,"icon":146},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[148,151,156],{"text":149,"config":150},"Security & Compliance",{"href":144,"dataGaLocation":43,"dataGaName":149},{"text":152,"config":153},"Software Supply Chain Security",{"href":154,"dataGaLocation":43,"dataGaName":155},"/solutions/supply-chain/","Software supply chain security",{"text":157,"config":158},"Compliance & Governance",{"href":159,"dataGaLocation":43,"dataGaName":160},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":162,"link":163,"items":168},"Measurement",{"config":164},{"icon":165,"href":166,"dataGaName":167,"dataGaLocation":43},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[169,173,177],{"text":170,"config":171},"Visibility & Measurement",{"href":166,"dataGaLocation":43,"dataGaName":172},"Visibility and Measurement",{"text":174,"config":175},"Value Stream Management",{"href":176,"dataGaLocation":43,"dataGaName":174},"/solutions/value-stream-management/",{"text":178,"config":179},"Analytics & Insights",{"href":180,"dataGaLocation":43,"dataGaName":181},"/solutions/analytics-and-insights/","Analytics and insights",{"title":183,"items":184},"GitLab for",[185,190,195],{"text":186,"config":187},"Enterprise",{"href":188,"dataGaLocation":43,"dataGaName":189},"/enterprise/","enterprise",{"text":191,"config":192},"Small Business",{"href":193,"dataGaLocation":43,"dataGaName":194},"/small-business/","small business",{"text":196,"config":197},"Public Sector",{"href":198,"dataGaLocation":43,"dataGaName":199},"/solutions/public-sector/","public sector",{"text":201,"config":202},"Pricing",{"href":203,"dataGaName":204,"dataGaLocation":43,"dataNavLevelOne":204},"/pricing/","pricing",{"text":206,"config":207,"link":209,"lists":213,"feature":297},"Resources",{"dataNavLevelOne":208},"resources",{"text":210,"config":211},"View all resources",{"href":212,"dataGaName":208,"dataGaLocation":43},"/resources/",[214,247,269],{"title":215,"items":216},"Getting started",[217,222,227,232,237,242],{"text":218,"config":219},"Install",{"href":220,"dataGaName":221,"dataGaLocation":43},"/install/","install",{"text":223,"config":224},"Quick start guides",{"href":225,"dataGaName":226,"dataGaLocation":43},"/get-started/","quick setup checklists",{"text":228,"config":229},"Learn",{"href":230,"dataGaLocation":43,"dataGaName":231},"https://university.gitlab.com/","learn",{"text":233,"config":234},"Product documentation",{"href":235,"dataGaName":236,"dataGaLocation":43},"https://docs.gitlab.com/","product documentation",{"text":238,"config":239},"Best practice videos",{"href":240,"dataGaName":241,"dataGaLocation":43},"/getting-started-videos/","best practice videos",{"text":243,"config":244},"Integrations",{"href":245,"dataGaName":246,"dataGaLocation":43},"/integrations/","integrations",{"title":248,"items":249},"Discover",[250,255,259,264],{"text":251,"config":252},"Customer success stories",{"href":253,"dataGaName":254,"dataGaLocation":43},"/customers/","customer success stories",{"text":256,"config":257},"Blog",{"href":258,"dataGaName":5,"dataGaLocation":43},"/blog/",{"text":260,"config":261},"Remote",{"href":262,"dataGaName":263,"dataGaLocation":43},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":265,"config":266},"TeamOps",{"href":267,"dataGaName":268,"dataGaLocation":43},"/teamops/","teamops",{"title":270,"items":271},"Connect",[272,277,282,287,292],{"text":273,"config":274},"GitLab Services",{"href":275,"dataGaName":276,"dataGaLocation":43},"/services/","services",{"text":278,"config":279},"Community",{"href":280,"dataGaName":281,"dataGaLocation":43},"/community/","community",{"text":283,"config":284},"Forum",{"href":285,"dataGaName":286,"dataGaLocation":43},"https://forum.gitlab.com/","forum",{"text":288,"config":289},"Events",{"href":290,"dataGaName":291,"dataGaLocation":43},"/events/","events",{"text":293,"config":294},"Partners",{"href":295,"dataGaName":296,"dataGaLocation":43},"/partners/","partners",{"backgroundColor":298,"textColor":299,"text":300,"image":301,"link":305},"#2f2a6b","#fff","Insights for the future of software development",{"altText":302,"config":303},"the source promo card",{"src":304},"/images/navigation/the-source-promo-card.svg",{"text":306,"config":307},"Read the latest",{"href":308,"dataGaName":309,"dataGaLocation":43},"/the-source/","the source",{"text":311,"config":312,"lists":314},"Company",{"dataNavLevelOne":313},"company",[315],{"items":316},[317,322,328,330,335,340,345,350,355,360,365],{"text":318,"config":319},"About",{"href":320,"dataGaName":321,"dataGaLocation":43},"/company/","about",{"text":323,"config":324,"footerGa":327},"Jobs",{"href":325,"dataGaName":326,"dataGaLocation":43},"/jobs/","jobs",{"dataGaName":326},{"text":288,"config":329},{"href":290,"dataGaName":291,"dataGaLocation":43},{"text":331,"config":332},"Leadership",{"href":333,"dataGaName":334,"dataGaLocation":43},"/company/team/e-group/","leadership",{"text":336,"config":337},"Team",{"href":338,"dataGaName":339,"dataGaLocation":43},"/company/team/","team",{"text":341,"config":342},"Handbook",{"href":343,"dataGaName":344,"dataGaLocation":43},"https://handbook.gitlab.com/","handbook",{"text":346,"config":347},"Investor relations",{"href":348,"dataGaName":349,"dataGaLocation":43},"https://ir.gitlab.com/","investor relations",{"text":351,"config":352},"Trust Center",{"href":353,"dataGaName":354,"dataGaLocation":43},"/security/","trust center",{"text":356,"config":357},"AI Transparency Center",{"href":358,"dataGaName":359,"dataGaLocation":43},"/ai-transparency-center/","ai transparency center",{"text":361,"config":362},"Newsletter",{"href":363,"dataGaName":364,"dataGaLocation":43},"/company/contact/","newsletter",{"text":366,"config":367},"Press",{"href":368,"dataGaName":369,"dataGaLocation":43},"/press/","press",{"text":371,"config":372,"lists":373},"Contact us",{"dataNavLevelOne":313},[374],{"items":375},[376,379,384],{"text":50,"config":377},{"href":52,"dataGaName":378,"dataGaLocation":43},"talk to sales",{"text":380,"config":381},"Get help",{"href":382,"dataGaName":383,"dataGaLocation":43},"/support/","get help",{"text":385,"config":386},"Customer portal",{"href":387,"dataGaName":388,"dataGaLocation":43},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":390,"login":391,"suggestions":398},"Close",{"text":392,"link":393},"To search repositories and projects, login to",{"text":394,"config":395},"gitlab.com",{"href":57,"dataGaName":396,"dataGaLocation":397},"search login","search",{"text":399,"default":400},"Suggestions",[401,403,407,409,413,417],{"text":72,"config":402},{"href":77,"dataGaName":72,"dataGaLocation":397},{"text":404,"config":405},"Code Suggestions (AI)",{"href":406,"dataGaName":404,"dataGaLocation":397},"/solutions/code-suggestions/",{"text":124,"config":408},{"href":126,"dataGaName":124,"dataGaLocation":397},{"text":410,"config":411},"GitLab on AWS",{"href":412,"dataGaName":410,"dataGaLocation":397},"/partners/technology-partners/aws/",{"text":414,"config":415},"GitLab on Google Cloud",{"href":416,"dataGaName":414,"dataGaLocation":397},"/partners/technology-partners/google-cloud-platform/",{"text":418,"config":419},"Why GitLab?",{"href":85,"dataGaName":418,"dataGaLocation":397},{"freeTrial":421,"mobileIcon":426,"desktopIcon":431,"secondaryButton":434},{"text":422,"config":423},"Start free trial",{"href":424,"dataGaName":48,"dataGaLocation":425},"https://gitlab.com/-/trials/new/","nav",{"altText":427,"config":428},"Gitlab Icon",{"src":429,"dataGaName":430,"dataGaLocation":425},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":427,"config":432},{"src":433,"dataGaName":430,"dataGaLocation":425},"/images/brand/gitlab-logo-type.svg",{"text":435,"config":436},"Get Started",{"href":437,"dataGaName":438,"dataGaLocation":425},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":440,"mobileIcon":444,"desktopIcon":446},{"text":441,"config":442},"Learn more about GitLab Duo",{"href":77,"dataGaName":443,"dataGaLocation":425},"gitlab duo",{"altText":427,"config":445},{"src":429,"dataGaName":430,"dataGaLocation":425},{"altText":427,"config":447},{"src":433,"dataGaName":430,"dataGaLocation":425},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":453,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"title":454,"button":455,"image":459,"config":462,"_id":464,"_type":29,"_source":31,"_file":465,"_stem":466,"_extension":34},"/shared/en-us/banner","is now in public beta!",{"text":83,"config":456},{"href":457,"dataGaName":458,"dataGaLocation":43},"/gitlab-duo/agent-platform/","duo banner",{"config":460},{"src":461},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":463},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":468,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":469,"_id":674,"_type":29,"title":675,"_source":31,"_file":676,"_stem":677,"_extension":34},"/shared/en-us/main-footer",{"text":470,"source":471,"edit":477,"contribute":482,"config":487,"items":492,"minimal":666},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":472,"config":473},"View page source",{"href":474,"dataGaName":475,"dataGaLocation":476},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":478,"config":479},"Edit this page",{"href":480,"dataGaName":481,"dataGaLocation":476},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":483,"config":484},"Please contribute",{"href":485,"dataGaName":486,"dataGaLocation":476},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":488,"facebook":489,"youtube":490,"linkedin":491},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[493,516,573,602,636],{"title":61,"links":494,"subMenu":499},[495],{"text":496,"config":497},"DevSecOps platform",{"href":70,"dataGaName":498,"dataGaLocation":476},"devsecops platform",[500],{"title":201,"links":501},[502,506,511],{"text":503,"config":504},"View plans",{"href":203,"dataGaName":505,"dataGaLocation":476},"view plans",{"text":507,"config":508},"Why Premium?",{"href":509,"dataGaName":510,"dataGaLocation":476},"/pricing/premium/","why premium",{"text":512,"config":513},"Why Ultimate?",{"href":514,"dataGaName":515,"dataGaLocation":476},"/pricing/ultimate/","why ultimate",{"title":517,"links":518},"Solutions",[519,524,527,529,534,539,543,546,550,555,557,560,563,568],{"text":520,"config":521},"Digital transformation",{"href":522,"dataGaName":523,"dataGaLocation":476},"/topics/digital-transformation/","digital transformation",{"text":149,"config":525},{"href":144,"dataGaName":526,"dataGaLocation":476},"security & compliance",{"text":138,"config":528},{"href":120,"dataGaName":121,"dataGaLocation":476},{"text":530,"config":531},"Agile development",{"href":532,"dataGaName":533,"dataGaLocation":476},"/solutions/agile-delivery/","agile delivery",{"text":535,"config":536},"Cloud transformation",{"href":537,"dataGaName":538,"dataGaLocation":476},"/topics/cloud-native/","cloud transformation",{"text":540,"config":541},"SCM",{"href":134,"dataGaName":542,"dataGaLocation":476},"source code management",{"text":124,"config":544},{"href":126,"dataGaName":545,"dataGaLocation":476},"continuous integration & delivery",{"text":547,"config":548},"Value stream management",{"href":176,"dataGaName":549,"dataGaLocation":476},"value stream management",{"text":551,"config":552},"GitOps",{"href":553,"dataGaName":554,"dataGaLocation":476},"/solutions/gitops/","gitops",{"text":186,"config":556},{"href":188,"dataGaName":189,"dataGaLocation":476},{"text":558,"config":559},"Small business",{"href":193,"dataGaName":194,"dataGaLocation":476},{"text":561,"config":562},"Public sector",{"href":198,"dataGaName":199,"dataGaLocation":476},{"text":564,"config":565},"Education",{"href":566,"dataGaName":567,"dataGaLocation":476},"/solutions/education/","education",{"text":569,"config":570},"Financial services",{"href":571,"dataGaName":572,"dataGaLocation":476},"/solutions/finance/","financial services",{"title":206,"links":574},[575,577,579,581,584,586,588,590,592,594,596,598,600],{"text":218,"config":576},{"href":220,"dataGaName":221,"dataGaLocation":476},{"text":223,"config":578},{"href":225,"dataGaName":226,"dataGaLocation":476},{"text":228,"config":580},{"href":230,"dataGaName":231,"dataGaLocation":476},{"text":233,"config":582},{"href":235,"dataGaName":583,"dataGaLocation":476},"docs",{"text":256,"config":585},{"href":258,"dataGaName":5,"dataGaLocation":476},{"text":251,"config":587},{"href":253,"dataGaName":254,"dataGaLocation":476},{"text":260,"config":589},{"href":262,"dataGaName":263,"dataGaLocation":476},{"text":273,"config":591},{"href":275,"dataGaName":276,"dataGaLocation":476},{"text":265,"config":593},{"href":267,"dataGaName":268,"dataGaLocation":476},{"text":278,"config":595},{"href":280,"dataGaName":281,"dataGaLocation":476},{"text":283,"config":597},{"href":285,"dataGaName":286,"dataGaLocation":476},{"text":288,"config":599},{"href":290,"dataGaName":291,"dataGaLocation":476},{"text":293,"config":601},{"href":295,"dataGaName":296,"dataGaLocation":476},{"title":311,"links":603},[604,606,608,610,612,614,616,620,625,627,629,631],{"text":318,"config":605},{"href":320,"dataGaName":313,"dataGaLocation":476},{"text":323,"config":607},{"href":325,"dataGaName":326,"dataGaLocation":476},{"text":331,"config":609},{"href":333,"dataGaName":334,"dataGaLocation":476},{"text":336,"config":611},{"href":338,"dataGaName":339,"dataGaLocation":476},{"text":341,"config":613},{"href":343,"dataGaName":344,"dataGaLocation":476},{"text":346,"config":615},{"href":348,"dataGaName":349,"dataGaLocation":476},{"text":617,"config":618},"Sustainability",{"href":619,"dataGaName":617,"dataGaLocation":476},"/sustainability/",{"text":621,"config":622},"Diversity, inclusion and belonging (DIB)",{"href":623,"dataGaName":624,"dataGaLocation":476},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":351,"config":626},{"href":353,"dataGaName":354,"dataGaLocation":476},{"text":361,"config":628},{"href":363,"dataGaName":364,"dataGaLocation":476},{"text":366,"config":630},{"href":368,"dataGaName":369,"dataGaLocation":476},{"text":632,"config":633},"Modern Slavery Transparency Statement",{"href":634,"dataGaName":635,"dataGaLocation":476},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":637,"links":638},"Contact Us",[639,642,644,646,651,656,661],{"text":640,"config":641},"Contact an expert",{"href":52,"dataGaName":53,"dataGaLocation":476},{"text":380,"config":643},{"href":382,"dataGaName":383,"dataGaLocation":476},{"text":385,"config":645},{"href":387,"dataGaName":388,"dataGaLocation":476},{"text":647,"config":648},"Status",{"href":649,"dataGaName":650,"dataGaLocation":476},"https://status.gitlab.com/","status",{"text":652,"config":653},"Terms of use",{"href":654,"dataGaName":655,"dataGaLocation":476},"/terms/","terms of use",{"text":657,"config":658},"Privacy statement",{"href":659,"dataGaName":660,"dataGaLocation":476},"/privacy/","privacy statement",{"text":662,"config":663},"Cookie preferences",{"dataGaName":664,"dataGaLocation":476,"id":665,"isOneTrustButton":106},"cookie preferences","ot-sdk-btn",{"items":667},[668,670,672],{"text":652,"config":669},{"href":654,"dataGaName":655,"dataGaLocation":476},{"text":657,"config":671},{"href":659,"dataGaName":660,"dataGaLocation":476},{"text":662,"config":673},{"dataGaName":664,"dataGaLocation":476,"id":665,"isOneTrustButton":106},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[679],{"_path":680,"_dir":681,"_draft":6,"_partial":6,"_locale":7,"content":682,"config":686,"_id":688,"_type":29,"title":18,"_source":31,"_file":689,"_stem":690,"_extension":34},"/en-us/blog/authors/dennis-appelt","authors",{"name":18,"config":683},{"headshot":684,"ctfId":685},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749672032/Blog/Author%20Headshots/dappelt-headshot.jpg","dappelt",{"template":687},"BlogAuthor","content:en-us:blog:authors:dennis-appelt.yml","en-us/blog/authors/dennis-appelt.yml","en-us/blog/authors/dennis-appelt",{"_path":692,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"header":693,"eyebrow":694,"blurb":695,"button":696,"secondaryButton":700,"_id":702,"_type":29,"title":703,"_source":31,"_file":704,"_stem":705,"_extension":34},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":45,"config":697},{"href":698,"dataGaName":48,"dataGaLocation":699},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":50,"config":701},{"href":52,"dataGaName":53,"dataGaLocation":699},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1754424504105]