<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://about.gitlab.com/blog</id>
    <title>GitLab</title>
    <updated>2026-08-14T19:14:05.917Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <author>
        <name>The GitLab Team</name>
    </author>
    <link rel="alternate" href="https://about.gitlab.com/blog"/>
    <link rel="self" href="https://about.gitlab.com/atom.xml"/>
    <subtitle>GitLab Blog RSS feed</subtitle>
    <icon>https://about.gitlab.com/favicon.ico</icon>
    <rights>All rights reserved 2026</rights>
    <entry>
        <title type="html"><![CDATA[How I built a demo generator with GitLab Duo Agent Platform]]></title>
        <id>https://about.gitlab.com/blog/agentic-click-through-demo/</id>
        <link href="https://about.gitlab.com/blog/agentic-click-through-demo/"/>
        <updated>2026-08-13T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>A demo used to take me days to build — screenshots, narration, stitching it together in an external tool, chasing feedback — and every time the feature changed I&#39;d have to start over. A few months ago, I handed most of that to an agent in GitLab Duo Agent Platform.</p><p><a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a> is built for intelligent orchestration, running agentic workflows across the software development lifecycle, but it&#39;s flexible enough to take on repetitive work outside of development, too. When I pointed it at demo generation instead, it worked well enough that I think you should try the same thing with something on your own plate. I created this hands-on tutorial to help you get started. And one more thing: You don&#39;t need to be a developer to do this. We&#39;ve seen an increase in interest from non-engineering roles in using GitLab to run agentic workflows like this one. If that&#39;s you, follow along to get started.</p><p><strong>In this article:</strong></p><ul><li><a href="#why-click-through-demos-are-so-effective">Why click-through demos are so effective</a></li><li><a href="#the-evolution-from-vms-to-external-demo-tools-to-agents">The evolution: From VMs to external demo tools to agents</a></li><li><a href="#the-stages-to-create-a-demo">The stages to create a demo</a></li><li><a href="#how-the-demo-generator-works">How the demo generator works</a></li><li><a href="#demos-are-now-in-code">Demos are now in code</a></li><li><a href="#how-gitlab-duo-agent-platform-made-this-possible">How GitLab Duo Agent Platform made this possible</a></li><li><a href="#build-your-first-agent">Build your first agent</a></li></ul><blockquote><p>🎯 Try <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel=""><strong>GitLab Duo Agent Platform</strong></a> today!</p></blockquote><h2 id="why-click-through-demos-are-so-effective">Why click-through demos are so effective</h2><p>People connect faster when they see a feature in action rather than read about it. But live demos are hard: You need product access and enough familiarity to navigate confidently.</p><p>A click-through demo solves that. You take real actions yourself, guided by a short narrative at each step. Unlike video, it puts you in control of the pace. And unlike live access, which requires a real environment, it&#39;s just a link: free to share, reusable, and consistent every time.</p><p>Explore examples in the <a href="https://dap-demo-hub-dac14a.gitlab.io/" rel="">GitLab Demo Hub</a>.</p><p><img alt="A click-through demo, guiding the user step by step through a real product flow" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1783421764/x0oyszct1nuhzg7sxv0z.png" title="A click-through demo, guiding the user step by step through a real product flow" /></p><h2 id="the-evolution-from-vms-to-external-demo-tools-to-agents">The evolution: From VMs to external demo tools to agents</h2><p>Demos haven&#39;t always looked like this. Looking back over my career, here&#39;s how they have evolved:</p><ul><li><strong>VMs (2000s)</strong>: Shipped virtual machines pre-loaded with the product and demo content, later centralized on ESX servers.</li><li><strong>External tools (SaaS era)</strong>: Moved to vendor platforms with built-in analytics, but still manual to build and tied to their infrastructure.</li><li><strong>Agentic (now)</strong>: Agents can generate demos from a prompt, deployed on the same project that creates them, no vendor dependency.</li></ul><p>Each layer made demos more accessible; the agentic layer is what makes them sustainable.</p><h2 id="the-stages-to-create-a-demo">The stages to create a demo</h2><p>Creating a click-through demo involves these stages:</p><ol><li><strong>Learn the feature</strong>: Read docs, dig through issues and Slack, sync with product managers and engineers to really understand what you&#39;re showing, and mainly understand the problem it solves and the customer impact and value.</li><li><strong>Build the story</strong>: Build a real-world scenario that shows the customer impact — what problem this solves for them in their day-to-day work, and why it matters.</li><li><strong>Set up the environment</strong>: Create a project and generate realistic demo data that supports the story; for example, seeded vulnerabilities for a security dashboard, or data for meaningful charts.</li><li><strong>Capture the content</strong>: Take screenshots or record clips of the actual flow.</li><li><strong>Write the narrative</strong>: Craft content that guides someone through each step, based on the story and customer scenario you defined in Step 2.</li><li><strong>Build the demo</strong>: Work in an external tool to stitch everything together into a clickable walkthrough, add links to related assets, and define the call to action for each step.</li><li><strong>Review with stakeholders</strong>: Share a draft, collect feedback, iterate.</li><li><strong>Incorporate edits</strong>: Update the narrative, reorder steps, regenerate as needed.</li><li><strong>Publish</strong>: Push to GitLab Docs, Demo Hub, and any other target location.</li><li><strong>Announce</strong>: Share internally on Slack, embed in blog posts, post on social.</li></ol><p>Together, these steps can take days, and the moment something changes in the product, you have to start over from Step 3.</p><p>An agent can help with almost all of these steps: reading docs, scanning issues, pulling context from Slack, populating demo data in the project, and pulling out what matters most. It can&#39;t fully replace the human who decides what to create and reviews the results before they ship, but it can do a remarkable amount of the groundwork.</p><p>In <a href="https://gitlab.com/gitlab-da/projects/click-through-demo-generator-v-2" rel="">the agentic tool I built</a>, the Click-Through Demo Generator, I focused on automating Steps 1, 2, 5, 6, and 9: the ones with clear inputs, predictable outputs, and previously fully manual execution. The other steps can also be handled by specialized agents.</p><h2 id="how-the-demo-generator-works">How the demo generator works</h2><p>The agent works like this: Drop screenshots into a folder in the project, optionally with a <code>context.md</code> for background on the feature, and trigger the workflow from an issue comment. The agent reorders and renames the screenshots, writes the narration, builds the demo with a built-in branded template, and opens a merge request. Review it, and once you merge it, the demo auto-publishes to GitLab Pages. If something needs to change, ask the agent to update it.</p><p><img alt="The issue comment that triggers the Click-Through Demo Generator, and the agent&#39;s response with the merge request link" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1783431076/etfiomoplfb4soaeevig.png" title="The issue comment that triggers the Click-Through Demo Generator, and the agent&#39;s response with the merge request link" /></p><p>Under the hood, a Custom Flow gets triggered. The agent calls a custom tool I built to assemble the demo into an HTML template, overlaying each screenshot with its narration message box, and comments the merge request link back on the issue. A skill guides its writing so the narration follows GitLab&#39;s marketing messaging, focused on customer outcomes rather than our own features.</p><p>Here&#39;s the actual instruction text from that skill&#39;s <code>SKILL.md</code> that the agent reads and follows every time it writes narration:</p><blockquote><p><em>&quot;Great narration sells an outcome, not a UI tour. Someone who clicks through should understand what problem the product solves, why this approach is better, and what they could now do, without reading any docs.</em></p><p><em>Structure every demo as three acts: Open on the customer&#39;s pain, show the product solving it step by step, and close by naming the value they walk away with.&quot;</em></p></blockquote><p>For demos in more languages, we just need to add a localization skill to the project, and every demo gets automatically localized from then on.</p><p><img alt="The demo gallery" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1783431133/ljn4kvbwvdxpaafhzgvi.png" title="The demo gallery: where demos are reviewed and staged before going to production" /></p><h3 id="publishing-with-a-skill">Publishing with a skill</h3><p>Publishing to the <a href="https://dap-demo-hub-dac14a.gitlab.io/" rel="">Demo Hub</a>, our production demo portal, is just as hands-off as publishing the demo itself. When a demo is ready to ship, you tag it as <strong>production</strong> in the development gallery. That&#39;s the cue for the agent to run a skill in this project that reaches into the Demo Hub project and does the rest: It writes a short description, stamps it with today&#39;s date, tags it as new, and opens a merge request adding the demo as a card. Merging that MR, and putting the demo live, is still a human&#39;s call.</p><h2 id="demos-are-now-in-code">Demos are now in code</h2><p>A click-through demo is really just a set of files: HTML, screenshots, and config, which makes it a great fit to live in a repo. The demo is no longer trapped in a separate tool that only a few people know how to use. It lives in a GitLab project, which means it can be:</p><ul><li>Reviewed in merge requests</li><li>Improved by teammates</li><li>Versioned over time</li><li>Updated by agents, not just humans</li></ul><p>The demo becomes a team asset, not a one-person task. That&#39;s a big deal. More teammates can now create demos, review them, improve them, and publish them, without needing any special tool knowledge. If you can open an issue and approve an MR, you can use this workflow.</p><h3 id="want-to-try-it-yourself">Want to try it yourself?</h3><p>Fork the <a href="https://gitlab.com/gitlab-da/projects/click-through-demo-generator-v-2" rel="">Click-Through Demo Generator</a> project and read the README for the full setup. Custom Flows aren&#39;t copied over when you fork a project, so you&#39;ll also need to enable the <a href="https://gitlab.com/gitlab-da/projects/click-through-demo-generator-v-2/-/automate/flows/1010005/" rel="">Generate click-through demo flow</a> (you&#39;ll need to be logged in to GitLab to view it) in your forked project. From there, the README walks you through everything else.</p><h2 id="how-gitlab-duo-agent-platform-made-this-possible">How GitLab Duo Agent Platform made this possible</h2><p>This project would have been significantly harder without GitLab Duo Agent Platform.</p><p>GitLab Duo Agent Platform gave me the missing infrastructure: a Custom Flow that triggers from an issue comment, a container image I define with exactly the runtime and dependencies it needs, and built-in tools to work with GitLab directly, like opening merge requests and commenting on issues. The merge request is where I review the demo before merging it and letting the agent publish it to the Demo Hub.</p><p>In platform terms, this is agentic automation — the <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/custom/" rel="">Custom Flow</a> orchestrating the agent&#39;s behavior while GitLab’s built-in tools let it work with issues, project files, merge requests, and GitLab Pages without requiring separate integrations.</p><p>Custom Flows let you define your own multi-step workflow and extend the agent with custom tools, like the tool I built to assemble screenshots and narration into the demo&#39;s HTML template. You implement that capability yourself, and it runs as part of the flow, on GitLab&#39;s compute.</p><p>Everything happens inside GitLab: the request, the review, the output, the deployment. That&#39;s what makes the workflow faster, clearer, and easier to hand off.</p><h2 id="build-your-first-agent">Build your first agent</h2><p>Zoom out from my own workflow for a second and focus on what happens when repetitive work gets handed to an agent with access to your GitLab data. For a team lead, that&#39;s fewer cycles spent producing collateral and more spent reviewing and deciding. The same shift shows up anywhere a team has a repeatable, well-scoped task sitting on top of GitLab context.</p><p>Start small and simple. The demo generator is just one example of the pattern, but you don&#39;t need to write code or use a Custom Flow to get started. Start with a single agent, give it one clear job, and see what it can do before reaching for anything more complex.</p><p>In this quick tutorial, you&#39;ll build your first agent, one that helps you plan your work and saves you time. Don&#39;t have access to GitLab Duo Agent Platform? You can <a href="https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&amp;glm_content=default-saas-trial" rel="">start a free trial</a> to follow along. Two tasks, about 10 minutes total:</p><p><strong>Task 1: Create a custom agent.</strong> In the GitLab UI, <a href="https://docs.gitlab.com/user/duo_agent_platform/agents/custom/#create-an-agent" rel="">create a custom agent</a> called &quot;Daily Planner.&quot; Tell it what priority means to you — for example, issues blocking a teammate, anything due this week, or &quot;treat anything with the customer label as top priority regardless of due date.&quot; Have it look at your assigned issues and merge requests, apply those rules, and tell you what to tackle first, what&#39;s blocking others, and what can wait.</p><p><strong>Task 2: Enable it and review.</strong> <a href="https://docs.gitlab.com/user/duo_agent_platform/agents/custom/#enable-an-agent" rel="">Enable the agent</a> in your project, then open GitLab Duo Agentic Chat, select it, and ask it to plan your day. It has built-in access to GitLab, so it pulls your actual assigned issues and MRs itself. Compare its plan to what you&#39;d have figured out yourself, and adjust the agent&#39;s instructions until the plan is genuinely useful.</p><p>Congratulations, you just built your first agent, and it&#39;s already making your day a little easier. This is where it gets fun: Start thinking about what else you&#39;d hand it, another decision you&#39;re tired of making yourself. Keep going, and that single-purpose agent turns into the assistant that runs your whole workflow.</p>]]></content>
        <author>
            <name>Itzik Gan Baruch</name>
            <uri>https://about.gitlab.com/blog/authors/itzik-gan-baruch/</uri>
        </author>
        <published>2026-08-13T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[How GitLab tracks vulnerabilities through refactors and reformatting]]></title>
        <id>https://about.gitlab.com/blog/improved-scope-offset-fingerprinting/</id>
        <link href="https://about.gitlab.com/blog/improved-scope-offset-fingerprinting/"/>
        <updated>2026-08-12T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Every day, security scans face the same problem: an agent or a developer adds a comment, reformats a file, or moves a function, and a naive vulnerability tracker suddenly reports the same finding twice. Security teams end up re-triaging issues they already dismissed, which causes futile auditing effort and erodes trust in the scan results.</p><p>In 2022, we <a href="https://about.gitlab.com/blog/introducing-gitlab-advanced-vulnerability-tracking/" rel="">introduced advanced vulnerability tracking</a> to tackle exactly this problem of <em>code volatility</em>. It is based on our <em>Scope+Offset</em> fingerprinting method: instead of identifying a finding by file and line number, we identify it by its narrowest enclosing <em>scope</em> (module, class, function) plus its line <em>offset</em> within that scope. That made tracking robust against code moving around the file and reduced futile re-auditing by about 30% compared to line-based tracking.</p><p>But one class of edits still slipped through: <strong>non-functional changes</strong>. The offset counted every line between the scope boundary and the finding, including comments and blank lines. Add a comment above a vulnerable statement, and the offset shifts. The tracker sees a &quot;new&quot; vulnerability; you see a duplicate.</p><p>Our improved method addresses this by simply ignoring non-functional code (comments and blank lines) when computing the fingerprint. Since these lines do not affect the program&#39;s behavior, they should not affect the identity of a vulnerability either. With this normalization in place, adding a comment or reformatting a file no longer changes the fingerprint, while the precision of the tracking remains the same as before. The details of the approach are described in our accompanying research paper.</p><p>We evaluated the normalized method on a targeted benchmark: 439 source files across C/C++, C#, Go, Java, JavaScript, Python, and Ruby. We generated 2,247 commits, each inserting a single comment or blank line directly before a known vulnerability, and scanned the code as the history was replayed. The benchmark deliberately stresses the worst case: every commit is a non-functional edit right next to a finding.</p><p>On this benchmark, the original <em>Scope+Offset</em> method accumulated 1,361 duplicate fingerprints, a 77% growth over the baseline. The normalized method produced zero duplicates and reduced unique fingerprints by 43% overall.</p><p><em>Normalized Scope+Offset</em> ships in GitLab as the <code>scope_offset_compressed</code> tracking algorithm, supporting C#, C/C++, Go, Java, JavaScript, Python, Ruby, and PHP. It reuses the parse tree the scanner already constructs, so scan times are unaffected. The security report format is unchanged, so it composes with any combination of SAST tools in a heterogeneous setup.</p><p>The preprint of our study &quot;<a href="https://res.cloudinary.com/about-gitlab-com/image/upload/v1786457681/jm8oieyjhwut8ed2cpaq.pdf" rel="">Vulnerability Tracking using Normalized
Scope+Offset</a>&quot; by Julian Thome, Hua Yan, Lucas Charles,
Craig Smith, and Jason Leasure will be presented at the <a href="https://conf.researchr.org/track/ase-2026/ase-2026-industry-showcase" rel="">ASE 2026 Industry Showcase</a>.</p><p><em><a href="https://gitlab.com/hyan3" rel="">Hua Yan</a>, <a href="https://gitlab.com/theoretick" rel="">Lucas Charles</a>, <a href="https://gitlab.com/craigmsmith" rel="">Craig Smith</a>, and Jason Leasure contributed to this article and study.</em></p>]]></content>
        <author>
            <name>Julian Thome</name>
            <uri>https://about.gitlab.com/blog/authors/julian-thome/</uri>
        </author>
        <published>2026-08-12T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[GitLab Patch Release: 19.2.2, 19.1.4, 19.0.6]]></title>
        <id>https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-2-released/</id>
        <link href="https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-2-released/"/>
        <updated>2026-08-12T00:00:00.000Z</updated>
        <published>2026-08-12T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[A sandbox is only as closed as what an AI agent can reach]]></title>
        <id>https://about.gitlab.com/blog/ai-agent-sandbox/</id>
        <link href="https://about.gitlab.com/blog/ai-agent-sandbox/"/>
        <updated>2026-08-12T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>In July, OpenAI and Hugging Face responsibly disclosed an OpenAI model under internal evaluation escaped its sandbox, reached the open internet, and accessed Hugging Face’s internal production infrastructure. The agent took datasets, cluster details, and cloud keys during the intrusion.</p><p>The most critical part of the external phase of this incident was the first hour, when the agent escaped its sandbox by using a vulnerability within a package proxy on its sandbox’s allowlist to access the internet.</p><p>As more frontier model developers <a href="https://www.anthropic.com/news/investigating-incidents-cybersecurity-evals" rel="">disclose similar incidents</a>, the security industry needs to closely consider how agents impact reachability within test environments. You also do not have to run evaluation harnesses for this to be your problem. Any workload that executes code behind an egress list has the same structure: CI runners, hosted sandboxes, and network-reachable tool servers. Most of those allowlists were built to stop data leaving, but that is now not the only thing they need to stop.</p><h2 id="why-allowlists-extend-reachability">Why allowlists extend reachability</h2><p>When building an allowlist, you typically consider what a workload needs to contact and weigh each entry by what data could leave through it.</p><p>OpenAI’s agent revealed a blind spot for this typical process. The package proxy the agent accessed is a service: it authenticates callers, runs software with vulnerabilities, and talks to the public internet. While the sandbox could not reach the internet, the agent gained access to the package proxy, which did.</p><p>An allowlist hands your AI workload the reach of any destination it can take over.</p><h2 id="how-openais-model-escaped">How OpenAI’s model escaped</h2><p>To escape, OpenAI’s agent identified two zero-day vulnerabilities in the package proxy on its allowlist with a very large payoff.</p><p>The first flaw was a server-side request forgery flaw that let the agent ask the proxy to fetch arbitrary URLs on its behalf. In <a href="https://www.youtube.com/watch?v=87DyyMV0kCY&amp;t=721s" rel="">OpenAI&#39;s Black Hat presentation</a>, the model&#39;s reasoning at that moment reads &quot;<em>excellent, we have arbitrary SSRF</em>.&quot; The sandbox borrowed the proxy’s internet connection.</p><p>The second flaw was a privilege escalation. <a href="https://nvd.nist.gov/vuln/detail/CVE-2026-65616" rel="">CVE-2026-65616</a> (CVSS 8.8) causes a package proxy&#39;s refresh-token endpoint to issue new tokens without validating token signatures. These tokens carry their scope as a claim rather than the server looking it up, so once the signature goes unverified the claim is whatever the caller says.</p><p>In this case, the caller was the agent, which extended the access of its read-scoped token within the sandbox by editing its claim to administrative. It then submitted the token for refresh to the package proxy which returned an administrator-scoped token. As a result, the agent could act with administrator permission instead of its original read-only permission.</p><p>The agents worked as a group to break out. Together, they explored the one service they could reach until they found a way to make it fetch on their behalf, then shared the method so other agents could use it too. One agent noted that external exploitation was outside the scope of its instructions, but continued anyway.</p><p>Hugging Face and OpenAI also put the proxy compromise inside roughly the first half hour of the sandbox test despite the elusive nature of the vulnerabilities. Remember, these were  zero-days, so the agent could not reference a CVE or advisory. The package proxy is also closed-source, and its code was never in the agent’s training set.</p><h2 id="why-the-model-escaped">Why the model escaped</h2><p>We now know why the agent went after the proxy. It was stuck on its evaluation task, and OpenAI&#39;s presentation shows the model reasoning &quot;<em>perhaps answer online</em>&quot; before looking for a way out. Frontier models are rewarded for solving tasks quickly, so a stuck model looks for shortcuts, and OpenAI normally closes that one by disabling internet access.</p><p>There are still open questions about the agent&#39;s behavior, including everything the agent did during its four-day intrusion and what it did once it gained access to the internet. What we do know is that this agent revealed, in practical terms, that we must make some new considerations as we build test environments for security-capable, autonomous AI.</p><h2 id="how-to-reduce-risk-across-ai-test-environments">How to reduce risk across AI test environments</h2><p>If you’re building sandboxes for AI agents, here are four ways to reduce your risk and limit reachability:</p><ol><li><strong>Block the routes a build client never uses</strong>. A build client only downloads files. It has no reason to call the proxy&#39;s admin API, its configuration routes, or its token-refresh route, which swaps an expiring token for a new one and is the route that was abused in this incident.</li><li><strong>Restrict what the proxy itself can reach</strong>. The agent got out because the proxy could reach the whole internet, so anyone controlling the proxy could too. Limit the proxy’s outbound connections to the registries it actually serves.</li><li><strong>Monitor the proxy.</strong> A proxy serving a build-fleet is monotonous, with short connections, small downloads, and requests that mostly succeed. Consider alerting on anything that doesn’t follow that pattern, such as connections that stay open, data moving outward in bulk, a run of requests for packages that are not there, and any call to an admin route.</li><li><strong>Treat untrusted workloads as internet-facing.</strong> If an untrusted workload can reach an internal service, treat that service as internet-facing. Anything that compromises the workload can reach it too. We looked at the <a href="https://about.gitlab.com/blog/harden-pipeline-perimeter-for-ai-assisted-coding/" rel="">same question for CI runners earlier</a> this year, where the untrusted code runs in a pipeline rather than an agent sandbox.</li></ol><h2 id="cyber-capable-models-require-new-sandbox-considerations">Cyber-capable models require new sandbox considerations</h2><p>A sandbox is a list of things the workload inside it can talk to, and everything on that list brings its own reach with it. When a workload is a build job that doesn’t matter, but it does when agents widen that list in ways allowlist designs never anticipated.</p><p>Beyond evaluation harnesses, agentic workloads are also moving into CI, production automation, and into tooling that interacts with internal services. Each of those has a list with similar properties and structure. As models get better at finding and chaining flaws, the reach on those lists extends what agents can impact.</p><p>OpenAI observes that these agents remain &quot;bounded by the privileges they can obtain and the systems they can communicate with,&quot; so existing controls still work.<br />
What must change is how carefully we draw those lists to minimize reachability.</p><blockquote><p>Find more articles from the Threat Research team on our <a href="https://about.gitlab.com/blog/categories/security-labs/" rel="">Security Labs site</a>.</p></blockquote>]]></content>
        <author>
            <name>Daniel Abeles</name>
            <uri>https://about.gitlab.com/blog/authors/daniel-abeles/</uri>
        </author>
        <published>2026-08-12T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[GitLab Secrets Manager adds ESO, Terraform, API support]]></title>
        <id>https://about.gitlab.com/blog/gitlab-secrets-manager-add-eso-terraform-api-support/</id>
        <link href="https://about.gitlab.com/blog/gitlab-secrets-manager-add-eso-terraform-api-support/"/>
        <updated>2026-08-06T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Today, you might maintain separate secret stores for CI/CD, Kubernetes, and Terraform. However, that leaves multiple tools to manage, access models to keep in sync, and audit trails to correlate when something goes wrong.</p><p>GitLab Secrets Manager now supports External Secrets Operator (ESO) and Terraform, extending <a href="https://docs.gitlab.com/ci/secrets/secrets_manager/non_cicd_access/" rel="">secure secret retrieval beyond CI/CD pipelines</a>. Powered by OpenBao, GitLab Secrets Manager provides a single source of truth for secrets across your software delivery chain. You can now use the same secret store for:</p><ul><li>Kubernetes workloads via ESO</li><li>Terraform or OpenTofu Runs</li><li>OpenBao or Vault CLI</li><li>CI/CD Jobs in GitLab (as of Version 19.0)</li><li>Any external automation through the <a href="https://docs.gitlab.com/api/secrets_manager/" rel="">Secrets Manager API</a></li></ul><h3 id="kubernetes-external-secrets-operator">Kubernetes: External Secrets Operator</h3><p>ESO syncs secrets from GitLab Secrets Manager using the Vault provider. A workload in your cluster holds a short-lived JSON Web Token (JWT) that ESO uses to authenticate with OpenBao and writes the secret into a Kubernetes Secret.</p><p><img alt="External Secrets Operator" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785953823/ojlr4rv1r34oflo4fynv.png" /></p><p>A <a href="https://external-secrets.io/latest/api/secretstore/" rel="">SecretStore</a> tells ESO where to fetch secrets from and how to authenticate. GitLab Secrets Manager exposes a Vault-compatible KV v2 API and you configure it using the Vault provider. The namespace field maps to your GitLab hierarchy (organization, group, project) and scopes which secrets this store can reach. Authentication uses a GitLab-minted JWT held in a Kubernetes secret, referenced by secretRef.</p><pre className="language-text" code="apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: gitlab-secrets-manager
  namespace: my-app
spec:
  provider:
    vault:
      server: https://secrets.gitlab.com      # provider.vault.server
      path: secrets/kv                        # provider.vault.path
      version: v2
      namespace: org_5/group_42/project_99    # provider.vault.namespace
      auth:
        jwt:
          path: api_jwt/cel                   # provider.vault.auth.jwt.path
          role: all_api                       # provider.vault.auth.jwt.role
          secretRef:
            name: gitlab-access-token         # Kubernetes secret holding the minted token
            key: token
" language="text"><code>apiVersion: external-secrets.io/v1
kind: SecretStore
metadata:
  name: gitlab-secrets-manager
  namespace: my-app
spec:
  provider:
    vault:
      server: https://secrets.gitlab.com      # provider.vault.server
      path: secrets/kv                        # provider.vault.path
      version: v2
      namespace: org_5/group_42/project_99    # provider.vault.namespace
      auth:
        jwt:
          path: api_jwt/cel                   # provider.vault.auth.jwt.path
          role: all_api                       # provider.vault.auth.jwt.role
          secretRef:
            name: gitlab-access-token         # Kubernetes secret holding the minted token
            key: token
</code></pre><p>An <a href="https://external-secrets.io/latest/api/externalsecret/" rel="">ExternalSecret</a> defines which secrets to pull and where to put them. It references the SecretStore you created above, then maps remote secrets into a Kubernetes secret that your workloads can mount or reference as environment variables.</p><p>ESO creates and owns the target secret (synced-secret), re-fetching from GitLab every refreshInterval so rotated values propagate without a redeploy. Each entry under data maps one remote secret to one key in the target: remoteRef.key is the path in GitLab Secrets Manager, property selects a field within that secret, and secretKey is the key it lands under in Kubernetes.</p><pre className="language-text" code="apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: my-app
spec:
  refreshInterval: 45m
  secretStoreRef:
    name: gitlab-secrets-manager
    kind: SecretStore
  target:
    name: synced-secret
  data:
    - secretKey: value
      remoteRef:
        key: explicit/&lt;secret_name&gt;           # &lt;secrets_path&gt;/&lt;secret_name&gt;
        property: value
" language="text"><code>apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
  name: my-secret
  namespace: my-app
spec:
  refreshInterval: 45m
  secretStoreRef:
    name: gitlab-secrets-manager
    kind: SecretStore
  target:
    name: synced-secret
  data:
    - secretKey: value
      remoteRef:
        key: explicit/&lt;secret_name&gt;           # &lt;secrets_path&gt;/&lt;secret_name&gt;
        property: value
</code></pre><p>Check out the <a href="https://gitlab.com/guided-explorations/secrets-management/gitlab-secrets-manager-with-eso-and-k3s" rel="">tutorial</a> with GitLab Secrets Manager and ESO.</p><h3 id="infrastructure-as-code-terraform-and-opentofu">Infrastructure as code: Terraform and OpenTofu</h3><p>Terraform state and <code>.tfvars</code> files are a common source of leaked credentials because secrets end up written to disk or checked into version control by accident. Terraform can avoid that by reading a GitLab secret as a data source, authenticating with a minted JWT at plan or apply time. Reference credentials using Terraform directly where nothing gets stored in <code>.tfvars</code> files or CI/CD variables.</p><pre className="language-shell shiki shiki-themes github-light" code="data &quot;external&quot; &quot;gitlab_secrets_token&quot; {
  program = [&quot;bash&quot;, &quot;${path.module}/scripts/mint_token.sh&quot;]

  query = {
    project_id = var.gitlab_project_id
  }
}

provider &quot;vault&quot; {
  address   = data.external.gitlab_secrets_token.result.server
  namespace = data.external.gitlab_secrets_token.result.namespace

  auth_login_jwt {
    mount = data.external.gitlab_secrets_token.result.auth_path
    role  = data.external.gitlab_secrets_token.result.role
    jwt   = data.external.gitlab_secrets_token.result.jwt
  }
}

data &quot;vault_kv_secret_v2&quot; &quot;my_secret&quot; {
  mount = data.external.gitlab_secrets_token.result.mount
  name  = &quot;${data.external.gitlab_secrets_token.result.secrets_path}/&lt;secret_name&gt;&quot;
}

output &quot;secret_value&quot; {
  value     = data.vault_kv_secret_v2.my_secret.data[&quot;value&quot;]
  sensitive = true
}
" language="shell" meta="" style=""><code><span class="line" line="1"><span class="s7eDp">data</span><span class="sYBdl"> &quot;external&quot;</span><span class="sYBdl"> &quot;gitlab_secrets_token&quot;</span><span class="sYBdl"> {
</span></span><span class="line" line="2"><span class="s7eDp">  program</span><span class="sYBdl"> =</span><span class="sgsFI"> [</span><span class="sYBdl">&quot;bash&quot;</span><span class="sgsFI">, </span><span class="sYBdl">&quot;${</span><span class="sgsFI">path</span><span class="sYBdl">.</span><span class="sgsFI">module</span><span class="sYBdl">}/scripts/mint_token.sh&quot;]
</span></span><span class="line" line="3"><span emptyLinePlaceholder>
</span></span><span class="line" line="4"><span class="s7eDp">  query</span><span class="sYBdl"> =</span><span class="sYBdl"> {
</span></span><span class="line" line="5"><span class="s7eDp">    project_id</span><span class="sYBdl"> =</span><span class="sYBdl"> var.gitlab_project_id
</span></span><span class="line" line="6"><span class="sgsFI">  }
</span></span><span class="line" line="7"><span class="sgsFI">}
</span></span><span class="line" line="8"><span emptyLinePlaceholder>
</span></span><span class="line" line="9"><span class="s7eDp">provider</span><span class="sYBdl"> &quot;vault&quot;</span><span class="sYBdl"> {
</span></span><span class="line" line="10"><span class="s7eDp">  address</span><span class="sYBdl">   =</span><span class="sYBdl"> data.external.gitlab_secrets_token.result.server
</span></span><span class="line" line="11"><span class="s7eDp">  namespace</span><span class="sYBdl"> =</span><span class="sYBdl"> data.external.gitlab_secrets_token.result.namespace
</span></span><span class="line" line="12"><span emptyLinePlaceholder>
</span></span><span class="line" line="13"><span class="s7eDp">  auth_login_jwt</span><span class="sYBdl"> {
</span></span><span class="line" line="14"><span class="s7eDp">    mount</span><span class="sYBdl"> =</span><span class="sYBdl"> data.external.gitlab_secrets_token.result.auth_path
</span></span><span class="line" line="15"><span class="s7eDp">    role</span><span class="sYBdl">  =</span><span class="sYBdl"> data.external.gitlab_secrets_token.result.role
</span></span><span class="line" line="16"><span class="s7eDp">    jwt</span><span class="sYBdl">   =</span><span class="sYBdl"> data.external.gitlab_secrets_token.result.jwt
</span></span><span class="line" line="17"><span class="sgsFI">  }
</span></span><span class="line" line="18"><span class="sgsFI">}
</span></span><span class="line" line="19"><span emptyLinePlaceholder>
</span></span><span class="line" line="20"><span class="s7eDp">data</span><span class="sYBdl"> &quot;vault_kv_secret_v2&quot;</span><span class="sYBdl"> &quot;my_secret&quot;</span><span class="sYBdl"> {
</span></span><span class="line" line="21"><span class="s7eDp">  mount</span><span class="sYBdl"> =</span><span class="sYBdl"> data.external.gitlab_secrets_token.result.mount
</span></span><span class="line" line="22"><span class="s7eDp">  name</span><span class="sYBdl">  =</span><span class="sYBdl"> &quot;${</span><span class="sgsFI">data</span><span class="sYBdl">.</span><span class="sgsFI">external</span><span class="sYBdl">.</span><span class="sgsFI">gitlab_secrets_token</span><span class="sYBdl">.</span><span class="sgsFI">result</span><span class="sYBdl">.</span><span class="sgsFI">secrets_path</span><span class="sYBdl">}/&lt;secret_name&gt;&quot;
</span></span><span class="line" line="23"><span class="sgsFI">}
</span></span><span class="line" line="24"><span emptyLinePlaceholder>
</span></span><span class="line" line="25"><span class="s7eDp">output</span><span class="sYBdl"> &quot;secret_value&quot;</span><span class="sYBdl"> {
</span></span><span class="line" line="26"><span class="s7eDp">  value</span><span class="sYBdl">     =</span><span class="sYBdl"> data.vault_kv_secret_v2.my_secret.data[&quot;value&quot;]
</span></span><span class="line" line="27"><span class="s7eDp">  sensitive</span><span class="sYBdl"> =</span><span class="sYu0t"> true
</span></span><span class="line" line="28"><span class="sgsFI">}
</span></span></code></pre><p>Learn more about how to <a href="https://docs.gitlab.com/ci/secrets/secrets_manager/non_cicd_access/#use-with-terraform" rel="">read secrets in Terraform</a>.</p><h3 id="command-line-openbao-or-vault-cli">Command line: OpenBao or Vault CLI</h3><p>Not every workflow goes through the API directly. If your team already scripts against Vault-compatible tooling, the OpenBao or Vault CLI reads secrets from GitLab Secrets Manager the same way it reads from Vault.</p><pre className="language-shell shiki shiki-themes github-light" code="export VAULT_ADDR=&quot;&lt;server&gt;&quot;
export VAULT_NAMESPACE=&quot;&lt;namespace&gt;&quot;

# Exchange the minted JWT for an OpenBao token, then export it.
vault write &quot;auth/&lt;auth_jwt_path&gt;/login&quot; role=&lt;role&gt; jwt=&lt;token&gt;
export VAULT_TOKEN=&quot;&lt;client_token&gt;&quot;

# Read the secret value.
vault kv get -mount=&lt;path&gt; &quot;&lt;secrets_path&gt;/&lt;secret_name&gt;&quot;
" language="shell" meta="" style=""><code><span class="line" line="1"><span class="sD7c4">export</span><span class="sgsFI"> VAULT_ADDR</span><span class="sD7c4">=</span><span class="sYBdl">&quot;&lt;server&gt;&quot;
</span></span><span class="line" line="2"><span class="sD7c4">export</span><span class="sgsFI"> VAULT_NAMESPACE</span><span class="sD7c4">=</span><span class="sYBdl">&quot;&lt;namespace&gt;&quot;
</span></span><span class="line" line="3"><span emptyLinePlaceholder>
</span></span><span class="line" line="4"><span class="sAwPA"># Exchange the minted JWT for an OpenBao token, then export it.
</span></span><span class="line" line="5"><span class="s7eDp">vault</span><span class="sYBdl"> write</span><span class="sYBdl"> &quot;auth/&lt;auth_jwt_path&gt;/login&quot;</span><span class="sYBdl"> role=</span><span class="sD7c4">&lt;</span><span class="sYBdl">rol</span><span class="sgsFI">e</span><span class="sD7c4">&gt;</span><span class="sYBdl"> jwt=</span><span class="sD7c4">&lt;</span><span class="sYBdl">toke</span><span class="sgsFI">n</span><span class="sD7c4">&gt;
</span></span><span class="line" line="6"><span class="sD7c4">export</span><span class="sgsFI"> VAULT_TOKEN</span><span class="sD7c4">=</span><span class="sYBdl">&quot;&lt;client_token&gt;&quot;
</span></span><span class="line" line="7"><span emptyLinePlaceholder>
</span></span><span class="line" line="8"><span class="sAwPA"># Read the secret value.
</span></span><span class="line" line="9"><span class="s7eDp">vault</span><span class="sYBdl"> kv</span><span class="sYBdl"> get</span><span class="sYu0t"> -mount=</span><span class="sD7c4">&lt;</span><span class="sYu0t">path</span><span class="sD7c4">&gt;</span><span class="sYBdl"> &quot;&lt;secrets_path&gt;/&lt;secret_name&gt;&quot;
</span></span></code></pre><h3 id="when-to-use-the-secrets-manager-api">When to use the Secrets Manager API</h3><p>For automation that doesn&#39;t fit GitLab CI/CD, Kubernetes, or Terraform, the <a href="https://docs.gitlab.com/api/secrets_manager/" rel="">Secrets Manager API</a> lets any external system fetch secrets from the Secrets Manager, instead of hardcoding credentials or maintaining separate var files.</p><pre className="language-shell shiki shiki-themes github-light" code="# Request JWT token using Service Account
RESPONSE=$(curl --silent --request POST \
  --header &quot;PRIVATE-TOKEN: &lt;your_access_token&gt;&quot; \
  --url &quot;https://gitlab.example.com/api/v4/projects/&lt;project_id&gt;/secrets_manager/access_token&quot;)

SERVER=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.server)
NAMESPACE=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.namespace)
MOUNT=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.path)
SECRETS_PATH=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.secrets_path)
AUTH_PATH=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.auth.jwt.path)
ROLE=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.auth.jwt.role)
JWT=$(echo &quot;$RESPONSE&quot; | jq --raw-output .provider.vault.auth.jwt.token)

# Exchange the JWT for a short-lived OpenBao token.
VAULT_TOKEN=$(curl --silent --request POST \
  --header &quot;X-Vault-Namespace: $NAMESPACE&quot; \
  --data &quot;{\&quot;role\&quot;:\&quot;$ROLE\&quot;,\&quot;jwt\&quot;:\&quot;$JWT\&quot;}&quot; \
  &quot;$SERVER/v1/auth/$AUTH_PATH/login&quot; | jq --raw-output .auth.client_token)

# Read the secret value.
curl --silent \
  --header &quot;X-Vault-Token: $VAULT_TOKEN&quot; \
  --header &quot;X-Vault-Namespace: $NAMESPACE&quot; \
  &quot;$SERVER/v1/$MOUNT/data/$SECRETS_PATH/&lt;secret_name&gt;&quot;
" language="shell" meta="" style=""><code><span class="line" line="1"><span class="sAwPA"># Request JWT token using Service Account
</span></span><span class="line" line="2"><span class="sgsFI">RESPONSE</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="s7eDp">curl</span><span class="sYu0t"> --silent</span><span class="sYu0t"> --request</span><span class="sYBdl"> POST</span><span class="sYu0t"> \
</span></span><span class="line" line="3"><span class="sYu0t">  --header</span><span class="sYBdl"> &quot;PRIVATE-TOKEN: &lt;your_access_token&gt;&quot;</span><span class="sYu0t"> \
</span></span><span class="line" line="4"><span class="sYu0t">  --url</span><span class="sYBdl"> &quot;https://gitlab.example.com/api/v4/projects/&lt;project_id&gt;/secrets_manager/access_token&quot;</span><span class="sgsFI">)
</span></span><span class="line" line="5"><span emptyLinePlaceholder>
</span></span><span class="line" line="6"><span class="sgsFI">SERVER</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.server</span><span class="sgsFI">)
</span></span><span class="line" line="7"><span class="sgsFI">NAMESPACE</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.namespace</span><span class="sgsFI">)
</span></span><span class="line" line="8"><span class="sgsFI">MOUNT</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.path</span><span class="sgsFI">)
</span></span><span class="line" line="9"><span class="sgsFI">SECRETS_PATH</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.secrets_path</span><span class="sgsFI">)
</span></span><span class="line" line="10"><span class="sgsFI">AUTH_PATH</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.auth.jwt.path</span><span class="sgsFI">)
</span></span><span class="line" line="11"><span class="sgsFI">ROLE</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.auth.jwt.role</span><span class="sgsFI">)
</span></span><span class="line" line="12"><span class="sgsFI">JWT</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="sYu0t">echo</span><span class="sYBdl"> &quot;</span><span class="sgsFI">$RESPONSE</span><span class="sYBdl">&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .provider.vault.auth.jwt.token</span><span class="sgsFI">)
</span></span><span class="line" line="13"><span emptyLinePlaceholder>
</span></span><span class="line" line="14"><span class="sAwPA"># Exchange the JWT for a short-lived OpenBao token.
</span></span><span class="line" line="15"><span class="sgsFI">VAULT_TOKEN</span><span class="sD7c4">=</span><span class="sgsFI">$(</span><span class="s7eDp">curl</span><span class="sYu0t"> --silent</span><span class="sYu0t"> --request</span><span class="sYBdl"> POST</span><span class="sYu0t"> \
</span></span><span class="line" line="16"><span class="sYu0t">  --header</span><span class="sYBdl"> &quot;X-Vault-Namespace: </span><span class="sgsFI">$NAMESPACE</span><span class="sYBdl">&quot;</span><span class="sYu0t"> \
</span></span><span class="line" line="17"><span class="sYu0t">  --data</span><span class="sYBdl"> &quot;{</span><span class="sYu0t">\&quot;</span><span class="sYBdl">role</span><span class="sYu0t">\&quot;</span><span class="sYBdl">:</span><span class="sYu0t">\&quot;</span><span class="sgsFI">$ROLE</span><span class="sYu0t">\&quot;</span><span class="sYBdl">,</span><span class="sYu0t">\&quot;</span><span class="sYBdl">jwt</span><span class="sYu0t">\&quot;</span><span class="sYBdl">:</span><span class="sYu0t">\&quot;</span><span class="sgsFI">$JWT</span><span class="sYu0t">\&quot;</span><span class="sYBdl">}&quot;</span><span class="sYu0t"> \
</span></span><span class="line" line="18"><span class="sYBdl">  &quot;</span><span class="sgsFI">$SERVER</span><span class="sYBdl">/v1/auth/</span><span class="sgsFI">$AUTH_PATH</span><span class="sYBdl">/login&quot;</span><span class="sD7c4"> |</span><span class="s7eDp"> jq</span><span class="sYu0t"> --raw-output</span><span class="sYBdl"> .auth.client_token</span><span class="sgsFI">)
</span></span><span class="line" line="19"><span emptyLinePlaceholder>
</span></span><span class="line" line="20"><span class="sAwPA"># Read the secret value.
</span></span><span class="line" line="21"><span class="s7eDp">curl</span><span class="sYu0t"> --silent</span><span class="sYu0t"> \
</span></span><span class="line" line="22"><span class="sYu0t">  --header</span><span class="sYBdl"> &quot;X-Vault-Token: </span><span class="sgsFI">$VAULT_TOKEN</span><span class="sYBdl">&quot;</span><span class="sYu0t"> \
</span></span><span class="line" line="23"><span class="sYu0t">  --header</span><span class="sYBdl"> &quot;X-Vault-Namespace: </span><span class="sgsFI">$NAMESPACE</span><span class="sYBdl">&quot;</span><span class="sYu0t"> \
</span></span><span class="line" line="24"><span class="sYBdl">  &quot;</span><span class="sgsFI">$SERVER</span><span class="sYBdl">/v1/</span><span class="sgsFI">$MOUNT</span><span class="sYBdl">/data/</span><span class="sgsFI">$SECRETS_PATH</span><span class="sYBdl">/&lt;secret_name&gt;&quot;
</span></span></code></pre><h3 id="get-started">Get started</h3><p><a href="https://about.gitlab.com/blog/secrets-manager-in-public-beta/" rel="">GitLab Secrets Manager is in public beta</a> for Premium and Ultimate customers. Secret access using ESO, Terraform, or the API are currently available on GitLab.com and GitLab Self-Managed, with GitLab Dedicated coming soon.</p><p>Secrets Manager is free during the beta period. When generally available, it will be a paid feature billed through <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/" rel="">GitLab Credits</a>. You&#39;ll need to opt in before anything is charged, and we&#39;ll give you advance notice.</p><p><a href="https://docs.gitlab.com/ci/secrets/secrets_manager/non_cicd_access/" rel="">Read the documentation</a> to get started. If you find a gap or have a request, <a href="https://gitlab.com/gitlab-org/gitlab/-/work_items/598100" rel="">comment in this issue</a> — we&#39;re gathering feedback ahead of general availability.</p><style>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 .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}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 .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}</style>]]></content>
        <author>
            <name>Erick Bajao</name>
            <uri>https://about.gitlab.com/blog/authors/erick-bajao/</uri>
        </author>
        <author>
            <name>Joe Randazzo</name>
            <uri>https://about.gitlab.com/blog/authors/joe-randazzo/</uri>
        </author>
        <published>2026-08-06T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Confidential AI for GitLab Self-Hosted]]></title>
        <id>https://about.gitlab.com/blog/confidential-ai-for-gitlab-self-hosted/</id>
        <link href="https://about.gitlab.com/blog/confidential-ai-for-gitlab-self-hosted/"/>
        <updated>2026-08-06T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Your developers want AI coding agents. Your source code is regulated IP that can&#39;t be sent to a third-party AI service, and your compliance team has said so in writing. The usual escape hatch, standing up your own GPU cluster and running the models yourself, means buying scarce hardware, hiring a team to operate it, and still trailing the frontier models by months. So you do nothing, and your teams fall behind the ones that adopted AI a year ago.</p><p>GitLab Duo Self-Hosted can now use <a href="https://www.privatemode.ai/" rel="">Privatemode AI</a> as its model provider. Privatemode runs state-of-the-art models inside confidential-computing hardware, so prompts, source code, and completions stay encrypted end-to-end, including during inference. You point GitLab Duo&#39;s AI Gateway at the Privatemode proxy, and your developers get the same Duo features they&#39;d get from any model, with one difference that matters to a regulated organization: The code never leaves an encrypted boundary, and no third party can read it.</p><h2 id="the-productivity-most-regulated-teams-cant-touch">The productivity most regulated teams can&#39;t touch</h2><p>AI coding assistance has moved well past autocomplete. <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a> runs multi-step work: It reviews merge requests, refactors across files, generates and runs tests, drives agentic flows as CI jobs, and much more. That is a real shift in how teams ship, and it compounds. The teams using it review faster and spend less time on boilerplate.</p><p>The catch is that every one of those features sends your prompts and your source code to a model provider. For a team working on proprietary code, regulated software, or sensitive IP, that single fact is disqualifying.</p><h2 id="why-regulated-organizations-self-host">Why regulated organizations self-host</h2><p>For these organizations, source code is core intellectual property, and where it gets processed is a contractual, sectoral, and regulatory question, not a convenience one. A bank&#39;s trading algorithms, a medical-device vendor&#39;s firmware, a defense contractor&#39;s control software: Sending that intellectual property to an external AI service can breach IP protections, data-processing agreements, and sector rules in one step.</p><p>The pressure comes from several directions at once. NIS2 and Digital Operational Resilience Act (DORA) raise the bar on operational resilience and third-party risk across critical infrastructure and financial services. GDPR governs how personal data in code and logs is processed. Sector regimes such as BaFin supervision in German finance, BSI C5 as a procurement baseline, and healthcare data rules add their own constraints. And many European organizations treat data sovereignty as a first-order requirement regardless of any single regulation.</p><p>The segments feeling this most are financial services, healthcare and pharma, defense, the public sector, and critical infrastructure. GitLab Self-Hosted exists precisely so this code never has to leave a trusted perimeter. Adding AI to the workflow shouldn&#39;t quietly undo that.</p><h2 id="why-ai-makes-self-hosting-hard">Why AI makes self-hosting hard</h2><p>A self-hosted team that wants AI coding assistance has three conventional options, and each one has costs the regulated buyer can&#39;t easily pay.</p><table><thead><tr><th></th><th>Public AI SaaS</th><th>VPC / private-cloud AI</th><th>Run your own LLM stack</th></tr></thead><tbody><tr><td>Source code leaves your perimeter</td><td>Yes</td><td>Yes (to the operator)</td><td>No</td></tr><tr><td>Guarantee type</td><td>Contractual (terms of service)</td><td>Contractual (operator + cloud)</td><td>Self-enforced</td></tr><tr><td>Sees your plaintext</td><td>The provider</td><td>The operator and cloud provider</td><td>Only you</td></tr><tr><td>Infrastructure burden</td><td>None</td><td>Low</td><td>High: GPUs, model ops, updates</td></tr><tr><td>Keeps pace with frontier models</td><td>Yes</td><td>Usually</td><td>Rarely, you lag the frontier</td></tr></tbody></table><br /><p>The comparison table shows that public AI SaaS and VPC options expose code and rely on contractual guarantees, while running your own stack keeps code private but carries heavy GPU and model-operations burden.</p><p>The honest summary: Public SaaS is off the table because the code leaves the building. A VPC-isolated or private-cloud service reduces exposure but still hands plaintext to the operator and the underlying cloud provider. At the same time, a contract is a promise, but not a cryptographic guarantee. Running your own models keeps the code private but is expensive to buy, expensive to staff, and structurally behind the best available models. Faced with that, most regulated organizations adopt AI narrowly or not at all.</p><p>The question becomes: How do you give developers modern AI coding agents without source code leaving the perimeter, and without operating an LLM stack yourself? Answering it takes a different kind of guarantee than a contract can provide, one enforced by hardware.</p><h2 id="confidential-computing-the-architectural-answer">Confidential computing: The architectural answer</h2><p>Confidential computing keeps data encrypted <em>in memory</em>, while it&#39;s being processed, using a hardware-based trusted execution environment (TEE), an isolated region of a CPU or GPU that even the operating system, the hypervisor, and the machine&#39;s operator cannot read into. The relevant hardware here is AMD SEV or Intel TDX on the CPU side, paired with NVIDIA Confidential Computing on the GPU. Data is encrypted in transit and at rest with AES-256, and it&#39;s only ever decrypted <em>inside</em> the TEE.</p><p>The piece that turns this from a promise into a guarantee is <strong>remote attestation</strong>. Before a client sends any data, it asks the TEE to prove what it is: The hardware produces signed, cryptographic evidence of exactly what code is running inside the enclave. The client verifies that evidence against known-good values, and only then establishes the encrypted channel and sends its request. Verify first, send second.</p><p><img alt="Data-flow diagram" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1786033561/tjh50p5pliyu1oyftdtn.png" /></p><p>The data-flow diagram shows prompts encrypted at the client, transmitted as ciphertext, and decrypted only inside a hardware TEE that neither the service operator nor the cloud provider can read.</p><p>The security property that follows is the whole point: Neither the AI service operator nor the underlying cloud provider can see your prompts, your completions, or your context. Not because they promise not to look, but because the hardware won&#39;t let them.</p><h2 id="privatemode-ai">Privatemode AI</h2><p><a href="https://docs.privatemode.ai/" rel="">Privatemode AI</a> is built by <a href="https://edgeless.systems/" rel="">Edgeless Systems</a>, a Germany-based specialist in confidential-computing software. <a href="https://images.nvidia.com/aem-dam/Solutions/Data-Center/confidential-computing/hpc-solution-brief-edgeless-systems-3427281.pdf?ncid=no-ncid" rel="">According to NVIDIA</a>, Privatemode is the &quot;first gen AI framework that keeps prompts encrypted at all times.&quot;</p><p>For the developer, the mechanics are invisible. Privatemode exposes an OpenAI-compatible API, and a client-side proxy handles attestation and encryption transparently, so tools and SDKs that speak the standard <code>/v1</code> API work unchanged. The current flagship model for coding is Kimi K2.6 with 256K context, with others like Kimi K3 and GLM coming soon.</p><p>This isn&#39;t a lab experiment. Privatemode is already in production with organizations that have exactly the constraints described above. Capgemini uses it for regulated-industry clients, including confidential coding. The German Federal Employment Agency runs it in the public sector. And banks, insurers, and defense organizations use it where source code and data cannot leave a trusted boundary. Its cryptography is post-quantum-safe, which also defends against &quot;harvest now, decrypt later&quot; attacks. An adversary capturing today&#39;s ciphertext in the hope of decrypting it with tomorrow&#39;s hardware gets nothing usable.</p><h2 id="how-the-integration-works">How the integration works</h2><p>GitLab Duo Self-Hosted lets you serve Duo&#39;s AI features from a model you control instead of a GitLab-managed gateway. Privatemode slots in as that model.</p><p>The path is straightforward. GitLab Duo talks to a self-hosted <strong>AI Gateway</strong>, which forwards inference to any OpenAI-compatible endpoint. The Privatemode proxy <em>is</em> that endpoint: It exposes a standard <code>/v1</code> API and handles encryption and attestation against the Privatemode service. When a request comes through, the proxy encrypts it before it leaves your network, verifies the remote TEE through attestation, and only then forwards it. Decryption happens exclusively inside the confidential-computing environment. Inside Duo, across Code Suggestions, Chat, Code Review, and agentic flows, the developer experience is unchanged.</p><pre className="language-mermaid shiki shiki-themes github-light" code="sequenceDiagram
    autonumber
    actor Dev as Developer /&lt;br&gt;Duo Agent Platform
    participant GW as Self-hosted GitLab&lt;br&gt;AI Gateway
    participant Proxy as Privatemode&lt;br&gt;Proxy
    participant TEE as Remote TEE&lt;br&gt;(CPU + GPU)

    Dev-&gt;&gt;GW: Inference request (Code&lt;br&gt;Suggestions, Chat,&lt;br&gt;Code Review, flows)
    GW-&gt;&gt;Proxy: Forward request&lt;br&gt;to OpenAI-compatible&lt;br&gt;endpoint

    rect rgb(255, 244, 214)
        Note over Proxy,TEE: Attestation before any code is sent
        Proxy-&gt;&gt;TEE: Request attestation evidence
        TEE--&gt;&gt;Proxy: Signed evidence of enclave code
        Proxy-&gt;&gt;Proxy: Verify evidence against known-good values
        Proxy-&gt;&gt;TEE: Establish encrypted channel (AES-256, post-quantum-safe)
    end

    Proxy-&gt;&gt;TEE: Forward encrypted request
    Note over TEE: Decryption + inference&lt;br&gt;happen only inside the enclave
    TEE--&gt;&gt;Proxy: Encrypted response
    Proxy--&gt;&gt;GW: Encrypted response
    GW--&gt;&gt;Dev: Completion (developer&lt;br&gt;experience unchanged)
" language="mermaid" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">sequenceDiagram
</span></span><span class="line" line="2"><span class="sgsFI">    autonumber
</span></span><span class="line" line="3"><span class="sgsFI">    actor Dev as Developer /&lt;br&gt;Duo Agent Platform
</span></span><span class="line" line="4"><span class="sgsFI">    participant GW as Self-hosted GitLab&lt;br&gt;AI Gateway
</span></span><span class="line" line="5"><span class="sgsFI">    participant Proxy as Privatemode&lt;br&gt;Proxy
</span></span><span class="line" line="6"><span class="sgsFI">    participant TEE as Remote TEE&lt;br&gt;(CPU + GPU)
</span></span><span class="line" line="7"><span emptyLinePlaceholder>
</span></span><span class="line" line="8"><span class="sgsFI">    Dev-&gt;&gt;GW: Inference request (Code&lt;br&gt;Suggestions, Chat,&lt;br&gt;Code Review, flows)
</span></span><span class="line" line="9"><span class="sgsFI">    GW-&gt;&gt;Proxy: Forward request&lt;br&gt;to OpenAI-compatible&lt;br&gt;endpoint
</span></span><span class="line" line="10"><span emptyLinePlaceholder>
</span></span><span class="line" line="11"><span class="sgsFI">    rect rgb(255, 244, 214)
</span></span><span class="line" line="12"><span class="sgsFI">        Note over Proxy,TEE: Attestation before any code is sent
</span></span><span class="line" line="13"><span class="sgsFI">        Proxy-&gt;&gt;TEE: Request attestation evidence
</span></span><span class="line" line="14"><span class="sgsFI">        TEE--&gt;&gt;Proxy: Signed evidence of enclave code
</span></span><span class="line" line="15"><span class="sgsFI">        Proxy-&gt;&gt;Proxy: Verify evidence against known-good values
</span></span><span class="line" line="16"><span class="sgsFI">        Proxy-&gt;&gt;TEE: Establish encrypted channel (AES-256, post-quantum-safe)
</span></span><span class="line" line="17"><span class="sgsFI">    end
</span></span><span class="line" line="18"><span emptyLinePlaceholder>
</span></span><span class="line" line="19"><span class="sgsFI">    Proxy-&gt;&gt;TEE: Forward encrypted request
</span></span><span class="line" line="20"><span class="sgsFI">    Note over TEE: Decryption + inference&lt;br&gt;happen only inside the enclave
</span></span><span class="line" line="21"><span class="sgsFI">    TEE--&gt;&gt;Proxy: Encrypted response
</span></span><span class="line" line="22"><span class="sgsFI">    Proxy--&gt;&gt;GW: Encrypted response
</span></span><span class="line" line="23"><span class="sgsFI">    GW--&gt;&gt;Dev: Completion (developer&lt;br&gt;experience unchanged)
</span></span></code></pre><br /><p>In the sequence diagram, a GitLab Duo request flows through the self-hosted AI Gateway to the Privatemode proxy, which attests the remote enclave and establishes an encrypted channel before forwarding the request for inference inside the trusted execution environment.
You run the AI Gateway and the proxy yourself, and the setup is deployment-agnostic (Linux package, Docker, or Kubernetes). The steps are documented and version-specific, so rather than reproduce them here, see <a href="https://www.privatemode.ai/coding-tool/gitlab-duo" rel="">Privatemode&#39;s GitLab Duo integration guide</a>.</p><h2 id="the-tradeoffs">The tradeoffs</h2><p>No architecture is free, and a technical reader deserves the costs stated plainly.</p><p><strong>You operate the gateway and the proxy.</strong> This is real infrastructure work: deploying the AI Gateway at a proper hostname, matching its image version to your GitLab release on every upgrade, configuring JWT keys and certificates, and keeping the proxy reachable. It is ordinary infrastructure operation, though, not GPU procurement and not model operations. That distinction is the point. The alternative that keeps code private, running your own LLM stack, means buying scarce GPUs and staffing a team to run and update models while lagging the frontier. Privatemode is a hosted SaaS that carries the model operations for you, and the burden you keep is a proxy and a gateway.</p><p><strong>Generic OpenAI-compatible models are still maturing</strong> in GitLab Duo Self-Hosted. Today, they run as a beta feature, so support for model-specific issues isn&#39;t yet guaranteed. It&#39;s on the roadmap to harden, but if you need a fully supported configuration now, factor that timeline into your rollout.</p><p><strong>Attestation and encryption add some overhead.</strong> The extra roundtrip and cryptographic work cost time per request. In our testing, this hasn&#39;t been a practical problem, but the integration guide does recommend raising the AI Gateway timeout for slower self-hosted backends, so it&#39;s worth measuring against your own latency budget.</p><p><strong>You still trust something, but something bounded.</strong> The guarantee rests on the hardware TEE and the attestation chain being sound. That&#39;s a smaller, more inspectable trust assumption than &quot;trust the operator not to look,&quot; and you can verify the attestation evidence yourself, but it isn&#39;t zero. Confidential computing narrows trust to the silicon. It doesn&#39;t eliminate it.</p><h2 id="what-this-means-in-practice">What this means in practice</h2><ul><li><strong>For regulated organizations:</strong> a path to modern AI coding agents that fits existing IP- and data-protection policy, because the code stays inside a hardware-encrypted boundary, and without buying GPUs or standing up model operations.</li><li><strong>For developers:</strong> the same GitLab Duo experience, the same or better models, and no new tooling. Because model selection lives on the instance, in-editor Chat and Code Suggestions through the GitLab Workflow extension inherit the same confidential setup.</li><li><strong>For compliance and security teams:</strong> the architecture aligns with the direction of BSI C5:2026 toward confidential computing and remote attestation, and it gives you concrete technical evidence, namely data encrypted in use and attested execution, to bring to NIS2, DORA, and GDPR conversations. It doesn&#39;t make you compliant on its own, because compliance is organizational and ongoing. It removes the &quot;our code would leave the perimeter&quot; objection that blocks AI adoption in the first place.</li></ul><h2 id="get-started-with-privatemode">Get started with Privatemode</h2><p>Privatemode as a GitLab Duo self-hosted model provider requires GitLab Self-Managed, Premium, or Ultimate, Version 17.9 or later, with the GitLab Duo Enterprise add-on. Agentic flows additionally need the GitLab Duo Agent Platform (generally available on Version 18.8+). Usage consumes GitLab credits under the bring-your-own-model rules and multipliers described in the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/" rel="">GitLab credits documentation</a>.</p><h2 id="read-more">Read more</h2><ul><li><a href="https://docs.privatemode.ai/" rel="">Privatemode documentation</a></li><li><a href="https://www.privatemode.ai/coding-tool/gitlab-duo" rel="">GitLab Duo integration guide</a></li><li><a href="https://docs.privatemode.ai/guides/coding-assistants/" rel="">Coding assistants guide</a></li><li><a href="https://www.privatemode.ai/case-studies/capgemini-case-study" rel="">Capgemini case study</a></li><li><a href="https://images.nvidia.com/aem-dam/Solutions/Data-Center/confidential-computing/hpc-solution-brief-edgeless-systems-3427281.pdf?ncid=no-ncid" rel="">NVIDIA solution brief</a></li></ul><style>html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}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);}</style>]]></content>
        <author>
            <name>Mathias Ewald</name>
            <uri>https://about.gitlab.com/blog/authors/mathias-ewald/</uri>
        </author>
        <author>
            <name>Martin Paloncy, Edgeless Systems</name>
            <uri>https://about.gitlab.com/blog/authors/martin-paloncy-edgeless-systems/</uri>
        </author>
        <published>2026-08-06T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Secure every commit to production with Claude and GitLab]]></title>
        <id>https://about.gitlab.com/blog/claude-security-and-gitlab/</id>
        <link href="https://about.gitlab.com/blog/claude-security-and-gitlab/"/>
        <updated>2026-08-03T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Agentic coding is moving faster than many enterprise governance programs can keep up with. Coding assistants, like the <a href="https://code.claude.com/docs/en/security-guidance" rel="">Claude security guidance plugin</a> and <a href="https://code.claude.com/docs/en/claude-security" rel="">Claude Security</a>, can flag and fix common vulnerabilities in code as it&#39;s written, in the same session. This is valuable for writing more secure code, but security doesn&#39;t stop there. A commit is one stage in the path to production: Merges, dependency updates, infrastructure changes, and audits happen after the session ends.</p><p>GitLab covers securing the remainder of the path to production. There are five handoffs in the typical Anthropic Claude-to-GitLab security workflow. This article walks through each one to illustrate how to govern agentic coding at scale.</p><p>Teams already using Claude security guidance and Claude Security can plug that context directly into GitLab through the <a href="https://docs.gitlab.com/user/model_context_protocol/mcp_server/" rel="">GitLab MCP server</a> and keep their existing workflow. Claude handles the moment of authoring; GitLab handles everything from there through production, on one platform.</p><h2 id="from-flagged-to-enforced-controls">From flagged to enforced controls</h2><p>The Claude security guidance plugin reviews code within a single developer&#39;s session, catching issues fast enough to keep an agent moving. Once that code leaves a session, security teams need a record of what happened inside it and controls over what happens next.</p><p>GitLab gives teams the visibility and the control to define guardrails for secure coding, before code reaches production, no matter where the code originated.</p><ul><li><strong>Define controls once, enforce scale.</strong> <a href="https://docs.gitlab.com/user/application_security/configuration/security_configuration_profiles/" rel="">Security configuration profiles</a> apply the scans you require across every project and pipeline from outside the repository, so coverage is consistent and can&#39;t be bypassed.</li><li><strong>Enforce separation of duties, even for agents.</strong> <a href="https://docs.gitlab.com/user/application_security/policies/merge_request_approval_policies/" rel="">Merge request approval policies</a> ensure that the agent that wrote a change can&#39;t approve it. An agent, or the developer who prompted it, can&#39;t merge its own work without a designated approver.</li><li><strong>Block critical vulnerabilities before they ship.</strong> Merge request approval policies hold any merge with unresolved critical findings until a named approver signs off, so dismissed or missed vulnerabilities can&#39;t reach production quietly.</li><li><strong>Track every finding&#39;s status, permanently.</strong> The <a href="https://docs.gitlab.com/user/application_security/vulnerability_report/" rel="">Vulnerability report</a> and <a href="https://docs.gitlab.com/user/application_security/security_dashboard/" rel="">Security dashboard</a> show whether each finding was detected, dismissed with a reason, or resolved.</li></ul><p><img alt="Enable scanners across every in-scope project at scale, with no way to bypass them" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785525382/b29bi5eu71wuowipzskr.png" title="Enable scanners across every in-scope project at scale, with no way to bypass them" /></p><h2 id="from-scanned-in-session-to-audit-evidence">From scanned in session to audit evidence</h2><p>Change management audit requirements are expanding to include agents. Compliance frameworks such as SOC 2, PCI DSS, and FedRAMP require documented evidence that every change was tested, reviewed, and approved before it shipped.</p><p>GitLab makes compliance controls enforceable and evidence collection automatic for auditors:</p><ul><li><strong>Prove the scan ran and review.</strong> <a href="https://docs.gitlab.com/user/compliance/compliance_frameworks/#gitlab-compliance-controls" rel="">Compliance controls</a> guarantee a scan runs on every merge request, and every finding surfaces in the merge request and vulnerability report, visible to a human.</li><li><strong>Answer auditors in minutes.</strong> <a href="https://docs.gitlab.com/ci/jobs/job_logs/" rel="">Pipeline logs</a>, <a href="https://docs.gitlab.com/user/project/merge_requests/approvals/" rel="">approval records</a>, and <a href="https://docs.gitlab.com/user/compliance/audit_events/" rel="">audit events</a> give you reproducible history of what was scanned and who approved it, change by change, tied to the people and agents involved.</li><li><strong>Map evidence to the framework your auditor requests.</strong> <a href="https://docs.gitlab.com/user/compliance/compliance_frameworks/#gitlab-compliance-controls" rel="">Compliance frameworks</a> group evidence into named requirements, such as SOC 2 or a custom framework, each built from specific controls, and the <a href="https://docs.gitlab.com/user/compliance/compliance_center/compliance_status_report/" rel="">compliance status report</a> shows which controls passed, are pending, or failed, per framework.</li></ul><p><img alt="Audit log of agent activity, showing session-level events and start times" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785525382/xehdn27jhyv1tb0agrjt.png" title="Audit log of agent activity, showing session-level events and start times" /></p><h2 id="control-what-sensitive-data-is-sent">Control what sensitive data is sent</h2><p>You probably send more of your code, and the business context around it, to a model for review than you do a person. Regulated, government, and IP-sensitive teams need to decide what leaves their environment, such as credentials, proprietary logic, and regulated data. That decision has to happen before any scan runs, and across every tool that touches their code.</p><p>With GitLab, you decide what data reaches a model before it ever leaves your environment:</p><ul><li><strong>Keep secrets and sensitive code out of what you send to a model.</strong> <a href="https://docs.gitlab.com/user/duo_agent_platform/context/" rel="">Context exclusions</a> hold secrets and sensitive files back from everything an agent sends to models.</li><li><strong>Keep code and inference inside your boundary, on models you approve.</strong> Run a self-managed environment with self-hosted models so nothing leaves your environment. <a href="https://docs.gitlab.com/user/duo_agent_platform/model_selection/" rel="">Select the model per flow</a>, restrict which models are permitted, and keep your code out of training.</li><li><strong>Filter what gets sent.</strong> <a href="https://docs.gitlab.com/user/gitlab_duo/prompt_guardrails/" rel="">GitLab Duo&#39;s prompt guardrails</a> scan code suggestions for secrets before they reach a model, and isolate the content a prompt can act on to reduce prompt injection risk, on top of whatever you&#39;ve already excluded.</li></ul><p><img alt="Define what files or directories should be excluded from being sent to AI models" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785525382/uvgikegtzsabqdqahg04.png" title="Define what files or directories should be excluded from being sent to AI models" /></p><h2 id="from-one-scan-to-full-scanning-coverage-across-the-development-lifecycle">From one scan to full scanning coverage across the development lifecycle</h2><p>Anthropic&#39;s <a href="https://github.com/anthropics/claude-plugins-official/tree/main/plugins/security-guidance" rel="">documentation</a> is explicit that the Claude security guidance plugin is a best-effort assistive tool, meant to sit alongside human code review and various security scanners, not replace them. That scoping is important to pay attention to, because some vulnerabilities don&#39;t exist at the moment code ships. A dependency you ship today can have a critical vulnerability disclosed against it next year, with no change to your own code. <a href="https://www.cisa.gov/news-events/cybersecurity-advisories/aa21-356a" rel="">Log4Shell</a> is the clearest example; applications that shipped years earlier were suddenly exploitable the moment the vulnerability became public knowledge in December 2021.</p><p>Dependencies, container images, infrastructure configuration, and secrets already sitting in your commit history need scanning that runs independently of any single session.</p><p>GitLab secures the entire software delivery lifecycle:</p><ul><li><strong>Cover the whole attack surface.</strong> <a href="https://docs.gitlab.com/user/application_security/dependency_scanning/" rel="">Dependency</a>, <a href="https://docs.gitlab.com/user/application_security/container_scanning/" rel="">container</a>, <a href="https://docs.gitlab.com/user/application_security/iac_scanning/" rel="">infrastructure-as-code</a>, <a href="https://docs.gitlab.com/user/application_security/secret_detection/" rel="">secret</a>, and <a href="https://docs.gitlab.com/user/application_security/dast/" rel="">dynamic application security testing (DAST)</a> scanning check the parts of an application a session-based review never reaches: the dependencies you pull in, the images you ship, the infrastructure you provision, the secrets that leak into commits, and the running app.</li><li><strong>Catch the flaws that scanners might miss.</strong> Deterministic scanners cannot catch business logic errors, broken authorization, or race conditions. <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/security_review/" rel="">Security Review Flow</a> reasons about intent to catch that category directly, posted as comments on the affected code for a human to act on.</li><li><strong>Have a deterministic scan the results don&#39;t drift on.</strong> LLM-based review could return different findings on the same code from one run to the next. A deterministic scan, such as advanced SAST, traces tainted data across function boundaries using a fixed algorithm and returns reproducible, CWE-mapped results — the consistent evidence a compliance audit needs.</li></ul><p><img alt="SAST, DAST, dependency, container, and secret scanning enforced to be run on the pipeline" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785525382/tmmgtxgnlivwhjmx6uz7.png" title="SAST, DAST, dependency, container, and secret scanning enforced to be run on the pipeline" /></p><h2 id="one-set-of-guardrails-for-every-agent-and-every-developer">One set of guardrails, for every agent and every developer</h2><p>The Claude security guidance plugin reviews the code Claude writes and commits inside a session. Commits made from a developer&#39;s own shell, including the &quot;!&quot; shell escape inside a session, <a href="https://code.claude.com/docs/en/security-guidance" rel="">fall outside what the plug-in reviews</a>. Claude Security extends that to a full codebase or human-written code, on demand, when a developer or admin runs it.</p><p>GitLab’s scan execution and merge request approval policies run on the pipeline for every change, so coverage doesn&#39;t depend on whether a human or an agent wrote the code, or whether they remembered to initiate a scan.</p><p><img alt="Configure security scans to be run on every default branch" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785525383/hs2u66vp2c7fbxemwvbt.png" title="Configure security scans to be run on every default branch" /></p><h2 id="govern-what-ships">Govern what ships</h2><p>Claude security guidance and Claude Security help developers catch and fix issues the moment code is written. Once that code leaves the session, enterprise security and platform teams are accountable for shipping it securely to production. They need visibility into what an agent did, proof that security procedures were followed, and the ability to stop a problematic change before it ships.</p><p>GitLab bridges your Claude workflow. Set guardrails once in GitLab, and every agent and every developer ships faster and more securely inside them. Claude helps write secure code. GitLab governs everything from there to production, without slowing teams down.</p><blockquote><p><a href="https://about.gitlab.com/free-trial/?utm_medium=native&amp;utm_source=integrate-market&amp;utm_campaign=eg_global_cmp_content-syndication_security_en_" rel="">Start a free trial of GitLab Ultimate!</a></p><p>Already on Ultimate? <a href="https://docs.gitlab.com/user/application_security/policies/" rel="">Set up scan execution and merge request approval policies</a> to start enforcing guardrails today.</p></blockquote><h2 id="learn-more">Learn more</h2><ul><li><a href="https://about.gitlab.com/blog/claude-code-and-gitlab/" rel="">Claude Code and GitLab: Three workflows that ship</a></li><li><a href="https://about.gitlab.com/blog/gitlab-duo-agent-platform-with-claude-accelerates-development/" rel="">GitLab Duo Agent Platform with Claude accelerates development</a></li><li><a href="https://about.gitlab.com/blog/how-to-use-gitlabs-custom-compliance-frameworks-in-your-devsecops/" rel="">How to use GitLab&#39;s Custom Compliance Frameworks in your DevSecOps environment</a></li></ul>]]></content>
        <author>
            <name>Alisa Ho</name>
            <uri>https://about.gitlab.com/blog/authors/alisa-ho/</uri>
        </author>
        <published>2026-08-03T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[How to govern agentic AI, MCPs, and AI code assistants]]></title>
        <id>https://about.gitlab.com/blog/govern-agentic-ai-mcps-code-assistants/</id>
        <link href="https://about.gitlab.com/blog/govern-agentic-ai-mcps-code-assistants/"/>
        <updated>2026-07-31T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>AI code completion built human review into the process by design. A developer types, a suggestion appears, and a human decides whether to accept it. A person looked at every line before it shipped.</p><p>Agentic AI breaks that review loop. An agent can open a merge request, call a tool, modify a CI/CD configuration, and push a change, sometimes without a person reviewing each individual step. Add in the <a href="https://about.gitlab.com/topics/ai/model-context-protocol/" rel="">Model Context Protocol (MCP)</a>, which lets agents connect to external tools and data sources on their own, and the question engineering leaders are asking shifts. It is no longer &quot;which model writes the best code?&quot; It is &quot;what is this agent allowed to do, and how can we prove what it did?&quot;</p><p><a href="https://about.gitlab.com/resources/ai-accountability-survey-2026/" rel="">GitLab&#39;s own research</a> across more than 1,500 developers and technology leaders found that 73% of respondents are concerned about the long-term maintainability of code and 86% agree that without clear governance, AI-generated code can compound technical debt faster than traditional development practice.</p><p>In this article, you&#39;ll learn how to proactively address some of the challenges organizations are starting to see with governing agentic AI. We&#39;ll introduce you to a governance framework for agentic AI in software development and explore what to control, where human review still belongs, how to measure a rollout, and a practical checklist for teams standardizing on <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a>.</p><h2 id="why-agentic-ai-needs-a-different-approach-to-governance">Why agentic AI needs a different approach to governance</h2><p>The security model for an interactive coding assistant is straightforward because a human is in the loop at every step: a developer asks a question, reviews a suggestion, and accepts or rejects it.</p><p><a href="https://about.gitlab.com/topics/agentic-ai/" rel="">Agentic AI</a> in automated workflows requires a different approach to governance. When an agent can run tests, modify configurations, and take <a href="https://about.gitlab.com/blog/multi-step-software-delivery-with-agentic-flows/" rel="">multi-step actions across the software delivery lifecycle</a> without a human reviewing each step, the relevant questions change to:</p><ul><li>What can this agent access?</li><li>What is it authorized to do?</li><li>What actions did it take, and can that be proven after the fact?</li></ul><p>Most teams are already feeling this challenge. <a href="https://about.gitlab.com/resources/ai-accountability-survey-2026/" rel="">Ninety-two percent of DevSecOps professionals</a> report some governance challenge with AI-generated code, and the specific concerns point directly to the questions above.</p><p>The top concerns include:</p><ul><li><strong>Code attribution:</strong> The ability to tell which code was AI-generated versus human-written in the first place.</li><li><strong>Traceability to intent:</strong> Connect AI-generated code back to the business requirement it was meant to satisfy.</li><li><strong>Documentation that scales:</strong> Manual documentation practices don&#39;t hold up once agents are generating a growing share of the codebase.</li></ul><p>Once an agent is approved for a project, it can typically write, delete, and push changes without someone reviewing the action before it happens. However, you are still accountable for what lands in the codebase regardless of whether a person or an agent made the change.</p><p><strong>Governance for agentic AI is not an add-on to code completion governance. It is a different approach, built around identity, permissions, and auditability.</strong></p><h2 id="setting-controls-for-mcps-agents-model-access-and-tool-permissions">Setting controls for MCPs, agents, model access, and tool permissions</h2><p>Once agents can call tools and connect to external systems through protocols like MCP, permissioning becomes the control point. A useful governance model answers three questions before any agent runs:</p><ol><li>Which agents and flows are allowed?</li><li>Where are they allowed to operate?</li><li>Which models can the agents use?</li></ol><p>In practice, this looks like a few layers working together:</p><ul><li><a href="https://about.gitlab.com/blog/ai-catalog-discover-and-share-agents/" rel=""><strong>A central catalog for agents and flows</strong></a>: Rather than every team standing up its own agent integrations, a shared AI catalog lets administrators decide what gets published, aligned to the organization&#39;s existing roles and group structure.</li><li><a href="https://about.gitlab.com/blog/improve-ai-security-in-gitlab-with-composite-identities/" rel=""><strong>Composite identity</strong></a><strong>:</strong> Every AI agent&#39;s identity should be linked to the human user who requested the action, so activity is never attributable to the agent alone. When an agent tries to access a resource, both principals, the agent and the human who instructed it, need to be authenticated and authorized before access is granted.</li><li><a href="https://docs.gitlab.com/user/duo_agent_platform/agents/tool-governance/" rel=""><strong>Tool approval guardrails</strong></a><strong>:</strong> Individual agent tools can be set to run autonomously, pause for a human reviewer, or stay blocked outright, so a sensitive action like writing a file or deleting a resource waits for sign-off before it executes.</li><li><a href="https://about.gitlab.com/blog/how-gitlab-uses-prompt-guardrails-to-help-protect-customers/" rel=""><strong>Prompt guardrails</strong></a><strong>:</strong> Because agents can process untrusted input (a webpage, an issue comment, a file an attacker controls), the platform needs to detect attempts to hijack agent behavior mid-workflow, not just log it after the fact.</li></ul><p>The goal is a control plane that treats agent permissions the same way an organization already treats human permissions: role-based, auditable, and consistent across every project.</p><h2 id="data-privacy-and-self-hosted-ai-the-questions-worth-asking">Data privacy and self-hosted AI: The questions worth asking</h2><p>Source code is one of the most sensitive assets an enterprise has, and every AI feature that reads it raises a data-handling question. Before rolling out agentic AI broadly, engineering and security leaders typically want clear answers to a short list of questions:</p><ul><li>Does the vendor train models on our code?</li><li>Who owns the inputs and outputs?</li><li>Where do our subprocessors sit, and can we be notified when that list changes?</li></ul><p>For organizations in regulated industries, the answer to &quot;where do our subprocessors sit&quot; often needs to be &quot;nowhere outside our own infrastructure.&quot; That is why self-hosting matters as a governance lever, not just a deployment preference. <a href="https://about.gitlab.com/blog/agentic-ai-enterprise-control-self-hosted-duo-agent-platform-and-byom/" rel="">Self-hosted options</a> let a team run its AI agents entirely on infrastructure it controls, while still accurately tracking team usage and satisfying regulators.</p><p>Bring-your-own-model support extends that further, letting administrators connect models they have already validated internally and map specific models to certain agent flows. With this method, a sensitive workflow can be pinned to a model the organization trusts while less sensitive workflows use a managed option.</p><h2 id="human-in-the-loop-decide-where-review-still-belongs">Human-in-the-loop: Decide where review still belongs</h2><p>Governance does not mean blocking agents from acting autonomously. It means deciding, deliberately, where autonomy ends and review begins. A workable policy usually separates two modes:</p><ul><li><strong>Interactive work</strong>, where a developer is present, sees each suggestion, and approves or rejects it directly. This is the mode most teams already understand from <a href="https://about.gitlab.com/topics/devops/ai-powered-code-completion/" rel="">AI code completion</a>.</li><li><strong>Automated or headless work</strong>, such as agents running inside CI/CD pipelines without a developer watching in real time. Here, the review has to happen either before the action (through tool approval guardrails) or immediately after (through an <a href="https://about.gitlab.com/blog/one-vulnerability-view/" rel="">audit trail</a> a human can inspect).</li></ul><h3 id="key-decision-points-worth-defining">Key decision points worth defining</h3><p>Code review, testing and validation, and deployment approval should all be defined by answering questions like:</p><ul><li>Which of these can an agent complete unassisted?</li><li>Which require a named human sign-off before the change proceeds?</li></ul><p>In practice, each checkpoint needs its own enforcement mechanism. This could look like:</p><ul><li><a href="https://docs.gitlab.com/user/application_security/policies/merge_request_approval_policies/" rel="">Merge request approval policies</a> determine who has to sign off before a merge request lands, regardless of whether an agent or a developer opened it.</li><li><a href="https://docs.gitlab.com/user/duo_agent_platform/agents/tool-governance/" rel="">Tool approval guardrails</a> for agents decide, tool by tool, whether an agent&#39;s action runs autonomously, pauses for review, or stays blocked.</li><li><a href="https://docs.gitlab.com/user/application_security/policies/scan_execution_policies/" rel="">Scanner enforcement</a> holds a change at the pipeline level until it clears the security and quality checks your organization requires.</li></ul><p>We recommend creating an organization-wide <a href="https://about.gitlab.com/blog/a-developers-guide-to-building-an-ai-security-governance-framework/" rel="">AI governance policy</a> rather than leaving it to individual team norms. This helps create consistent usage and policies, and helps auditors verify your use of AI.</p><h3 id="added-context-from-the-decision-layer">Added context from the decision layer</h3><p>There is a longer-term benefit to capturing these approvals as structured records rather than letting them evaporate in a chat thread or a reviewer&#39;s memory. An exception granted last quarter, the policy version it was granted under, and who approved it are exactly the kind of organizational judgment that both auditors and future agents need to reference.</p><p>Enterprises that treat decisions as durable, queryable events get the added benefit that the next reviewer, human or agent, starts with additional context instead of starting from zero.</p><blockquote><p>Learn more about <a href="https://learn.gitlab.com/transcend-evergreen/whitepaper-use-case-for-context-graphs" rel="">the decision layer</a> and how capturing decision events can impact your software development.</p></blockquote><h2 id="_5-metrics-that-measure-an-ai-rollout">5 metrics that measure an AI rollout</h2><p>Five categories are worth tracking from the start, and they should be reviewed together rather than in isolation, since a spike in adoption without a matching look at risk metrics is itself a warning sign.</p><ol><li><strong>Adoption:</strong> Active users of AI features week over week, number of flows or agents run, and which teams have turned agentic capabilities on versus which have not.</li><li><strong>Acceptance and quality:</strong> Downstream signals like revert rate on AI-assisted changes and how often AI-authored merge requests pass review without rework. A single acceptance-rate number is a weak proxy for effectiveness on its own, since it says nothing about what happens to the code after it is accepted.</li><li><strong>Risk:</strong> Track how often tool approval guardrails pause an action for review, how often those pauses result in a blocked or modified action, and whether any agent activity triggers a policy violation.</li><li><strong>Remediation</strong>: Keep an eye on the scanner coverage across projects, the share of vulnerabilities that get auto-remediated versus manually triaged, and time to resolve findings once flagged.</li><li><strong>ROI:</strong> Once you have a full quarter of data, explore the ROI of your AI investment. Track how much time developers save on tasks agents now handle and weigh that against the cost per resolved issue or merged change, in credits or compute spent. Check out this tutorial for an <a href="https://about.gitlab.com/blog/measuring-ai-roi-at-scale-a-practical-guide-to-gitlab-duo-analytics/" rel="">in-depth look at your AI ROI</a> — you’ll learn how to transform raw usage data into actionable business insights and ROI calculations.</li></ol><p>By tracking all five metrics together, you can catch issues with the AI rollout early. A rollout can look successful on adoption and acceptance while accumulating risk that only shows up in an audit six months later. With the above metrics, you get a holistic view of the value of AI to your organization.</p><h2 id="your-gitlab-duo-agent-platform-governance-checklist">Your GitLab Duo Agent Platform governance checklist</h2><p>For teams standardizing on GitLab Duo Agent Platform, here is a practical starting checklist before expanding agentic AI beyond a pilot:</p><ul className="contains-task-list"><li className="task-list-item"><input disabled type="checkbox" /> Review the <a href="https://about.gitlab.com/ai-transparency-center/" rel="">AI Transparency Center</a> and confirm your understanding of data usage, model vendors, and subprocessor commitments.</li><li className="task-list-item"><input disabled type="checkbox" /> Decide, at the platform level, which agents and flows are approved for use, and publish them through GitLab’s <a href="https://about.gitlab.com/blog/ai-catalog-discover-and-share-agents/#creating-sharing-and-managing-visibility" rel="">AI Catalog</a> rather than letting teams configure their own.</li><li className="task-list-item"><input disabled type="checkbox" /> Set <a href="https://docs.gitlab.com/user/duo_agent_platform/agents/tool-governance/" rel="">tool approval guardrails</a> as always allow, always ask, or always deny, based on the sensitivity of the tool.</li><li className="task-list-item"><input disabled type="checkbox" /> Set up <a href="https://docs.gitlab.com/development/ai_features/composite_identity/" rel="">composite identity</a> so every agent action is linked to the human who requested it, and access requires both to be authorized.</li><li className="task-list-item"><input disabled type="checkbox" /> For regulated workloads, evaluate <a href="https://about.gitlab.com/blog/agentic-ai-enterprise-control-self-hosted-duo-agent-platform-and-byom/" rel="">self-hosted deployment and bring-your-own-model options</a> against your data residency requirements.</li><li className="task-list-item"><input disabled type="checkbox" /> Document explicit human-in-the-loop checkpoints for code review, testing and validation, and deployment approval.</li><li className="task-list-item"><input disabled type="checkbox" /> Turn on <a href="https://docs.gitlab.com/user/compliance/audit_event_streaming/" rel="">audit event streaming</a> for agent activity so every action lands in the same audit trail your organization already reviews.</li><li className="task-list-item"><input disabled type="checkbox" /> Define your <a href="https://docs.gitlab.com/user/analytics/" rel="">rollout metrics</a> (adoption, acceptance, risk, remediation, ROI) before expanding past a pilot, and review them together on a recurring cadence.</li></ul><p>Revisit the checklist each release cycle. Governance for agentic AI is not a one-time setup. New agents, new tools, and new models often reopen governance questions.</p><h2 id="where-agentic-ai-speed-meets-enterprise-control">Where agentic AI speed meets enterprise control</h2><p>Agentic AI changes what needs governing. Code completion asked a developer whether a suggestion was good. Agentic AI asks what an agent is allowed to touch, who approved it, and whether that can be proven later.</p><p>Answering those questions fully requires governance built into the platform itself, not layered on afterward. <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a> provides an AI Catalog, approval guardrails, and audit event streaming directly into the platform where the work happens, so governance isn&#39;t bolted on after the fact. Teams get AI-assisted speed and enterprise control together, because the guardrails are part of the workflow, not a separate process running alongside it.</p><blockquote><p>Start a <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">free trial of GitLab Duo Agent Platform</a>. On the Free tier, you can <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#for-the-free-tier-on-gitlabcom" rel="">sign up in a few simple steps</a>. If you&#39;re already on GitLab Premium or Ultimate, you can <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">turn on Duo Agent Platform</a> and use the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits/" rel="">GitLab Credits included with your subscription</a>.</p></blockquote>]]></content>
        <author>
            <name>Julie Griffin</name>
            <uri>https://about.gitlab.com/blog/authors/julie-griffin/</uri>
        </author>
        <published>2026-07-31T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Why GitLab signed the Open Weights and American AI Leadership letter]]></title>
        <id>https://about.gitlab.com/blog/open-weight-model-letter/</id>
        <link href="https://about.gitlab.com/blog/open-weight-model-letter/"/>
        <updated>2026-07-29T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>This week GitLab signed the <a href="https://www.microsoft.com/en-us/corporate-responsibility/topics/open-weight/" rel="">Open Weights and American AI Leadership letter</a>, joining a long list of other technology companies that support a strong, open AI ecosystem.</p><p>The letter argues that open weights spur innovation, give customers greater control, and provide an important path to AI safety and security. In addition to being a policy position we share, it’s core to how we think about agentic engineering: Teams do their best work when they can choose the right model for the job.</p><p>As the intelligent orchestration platform for DevSecOps that enables speed with control for agentic software engineering, GitLab prioritizes customer choice by orchestrating the software lifecycle and supporting multiple models across a team’s workflow.</p><h2 id="empowering-customers-to-choose-their-ai-models">Empowering customers to choose their AI models</h2><p>For many organizations, there is an emerging interest in having governed access to best-in-class foundation and open weight models. GitLab supports both.</p><p>Foundation models often lead on general-purpose capability, while open weight models can provide benefits for customer control over cost, deployment, and data residency. Our goal is to help customers combine them as needed.</p><p>One of the most critical decisions corporate leaders make is how to protect software and strategic IP against security, privacy, and competitive threats. Organizations shouldn&#39;t be locked into one cloud or one AI model provider.</p><p>GitLab is the only platform that&#39;s cloud neutral and AI model neutral. That choice only holds up if the model market stays open. Open weight models give development teams the choice of where to run their AI models — in air-gapped environments if necessary — while keeping control of their code.</p><h2 id="our-stance">Our stance</h2><p>Like policymakers, we want a safe, secure AI ecosystem, and view openness as an important part of achieving it. We support policies that preserve the ability to develop, distribute, and use open weight models subject to focused, risk-based safeguards and well-targeted tools for addressing genuine misuse. These kinds of interventions can play a meaningful role in fostering a robust ecosystem in which multiple model providers — open and proprietary — can compete on the merits, to the benefit of innovation, security, and customer choice.</p><h2 id="related-links">Related links</h2><ul><li><a href="https://about.gitlab.com/ai-transparency-center/" rel="">GitLab AI Transparency Center</a></li><li><a href="https://about.gitlab.com/blog/securing-ai-together-gitlabs-partnership-with-security-researchers/" rel="">Securing AI together: GitLab&#39;s partnership with security researchers</a></li><li><a href="https://about.gitlab.com/blog/why-enterprise-independence-matters-more-than-ever-in-devsecops/" rel="">Why enterprise independence matters more than ever in DevSecOps</a></li></ul>]]></content>
        <author>
            <name>Bill Staples</name>
            <uri>https://about.gitlab.com/blog/authors/bill-staples/</uri>
        </author>
        <published>2026-07-29T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[GitLab Patch Release: 19.2.1, 19.1.3, 19.0.5]]></title>
        <id>https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-1-released/</id>
        <link href="https://docs.gitlab.com/releases/patches/patch-release-gitlab-19-2-1-released/"/>
        <updated>2026-07-29T00:00:00.000Z</updated>
        <published>2026-07-29T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Claude Opus 5 on GitLab: Reasoning built for the hard tasks]]></title>
        <id>https://about.gitlab.com/blog/claude-opus-5-on-gitlab-duo-agent-platform/</id>
        <link href="https://about.gitlab.com/blog/claude-opus-5-on-gitlab-duo-agent-platform/"/>
        <updated>2026-07-27T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>A mistake on a routine task can cost you a minute. A mistake on a large refactor or a debugging trail spanning months of commit history can cost far more, as it compounds silently over hundreds of exchanges. By the time you catch it, every step built on top of it needs unwinding, too. That&#39;s the difference between work that rewards speed and high-complexity work that requires getting it right the first time.</p><p>Anthropic&#39;s newest AI model Claude Opus 5, now available on <a href="https://docs.gitlab.com/user/duo_agent_platform/" rel="">GitLab Duo Agent Platform</a>, is built for the tasks that demand the most from an agent. With Opus 5, your engineering team can trust agents with more complex, critical work. In GitLab&#39;s internal evaluation, Opus 5 resolved 93.3% of benchmark tasks, a 20.3-point improvement over Opus 4.8&#39;s 73.0% resolution rate.</p><blockquote><p><strong>&quot;The teams getting the most value from AI agents can hand over their hardest, highest-stakes work and trust the reasoning holds up from first step to last.&quot;</strong></p><p>— Stuart Moncada, VP, AI Product Management, GitLab</p></blockquote><h2 id="reasoning-that-holds-up-under-complexity">Reasoning that holds up under complexity</h2><p>Some teams hesitate when delegating their most challenging work to an agent because the mistakes are costly to unwind. On long-running, high-complexity tasks, an agent&#39;s reasoning has to persist from start to finish. With Opus 5’s deeper reasoning, more of your complex tasks, like multi-file features and larger refactors, resolve correctly the first time, helping cut down on the time you spend diagnosing and re-prompting failed runs. Teams running GitLab Duo Agent Platform with Opus 5 can expect to see fewer partial patches, with more of the work coming back ready to merge.</p><p>That reliability extends to completeness as well. In GitLab’s internal testing, Opus 5 completed 100% of the tasks it attempted, matching Opus 4.8’s completion rate. The edge is in what they produce: more of Opus 5&#39;s solutions are verified correct, putting Opus 5&#39;s resolution rate at 93.3%, against Opus 4.8&#39;s 73.0%.</p><p>One task in GitLab&#39;s evaluation called for mockable SSO login support in a CLI authentication flow, a change spanning five files, including new exported types and configuration fields. Several other models tested produced no attempt at a fix. Opus 5 built the full implementation, committed it, and opened a merge request.</p><p>You can expect the same precision in code review. Opus 5 flags real bugs and produces few false positives, so your team can stay focused on genuine vulnerabilities and spend less time filtering noise.</p><p>If your workload runs several agents at once, you waste less time untangling conflicts between them. Opus 5 keeps subagents coordinated, ensuring they stay out of each other&#39;s work. Writer-verifier patterns catch problems between agents before they reach you, with one agent checking another&#39;s output before it&#39;s accepted. Teams running longer, more autonomous sessions with more agents in parallel see the strongest results.</p><p>For cost-sensitive workloads running multiple parallel agents, <a href="https://about.gitlab.com/blog/gitlab-18-11-budget-guardrails-for-gitlab-credits/" rel="">GitLab Credits usage caps</a> let you set a hard limit on spend, so parallel work never runs beyond what you&#39;ve budgeted.</p><h2 id="speed-keeps-pace-with-depth">Speed keeps pace with depth</h2><p>On GitLab&#39;s hardest benchmark tasks, Opus 5 pairs reliability with speed. At the 95th percentile, the slower tail of its runs, Opus 5 finished 2.2% faster than Opus 4.8 (768 seconds vs. 784.98 seconds) and 21.9% faster than Sonnet 4.6 (768 seconds vs. 982.57 seconds). Reliability and speed move together. For your team, that means more predictable turnaround, even on your longest runs.</p><h2 id="choose-the-right-model-for-the-task-at-hand">Choose the right model for the task at hand</h2><p>The right model depends on the task in front of you, not a single org-wide policy. Sonnet-class models handle the bulk of day-to-day development work: fast, affordable, and dependable for what most teams run constantly. Turn to Opus 5 when the work demands deeper reasoning: the hardest debugging, the largest refactors, the decisions you don&#39;t want to rework.</p><p>You set that choice directly in your GitLab instance through <a href="https://docs.gitlab.com/user/duo_agent_platform/model_selection/" rel="">model selection</a>. Whichever model you choose, it runs inside the same infrastructure: the context layer, policy checks, and audit trail that cover every model on GitLab Duo Agent Platform.</p><p><img alt="Opus 5 on GitLab" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1785170335/jjimrfrttyyskwa96lnk.png" /></p><h2 id="put-opus-5-to-work">Put Opus 5 to work</h2><p>Claude Opus 5 is available now on GitLab Duo Agent Platform and, like other models, runs on <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#models" rel="">GitLab Credits</a>. New to Duo Agent Platform? <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">Start a free trial</a> today. Already a GitLab Premium or Ultimate subscriber? <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">Turn on Duo Agent Platform</a> and use the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits" rel="">GitLab Credits included with your subscription</a>.</p>]]></content>
        <author>
            <name>Brittany Lutz</name>
            <uri>https://about.gitlab.com/blog/authors/brittany-lutz/</uri>
        </author>
        <published>2026-07-27T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Modernize Java with Cursor and GitLab]]></title>
        <id>https://about.gitlab.com/blog/modernize-java-with-cursor-and-gitlab/</id>
        <link href="https://about.gitlab.com/blog/modernize-java-with-cursor-and-gitlab/"/>
        <updated>2026-07-22T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>&quot;Modernize Java 8 to Java 21&quot; sounds like one task. It is not. It touches the build, the runtime, dependencies, APIs, concurrency, tests, containers, and production behavior, often all at once. Ask an agent to do all of that in one prompt, and you get one enormous merge request that nobody can safely review.</p><p>Cursor, an AI coding agent, is good at the focused part of that problem. Give it one failing test or one bounded issue, and it can inspect the implementation, explain what went wrong, propose a fix, and run the tests without pulling us out of the development flow. What it cannot decide on its own is what &quot;safe&quot; means across a multi-step migration.</p><p>That is where GitLab comes in, with <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">Duo Agent Platform</a> orchestrating AI workflows in the rest of the software lifecycle, designed to certify the work of coding agents. The issue hierarchy with epics makes the plan durable and reviewable. The GitLab Model Context Protocol (<a href="https://about.gitlab.com/topics/ai/model-context-protocol/" rel="">MCP</a>) server brings that software development lifecycle context into Cursor. CI/CD, security scanning, code review, impact analysis and a cross-service test give us the evidence we need before changing production behavior.</p><p>In this tutorial, we will walk through three use cases with Cursor and GitLab:</p><ol><li><a href="#fix-a-failing-end-to-end-test-with-cursor">Fix a failing Java end-to-end test with Cursor</a></li><li><a href="#prepare-quality-gates-for-java-21-modernization">Prepare quality gates for Java 8 to 21 modernization</a></li><li><a href="#modernize-http-connection-handling-with-java-21">Modernize HTTP connection handling with Java 21</a></li></ol><p>The progression matters: Start small, add project context, and then modernize one boundary. Cursor moves fast inside that boundary. Code Review Flow, Developer Flow, CI/CD, code owner approvals, and impact analysis are what keep that speed safe. They are not optional checkpoints, but the mechanism that holds every agent-created merge request to the same standard as any other.</p><p>We are using the <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector" rel="">Java HTTP metrics collector from the Tanuki IoT Platform</a> for all three use cases. It checks HTTP endpoints, records metrics such as response status and timing, and sends readings to its <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/backend/rust-metrics-store" rel="">Rust metrics backend</a>. That gives us a visible application boundary to modernize and a real backend contract to verify. A while back, we developed the Rust backend in the <a href="https://about.gitlab.com/blog/fix-bugs-with-codex-and-gitlab/" rel="">Codex and GitLab tutorial</a>, and it now fits into the production architecture:</p><pre className="language-mermaid shiki shiki-themes github-light" code="flowchart LR
  subgraph sources[&quot;HTTP metric sources&quot;]
    direction TB
    health[&quot;Health endpoint&quot;]
    maintenance[&quot;Maintenance endpoint&quot;]
  end

  java[&quot;Java HTTP metrics collector&quot;]
  rust[(&quot;Rust metrics-store backend&quot;)]

  java --&gt;|&quot;GET&quot;| health
  java --&gt;|&quot;GET&quot;| maintenance
  java --&gt;|&quot;POST /api/metrics&quot;| rust
  rust --&gt;|&quot;HTTP response&quot;| java

  classDef source fill:#f8fafc,stroke:#64748b,stroke-width:2px,color:#0f172a
  classDef focus fill:#dcfce7,stroke:#16a34a,stroke-width:3px,color:#0f172a
  classDef backend fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a

  class health,maintenance source
  class java focus
  class rust backend
" language="mermaid" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">flowchart LR
</span></span><span class="line" line="2"><span class="sgsFI">  subgraph sources[&quot;HTTP metric sources&quot;]
</span></span><span class="line" line="3"><span class="sgsFI">    direction TB
</span></span><span class="line" line="4"><span class="sgsFI">    health[&quot;Health endpoint&quot;]
</span></span><span class="line" line="5"><span class="sgsFI">    maintenance[&quot;Maintenance endpoint&quot;]
</span></span><span class="line" line="6"><span class="sgsFI">  end
</span></span><span class="line" line="7"><span emptyLinePlaceholder>
</span></span><span class="line" line="8"><span class="sgsFI">  java[&quot;Java HTTP metrics collector&quot;]
</span></span><span class="line" line="9"><span class="sgsFI">  rust[(&quot;Rust metrics-store backend&quot;)]
</span></span><span class="line" line="10"><span emptyLinePlaceholder>
</span></span><span class="line" line="11"><span class="sgsFI">  java --&gt;|&quot;GET&quot;| health
</span></span><span class="line" line="12"><span class="sgsFI">  java --&gt;|&quot;GET&quot;| maintenance
</span></span><span class="line" line="13"><span class="sgsFI">  java --&gt;|&quot;POST /api/metrics&quot;| rust
</span></span><span class="line" line="14"><span class="sgsFI">  rust --&gt;|&quot;HTTP response&quot;| java
</span></span><span class="line" line="15"><span emptyLinePlaceholder>
</span></span><span class="line" line="16"><span class="sgsFI">  classDef source fill:#f8fafc,stroke:#64748b,stroke-width:2px,color:#0f172a
</span></span><span class="line" line="17"><span class="sgsFI">  classDef focus fill:#dcfce7,stroke:#16a34a,stroke-width:3px,color:#0f172a
</span></span><span class="line" line="18"><span class="sgsFI">  classDef backend fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a
</span></span><span class="line" line="19"><span emptyLinePlaceholder>
</span></span><span class="line" line="20"><span class="sgsFI">  class health,maintenance source
</span></span><span class="line" line="21"><span class="sgsFI">  class java focus
</span></span><span class="line" line="22"><span class="sgsFI">  class rust backend
</span></span></code></pre><h2 id="prerequisites">Prerequisites</h2><ol><li><a href="https://www.cursor.com/" rel="">Cursor</a> installed and configured. We will use the Cursor IDE in this tutorial.</li><li>A GitLab project with the Java collector source, issues, and modernization work items. You can use the <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector" rel="">Tanuki IoT Platform Java HTTP metrics collector</a>.</li><li>Java 8 for the first use case and Java 21 for the modernization work</li><li>Maven, Docker and Docker Compose for local builds and functional tests</li><li>The <a href="https://docs.gitlab.com/user/model_context_protocol/mcp_server/" rel="">GitLab MCP server</a> enabled on your GitLab instance or top-level group</li><li><a href="https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/code_review/" rel="">GitLab Duo Code Review Flow</a>,  <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/developer/" rel="">Developer Flow</a> and <a href="#automate-impact-analysis-for-modernization-breaking-changes">custom flow for impact analysis on breaking changes</a> enabled for the Java collector project. These flows apply project guardrails to every merge request the agent creates.</li></ol><h3 id="prepare-the-gitlab-project">Prepare the GitLab project</h3><p>If you want to repeat the workflow in your own environment, start by importing and cloning the project and opening the project in Cursor:</p><ol><li>Import the <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector" rel="">Tanuki IoT Platform Java HTTP metrics collector</a> into your GitLab environment, including all open issues.</li><li>Clone the project into your local environment and navigate into it.</li><li>Open the project in Cursor.</li></ol><pre className="language-shell shiki shiki-themes github-light" code="git clone https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector.git
cd java-http-metrics-collector

cursor .
" language="shell" meta="" style=""><code><span class="line" line="1"><span class="s7eDp">git</span><span class="sYBdl"> clone</span><span class="sYBdl"> https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector.git
</span></span><span class="line" line="2"><span class="sYu0t">cd</span><span class="sYBdl"> java-http-metrics-collector
</span></span><span class="line" line="3"><span emptyLinePlaceholder>
</span></span><span class="line" line="4"><span class="s7eDp">cursor</span><span class="sYBdl"> .
</span></span></code></pre><p>The project includes an <code>AGENTS.md</code> file with repository instructions and Maven commands. Cursor can use these local instructions to understand how the project is organized and how changes should be tested.</p><p><img alt="The Java HTTP metrics collector open in Cursor with AGENTS.md instructions" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733478/l4hqhlzxekmhobu2qg0v.png" /></p><h2 id="fix-a-failing-end-to-end-test-with-cursor">Fix a failing end-to-end test with Cursor</h2><p>The collector allows users to configure the HTTP status code they expect from an endpoint. The implementation, however, treats every <code>2xx</code> response as successful, and <code>503</code> errors would always fail even when configured as expected.</p><p>The end-to-end test already exposes this mismatch, but the CI/CD job is allowed to fail. That has turned a useful signal into accepted background noise.</p><p><img alt="The failing end-to-end test and its allowed-to-fail CI/CD job" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733536/uaxqalqoceujyja7usmv.png" /></p><h3 id="reproduce-and-fix-with-cursor">Reproduce and fix with Cursor</h3><p>The problem can be reproduced locally. Open the Cursor IDE with a new chat, and start by describing the observable problem directly in the prompt:</p><pre className="language-markdown shiki shiki-themes github-light" code="Can you help me fix the end-to-end tests in this project? Please create an analysis first, then fix it, and run the tests again.
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">Can you help me fix the end-to-end tests in this project? Please create an analysis first, then fix it, and run the tests again.
</span></span></code></pre><p>Cursor starts by tracing the endpoint configuration into <code>HttpCollector</code> and the failing end-to-end test, and identifies the root cause.</p><p><img alt="Cursor analysing the problem and root cause" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733605/ojz2pzcftwjfcfscjtwg.png" /></p><p>After the focused tests and the full Maven test suite pass, create a branch and merge request. The previously allowed-to-fail end-to-end job can become required when it is deterministic and green.</p><pre className="language-markdown shiki shiki-themes github-light" code="Can you create a git branch and merge request?
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">Can you create a git branch and merge request?
</span></span></code></pre><h3 id="review-and-merge">Review and merge</h3><p>The merge request automatically triggers CI/CD build and tests, and security scanning.</p><p><img alt="Merge request with fixed end-to-end tests" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733663/koz3yb3zq5ewwl6vrbgk.png" /></p><p><a href="https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/code_review/" rel="">GitLab Duo Code Review</a> then reviews the focused change using the project&#39;s Java-specific review instructions.</p><p><img alt="Code Review feedback" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733717/cjxeoecb4fa7yrvy7i90.png" /></p><p>When the review identifies a concrete problem, we address it through the Developer Flow before merging. That is the point: Code Review Flow ensures every agent-created merge request meets the same bar as any other, regardless of how fast Cursor produced it. The merge request remains the collaboration and decision surface.</p><p><img alt="Developer Flow addressing review feedback" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733848/wehjrbkhhyhze8vtkaby.png" /></p><p>The fix gives us a behavioral baseline. We corrected a real bug without mixing it with a runtime migration, and the tests now protect the expected-status contract during the modernization work that follows.</p><p>Watch this video to learn how Cursor investigates and fixes the expected end-to-end tests:</p><figure className="video_container">
  <iframe src="https://www.youtube.com/embed/vpPt8TICiZY" frameBorder="0" allowFullScreen="true"> </iframe></figure><h2 id="prepare-quality-gates-for-java-21-modernization">Prepare quality gates for Java 21 modernization</h2><p>The first fix worked with repository context alone. The next request is much larger: Modernize the collector from Java 8 to Java 21.</p><p>That work already has planning context in the <a href="https://gitlab.com/groups/gitlab-da/demo-environments/tanuki-iot-platform/-/work_items/13" rel="">Java modernization epic</a>: child work items, team discussions, research with merge requests, pipeline history, dependencies, and security findings. Those details do not live in the local checkout. Instead of copying all of them into one enormous prompt, we can bring the GitLab context into Cursor with MCP.</p><h3 id="configure-the-gitlab-mcp-server-in-cursor">Configure the GitLab MCP server in Cursor</h3><p>Ensure that the GitLab MCP server is <a href="https://docs.gitlab.com/user/gitlab_duo/model_context_protocol/mcp_server/#prerequisites" rel="">enabled</a> on your instance or top-level group. Cursor uses HTTP transport to connect directly without additional dependencies.</p><p>To <a href="https://docs.gitlab.com/user/gitlab_duo/model_context_protocol/mcp_server/#connect-cursor-to-the-gitlab-mcp-server" rel="">connect Cursor to the GitLab MCP server</a>:</p><ol><li>In Cursor, go to <strong>Settings &gt; Cursor Settings &gt; Tools &amp; MCP</strong>.</li><li>Under <strong>Installed MCP Servers</strong>, select <strong>New MCP Server</strong>.</li><li>Add the following definition to the <code>mcpServers</code> key in the opened <code>mcp.json</code> file. For GitLab.com, replace <code>&lt;gitlab.example.com&gt;</code> with <code>gitlab.com</code>. For GitLab Self-Managed or Dedicated, use your GitLab instance URL.</li></ol><pre className="language-json shiki shiki-themes github-light" code="{
  &quot;mcpServers&quot;: {
    &quot;GitLab&quot;: {
      &quot;type&quot;: &quot;http&quot;,
      &quot;url&quot;: &quot;https://&lt;gitlab.example.com&gt;/api/v4/mcp&quot;
    }
  }
}
" language="json" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">{
</span></span><span class="line" line="2"><span class="sYu0t">  &quot;mcpServers&quot;</span><span class="sgsFI">: {
</span></span><span class="line" line="3"><span class="sYu0t">    &quot;GitLab&quot;</span><span class="sgsFI">: {
</span></span><span class="line" line="4"><span class="sYu0t">      &quot;type&quot;</span><span class="sgsFI">: </span><span class="sYBdl">&quot;http&quot;</span><span class="sgsFI">,
</span></span><span class="line" line="5"><span class="sYu0t">      &quot;url&quot;</span><span class="sgsFI">: </span><span class="sYBdl">&quot;https://&lt;gitlab.example.com&gt;/api/v4/mcp&quot;
</span></span><span class="line" line="6"><span class="sgsFI">    }
</span></span><span class="line" line="7"><span class="sgsFI">  }
</span></span><span class="line" line="8"><span class="sgsFI">}
</span></span></code></pre><ol start="4"><li>Save the file and wait for the OAuth authorization page to open in your browser. If it does not open, close and restart Cursor.</li><li>Review and approve the authorization request in your browser.</li><li>Return to Cursor and inspect the listed tools.</li></ol><p><img alt="The GitLab MCP server connected in Cursor after OAuth authorization" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733928/anreghjemkrnuezohhzh.png" /></p><p>You can now start a new chat and ask a question based on the available GitLab MCP tools.</p><p>When Cursor authenticates with GitLab MCP, it acts with your existing GitLab identity. It can only access projects and resources that you can already access. MCP brings approved context into the IDE; it does not bypass GitLab permissions.</p><h3 id="prepare-the-environment-for-java-21-modernization">Prepare the environment for Java 21 modernization</h3><p>The <a href="https://gitlab.com/groups/gitlab-da/demo-environments/tanuki-iot-platform/-/work_items/13" rel="">Java 8 to 21 modernization epic</a> breaks down the necessary plan into smaller iterations, each artifact and change being testable on its own.</p><p><img alt="GitLab epic with child issues" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784733989/thwfzpvbs7tcm0un2xg6.png" /></p><p>The first step is to ensure that the CI/CD infrastructure tests both Java 8 and 21, in parallel. Increasing the test coverage from the beginning into each modernization task is mandatory, too.</p><p>Open the Cursor IDE, and use the following prompt to fetch the planning context:</p><pre className="language-markdown shiki shiki-themes github-light" code="Please help me modernize this sensor from Java 8 to 21. We want to start with the base line for CI/CD builds in work item 14, and then also look into test coverage from 21. Start the implementation in a new Git branch called `maint-java-21` so we can continue testing different scenarios.
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">Please help me modernize this sensor from Java 8 to 21. We want to start with the base line for CI/CD builds in work item 14, and then also look into test coverage from 21. Start the implementation in a new Git branch called </span><span class="sYu0t">`maint-java-21`</span><span class="sgsFI"> so we can continue testing different scenarios.
</span></span></code></pre><p>After finishing the work on the CI build visibility issue, Cursor can use the <code>create_workitem_note</code> MCP tool to add a summary comment into the issue, too.</p><p><img alt="Cursor summary with GitLab MCP server tool call" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734071/bks4lwnncddardc05r3e.png" /></p><p>The new merge request triggers CI/CD pipelines, and also the Code Review Flow, which leaves comments about the development style guide requiring documentation.</p><p><img alt="Code review feedback in the merge request" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734168/z7ootq0wqmom3yxmdexj.png" /></p><p>We can immediately address the feedback in the GitLab UI by mentioning the Developer Flow&#39;s service account.</p><pre className="language-markdown shiki shiki-themes github-light" code="@duo-developer-&lt;group-name&gt; Can you help address the review feedback?
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">@duo-developer-&lt;</span><span class="shJU0">group-name</span><span class="sgsFI">&gt; Can you help address the review feedback?
</span></span></code></pre><p>This prompt starts a new background session, and we can focus on other tasks meanwhile. Alternatively, we can change back into the Cursor IDE and prompt its chat to address the review feedback in the merge request.</p><p><img alt="Cursor IDE prompt &quot;There is review feedback in the MR - please help me fix it&quot;" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734264/n5ky8nj73bpb1imzrj6h.png" /></p><p>Cursor implements the changes, and adds comments into the merge request threads using the <code>create_merge_request_note</code> MCP tool.</p><p><img alt="GitLab merge request with addressed code review comments" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734337/hah0qxe8ei5h6iefzqz4.png" /></p><p>The change keeps the temporary Java 8 baseline and adds distinct Java 21 build and test validation. This change makes compatibility visible in the pipeline before the source starts using Java 21-only APIs. Once these quality gates exist, every subsequent agent-driven change is reviewed, tested, and traceable. That is the same standard we apply to any other merge request, and it is what makes it safe to let Cursor move fast.</p><p>Watch this video to learn how Cursor uses GitLab MCP to prepare quality gates and address code review feedback:</p><figure className="video_container">
  <iframe src="https://www.youtube.com/embed/bqT2exfE5Go" frameBorder="0" allowFullScreen="true"> </iframe></figure><h2 id="modernize-http-connection-handling-with-java-21">Modernize HTTP connection handling with Java 21</h2><p>The Java HTTP metrics collector currently uses the legacy <code>HttpURLConnection</code> API from Java 8. Java 21 modernized the HTTP library with <code>java.net.http.HttpClient</code>, but this is not just a mechanical rename. Redirects, restricted headers, timeout scope, response bodies, interruption, and connection reuse can all behave differently. That is why the implementation lives in one bounded work item: <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector/-/work_items/16" rel="">Replace HttpURLConnection with java.net.http.HttpClient</a>. Let&#39;s put that into practice.</p><p>Open the Cursor IDE with a new chat, and ask to implement the changes.</p><p><strong>Note:</strong> For this use case, we want to use a local Docker compose setup to verify the changes. If you want to reproduce the behavior, install Docker and Docker compose, otherwise remove the second prompt.</p><pre className="language-markdown shiki shiki-themes github-light" code="We want to continue modernizing the app to Java 21 - use the same maint-java-21 branch, and start implementing issue 16.

Verify the changes locally using the docker compose setup, after making the changes.
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">We want to continue modernizing the app to Java 21 - use the same maint-java-21 branch, and start implementing issue 16.
</span></span><span class="line" line="2"><span emptyLinePlaceholder>
</span></span><span class="line" line="3"><span class="sgsFI">Verify the changes locally using the docker compose setup, after making the changes.
</span></span></code></pre><p>The GitLab MCP server provides the issue context, acceptance criteria, dependencies, and related discussions. The first code modernization issue remains deliberately synchronous and limited. It replaces <code>HttpURLConnection</code> with one reusable <code>HttpClient</code> and does not add virtual threads, change the time model, or remediate unrelated dependencies. Those are valuable follow-ups, but combining them would make behavior changes harder to isolate, review, and roll back.</p><h3 id="implement-and-verify-locally">Implement and verify locally</h3><p>Focused local HTTP server tests cover methods, headers, expected and unexpected status codes, redirects, timeouts, response metadata, connection failures, and interruption.</p><p><img alt="Cursor running local Maven tests" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734391/fuxi3jcrcg5alhuqcrje.png" /></p><p>The Docker Compose functional test then proves that authenticated readings still arrive in the <code>rust-metrics-store</code> backend.</p><p><img alt="Cursor running local Docker compose with Rust backend" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734439/w83djmi4df9dfynb9dfj.png" /></p><p>If the CI/CD pipelines are failing after the changes, leverage the GitLab MCP server tools to inspect and fix directly in the Cursor IDE without context switching.</p><p><img alt="Cursor IDE with GitLab MCP server tool call to fetch CI/CD job logs" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734501/g4mfs2zdrffzb9pd8v09.png" /></p><p>In the GitLab UI, you can use <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/fix_pipeline/" rel="">Fix CI/CD Pipeline Flow</a>, or ask the <a href="https://docs.gitlab.com/user/duo_agent_platform/agents/foundational_agents/ci_expert_agent/" rel="">CI Expert agent</a> for help.</p><h3 id="cicd-and-review-evidence">CI/CD and review evidence</h3><p>GitLab CI/CD, GitLab Duo Code Review, security scanning, and AI-assisted impact analysis provide the final evidence in the merge request. Human review still matters most at the subtle boundaries: Any intentional behavior difference should be explicit in the merge request, not discovered after deployment.</p><p><img alt="Developer Flow with impact analysis" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734549/jxqds2bwzcedn7yafdvr.png" /></p><p>Watch this video to learn how Cursor and GitLab modernize the collector&#39;s HTTP library to Java 21:</p><figure className="video_container">
  <iframe src="https://www.youtube.com/embed/AZEDvb474n0" frameBorder="0" allowFullScreen="true"> </iframe></figure><h2 id="tips-for-cursor-and-gitlab">Tips for Cursor and GitLab</h2><p>Here are some tips to use Cursor and GitLab together.</p><h3 id="automate-impact-analysis-for-modernization-breaking-changes">Automate impact analysis for modernization breaking changes</h3><p>The <a href="https://www.youtube.com/watch?v=AZEDvb474n0" rel="">third use case</a> shows the Developer Flow conducting a breaking change impact analysis. You can turn this workflow into an automated <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/custom/" rel="">custom flow</a> that gets triggered when a merge request is ready, or the pipeline is OK. Additional context can be retrieved from <a href="https://about.gitlab.com/blog/introducing-gitlab-orbit/" rel="">GitLab Orbit</a>, which provides a context graph across code, work items, merge requests, vulnerabilities, and more.</p><p>You can start inspecting the example flow in the AI Catalog: <a href="https://gitlab.com/explore/ai-catalog/flows/1013017/" rel="">MR Impact analysis (Orbit)</a>. Thanks to my teammate Fatima Sarah Kalid for the inspiration. Custom flows are generally available in <a href="https://about.gitlab.com/blog/multi-step-software-delivery-with-agentic-flows/" rel="">GitLab 19.2</a>.</p><p><img alt="Custom flow in the AI Catalog" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734604/nk2faraxdhghiktndrs5.png" /></p><p><img alt="Merge request impact analysis with a custom flow in GitLab Duo Agent Platform, and Orbit" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784734740/app3pnjwqzoyulojkomq.png" /></p><h3 id="document-guidelines-and-boundaries-for-agents">Document guidelines and boundaries for agents</h3><h4 id="agentsmd-for-java">AGENTS.md for Java</h4><p>An <a href="https://docs.gitlab.com/user/duo_agent_platform/customize/agents_md/" rel=""><code>AGENTS.md</code></a> file helps Cursor and other coding agents understand the project architecture, commands, code style, testing expectations, and boundaries. Keep these instructions close to the code and make them concrete enough to verify.</p><p>Example from the <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector/-/blob/main/AGENTS.md?ref_type=heads" rel="">AGENTS.md in the Java HTTP metrics collector project</a>.</p><pre className="language-markdown shiki shiki-themes github-light" code="# Java HTTP Metrics Collector - Agent Instructions

## Overview

The Java HTTP Metrics Collector is a REST API metrics collection sensor for the Tanuki IoT Platform. It monitors HTTP endpoints, collects performance metrics (response time, status codes, content length), and exports them in Prometheus text format. The application runs continuously with configurable collection intervals and supports concurrent endpoint monitoring.

## Code Style and Standards

### Java 8 Compatibility

- Do not modernize Java 8 code to Java 11+ features unless there is a GitLab issue or task specifically requesting modernization
- Target Java 8 for source and compilation: `maven.compiler.source=1.8` and `maven.compiler.target=1.8`
- Use Java 8 compatible patterns (e.g., anonymous inner classes instead of lambdas where appropriate)

### Documentation

- All public classes must have Javadoc describing purpose and usage
- All public methods must have Javadoc with `@param` and `@return` tags
- Include code examples in main class Javadoc

### Class Organization

- **Main entry point**: `HttpMetricsCollector` - orchestrates configuration loading, metric collection, and export
- **Collector**: `HttpCollector` - performs HTTP requests and collects metrics
- **Exporter**: `PrometheusExporter` - exports metrics in Prometheus text format
- **Models**: `CollectorConfig`, `EndpointConfig`, `HttpMetric` - data transfer objects

### Dependency Management

- Always use Maven for dependency management
- Use property-based version management for dependencies (e.g., `${jackson.version}`)
- Keep dependencies up-to-date in `pom.xml`

### Error Handling

- Use try-catch blocks with proper resource management (try-with-resources where applicable)
- Log errors using SLF4J Logger
- Gracefully handle configuration loading failures
- Implement proper shutdown hooks for resource cleanup

### Concurrency

- Use `ExecutorService` for concurrent HTTP requests
- Thread pool size is limited to the minimum of endpoint count and 10
- Properly shutdown executor service with timeout handling
- Use `Future` objects to collect results from concurrent tasks
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="surfw"># Java HTTP Metrics Collector - Agent Instructions
</span></span><span class="line" line="2"><span emptyLinePlaceholder>
</span></span><span class="line" line="3"><span class="surfw">## Overview
</span></span><span class="line" line="4"><span emptyLinePlaceholder>
</span></span><span class="line" line="5"><span class="sgsFI">The Java HTTP Metrics Collector is a REST API metrics collection sensor for the Tanuki IoT Platform. It monitors HTTP endpoints, collects performance metrics (response time, status codes, content length), and exports them in Prometheus text format. The application runs continuously with configurable collection intervals and supports concurrent endpoint monitoring.
</span></span><span class="line" line="6"><span emptyLinePlaceholder>
</span></span><span class="line" line="7"><span class="surfw">## Code Style and Standards
</span></span><span class="line" line="8"><span emptyLinePlaceholder>
</span></span><span class="line" line="9"><span class="surfw">### Java 8 Compatibility
</span></span><span class="line" line="10"><span emptyLinePlaceholder>
</span></span><span class="line" line="11"><span class="sqxcx">-</span><span class="sgsFI"> Do not modernize Java 8 code to Java 11+ features unless there is a GitLab issue or task specifically requesting modernization
</span></span><span class="line" line="12"><span class="sqxcx">-</span><span class="sgsFI"> Target Java 8 for source and compilation: </span><span class="sYu0t">`maven.compiler.source=1.8`</span><span class="sgsFI"> and </span><span class="sYu0t">`maven.compiler.target=1.8`
</span></span><span class="line" line="13"><span class="sqxcx">-</span><span class="sgsFI"> Use Java 8 compatible patterns (e.g., anonymous inner classes instead of lambdas where appropriate)
</span></span><span class="line" line="14"><span emptyLinePlaceholder>
</span></span><span class="line" line="15"><span class="surfw">### Documentation
</span></span><span class="line" line="16"><span emptyLinePlaceholder>
</span></span><span class="line" line="17"><span class="sqxcx">-</span><span class="sgsFI"> All public classes must have Javadoc describing purpose and usage
</span></span><span class="line" line="18"><span class="sqxcx">-</span><span class="sgsFI"> All public methods must have Javadoc with </span><span class="sYu0t">`@param`</span><span class="sgsFI"> and </span><span class="sYu0t">`@return`</span><span class="sgsFI"> tags
</span></span><span class="line" line="19"><span class="sqxcx">-</span><span class="sgsFI"> Include code examples in main class Javadoc
</span></span><span class="line" line="20"><span emptyLinePlaceholder>
</span></span><span class="line" line="21"><span class="surfw">### Class Organization
</span></span><span class="line" line="22"><span emptyLinePlaceholder>
</span></span><span class="line" line="23"><span class="sqxcx">-</span><span class="sbYKK"> **Main entry point**</span><span class="sgsFI">: </span><span class="sYu0t">`HttpMetricsCollector`</span><span class="sgsFI"> - orchestrates configuration loading, metric collection, and export
</span></span><span class="line" line="24"><span class="sqxcx">-</span><span class="sbYKK"> **Collector**</span><span class="sgsFI">: </span><span class="sYu0t">`HttpCollector`</span><span class="sgsFI"> - performs HTTP requests and collects metrics
</span></span><span class="line" line="25"><span class="sqxcx">-</span><span class="sbYKK"> **Exporter**</span><span class="sgsFI">: </span><span class="sYu0t">`PrometheusExporter`</span><span class="sgsFI"> - exports metrics in Prometheus text format
</span></span><span class="line" line="26"><span class="sqxcx">-</span><span class="sbYKK"> **Models**</span><span class="sgsFI">: </span><span class="sYu0t">`CollectorConfig`</span><span class="sgsFI">, </span><span class="sYu0t">`EndpointConfig`</span><span class="sgsFI">, </span><span class="sYu0t">`HttpMetric`</span><span class="sgsFI"> - data transfer objects
</span></span><span class="line" line="27"><span emptyLinePlaceholder>
</span></span><span class="line" line="28"><span class="surfw">### Dependency Management
</span></span><span class="line" line="29"><span emptyLinePlaceholder>
</span></span><span class="line" line="30"><span class="sqxcx">-</span><span class="sgsFI"> Always use Maven for dependency management
</span></span><span class="line" line="31"><span class="sqxcx">-</span><span class="sgsFI"> Use property-based version management for dependencies (e.g., </span><span class="sYu0t">`${jackson.version}`</span><span class="sgsFI">)
</span></span><span class="line" line="32"><span class="sqxcx">-</span><span class="sgsFI"> Keep dependencies up-to-date in </span><span class="sYu0t">`pom.xml`
</span></span><span class="line" line="33"><span emptyLinePlaceholder>
</span></span><span class="line" line="34"><span class="surfw">### Error Handling
</span></span><span class="line" line="35"><span emptyLinePlaceholder>
</span></span><span class="line" line="36"><span class="sqxcx">-</span><span class="sgsFI"> Use try-catch blocks with proper resource management (try-with-resources where applicable)
</span></span><span class="line" line="37"><span class="sqxcx">-</span><span class="sgsFI"> Log errors using SLF4J Logger
</span></span><span class="line" line="38"><span class="sqxcx">-</span><span class="sgsFI"> Gracefully handle configuration loading failures
</span></span><span class="line" line="39"><span class="sqxcx">-</span><span class="sgsFI"> Implement proper shutdown hooks for resource cleanup
</span></span><span class="line" line="40"><span emptyLinePlaceholder>
</span></span><span class="line" line="41"><span class="surfw">### Concurrency
</span></span><span class="line" line="42"><span emptyLinePlaceholder>
</span></span><span class="line" line="43"><span class="sqxcx">-</span><span class="sgsFI"> Use </span><span class="sYu0t">`ExecutorService`</span><span class="sgsFI"> for concurrent HTTP requests
</span></span><span class="line" line="44"><span class="sqxcx">-</span><span class="sgsFI"> Thread pool size is limited to the minimum of endpoint count and 10
</span></span><span class="line" line="45"><span class="sqxcx">-</span><span class="sgsFI"> Properly shutdown executor service with timeout handling
</span></span><span class="line" line="46"><span class="sqxcx">-</span><span class="sgsFI"> Use </span><span class="sYu0t">`Future`</span><span class="sgsFI"> objects to collect results from concurrent tasks
</span></span></code></pre><h4 id="code-review-instructions-for-java">Code review instructions for Java</h4><p>GitLab Duo Code Review Flow helps maintain style guides and boundaries. It expects specific instructions in the <a href="https://docs.gitlab.com/user/duo_agent_platform/customize/review_instructions/" rel=""><code>.gitlab/duo/mr-review-instructions.yaml</code> file</a>, for example, for <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector/-/blob/main/.gitlab/duo/mr-review-instructions.yaml?ref_type=heads" rel="">Java</a>:</p><pre className="language-yaml shiki shiki-themes github-light" code="# Custom instructions for GitLab Duo Code Review

instructions:
  # General guidelines

  - name: Code Review
    instructions: |
      1. Focus on correctness and performance
      2. Ensure code comments and documentation are clear and concise
      3. Be respectful and constructive in comments

  - name: CI/CD Configuration
    fileFilters:
      - &quot;.gitlab-ci.yml&quot;
    instructions: |
      1. Do not use YAML anchors
      2. Always use rules in jobs, avoid using `only`

  # Java style guide

  - name: Java Style Guide
    fileFilters:
      - &quot;**/*.java&quot;
    instructions: |
      1. Do not modernize Java 8 code to Java 11+ features, unless there is a GitLab issue or task specifically requesting modernization
      2. All public classes must have Javadoc describing purpose and usage
      3. All public methods must have Javadoc with @param and @return tags
      4. Include code examples in main class Javadoc
      5. All public methods must have at least one test case
      6. Use httpbun.com for test endpoints (status codes, delays, JSON responses)
" language="yaml" meta="" style=""><code><span class="line" line="1"><span class="sAwPA"># Custom instructions for GitLab Duo Code Review
</span></span><span class="line" line="2"><span emptyLinePlaceholder>
</span></span><span class="line" line="3"><span class="shJU0">instructions</span><span class="sgsFI">:
</span></span><span class="line" line="4"><span class="sAwPA">  # General guidelines
</span></span><span class="line" line="5"><span emptyLinePlaceholder>
</span></span><span class="line" line="6"><span class="sgsFI">  - </span><span class="shJU0">name</span><span class="sgsFI">: </span><span class="sYBdl">Code Review
</span></span><span class="line" line="7"><span class="shJU0">    instructions</span><span class="sgsFI">: </span><span class="sD7c4">|
</span></span><span class="line" line="8"><span class="sYBdl">      1. Focus on correctness and performance
</span></span><span class="line" line="9"><span class="sYBdl">      2. Ensure code comments and documentation are clear and concise
</span></span><span class="line" line="10"><span class="sYBdl">      3. Be respectful and constructive in comments
</span></span><span class="line" line="11"><span emptyLinePlaceholder>
</span></span><span class="line" line="12"><span class="sgsFI">  - </span><span class="shJU0">name</span><span class="sgsFI">: </span><span class="sYBdl">CI/CD Configuration
</span></span><span class="line" line="13"><span class="shJU0">    fileFilters</span><span class="sgsFI">:
</span></span><span class="line" line="14"><span class="sgsFI">      - </span><span class="sYBdl">&quot;.gitlab-ci.yml&quot;
</span></span><span class="line" line="15"><span class="shJU0">    instructions</span><span class="sgsFI">: </span><span class="sD7c4">|
</span></span><span class="line" line="16"><span class="sYBdl">      1. Do not use YAML anchors
</span></span><span class="line" line="17"><span class="sYBdl">      2. Always use rules in jobs, avoid using `only`
</span></span><span class="line" line="18"><span emptyLinePlaceholder>
</span></span><span class="line" line="19"><span class="sAwPA">  # Java style guide
</span></span><span class="line" line="20"><span emptyLinePlaceholder>
</span></span><span class="line" line="21"><span class="sgsFI">  - </span><span class="shJU0">name</span><span class="sgsFI">: </span><span class="sYBdl">Java Style Guide
</span></span><span class="line" line="22"><span class="shJU0">    fileFilters</span><span class="sgsFI">:
</span></span><span class="line" line="23"><span class="sgsFI">      - </span><span class="sYBdl">&quot;**/*.java&quot;
</span></span><span class="line" line="24"><span class="shJU0">    instructions</span><span class="sgsFI">: </span><span class="sD7c4">|
</span></span><span class="line" line="25"><span class="sYBdl">      1. Do not modernize Java 8 code to Java 11+ features, unless there is a GitLab issue or task specifically requesting modernization
</span></span><span class="line" line="26"><span class="sYBdl">      2. All public classes must have Javadoc describing purpose and usage
</span></span><span class="line" line="27"><span class="sYBdl">      3. All public methods must have Javadoc with @param and @return tags
</span></span><span class="line" line="28"><span class="sYBdl">      4. Include code examples in main class Javadoc
</span></span><span class="line" line="29"><span class="sYBdl">      5. All public methods must have at least one test case
</span></span><span class="line" line="30"><span class="sYBdl">      6. Use httpbun.com for test endpoints (status codes, delays, JSON responses)
</span></span></code></pre><p>In the process of modernizing the code, the first guideline with Java 8 enforcement will need to be updated.</p><h3 id="turn-a-proven-workflow-into-an-agentic-skill">Turn a proven workflow into an agentic skill</h3><p>When a specialized workflow becomes repeatable, capture it in an <a href="https://docs.gitlab.com/user/duo_agent_platform/customize/agent_skills/" rel="">agentic skill</a>. Skills are loaded on demand, not populating the context window by default.</p><p>Start with working CI/CD, tests, and reviewed decisions so the agentic skill reflects proven practice rather than an untested plan. <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector/-/work_items/24" rel="">Issue 24</a> in the modernization epic captures the approach in a focused Java 21+ modernization agentic skill. This adds value beyond the current merge request: Future agent sessions can reuse the same safety boundaries instead of reconstructing them from earlier discussions.</p><p>Try this example skill implementation, inspired by the existing <a href="https://gitlab.com/gitlab-da/demo-environments/tanuki-iot-platform/sensors/java-http-metrics-collector/-/blob/main/skills/java8-maven-maintenance/SKILL.md?ref_type=heads" rel="">Java 8 Maven maintenance skill</a>:</p><pre className="language-markdown shiki shiki-themes github-light" code="---
name: java21-modernization
description: &gt;-
  Guide incremental Java 8 to Java 21+ modernization for the HTTP metrics
  collector. Use when a GitLab work item asks for Java 21 CI visibility,
  runtime/image upgrades, HttpClient migration, dependency or source API
  modernization, or review of maint-java-21 style merge requests. Do not use
  for routine Java 8 maintenance; prefer java8-maven-maintenance instead.
compatibility: Requires Maven, Docker Compose, and access to the owning GitLab work item.
---

# Java 21 Modernization

## Overview

Modernize in small, reviewable steps. The owning work item is authoritative.
Preserve collector → Rust metrics-store behavior unless the issue says otherwise.

Companion skill: `skills/java8-maven-maintenance/` for the Java 8 default path.

## Before editing

1. Read the owning issue/epic, `AGENTS.md`, `.gitlab-ci.yml`, `pom.xml`,
   `Dockerfile`, and affected tests.
2. Record the current baseline:
   - `maven.compiler.source` / `target`
   - default CI image vs any `*:java-21` jobs
   - container base image
   - observable CLI/Compose behavior
3. Classify the change into **one** lane:
   - CI visibility only
   - runtime / image switch
   - source / API modernization
   - dependency upgrade
   - tests / contract checks

Do not combine lanes in one MR unless the work item explicitly requires it.

## Workflow

Copy and track:

```text
Modernization progress:
- [ ] Baseline recorded
- [ ] Scoped to owning work item
- [ ] Target-JDK CI evidence available before JDK-only APIs
- [ ] Java 8 lane preserved until exit criteria say otherwise
- [ ] Unit / IT / Compose checks run
- [ ] MR documents risks, rollback, human decisions
```

## Guardrails

- Do not remove Java 8 compatibility unless the work item authorizes it.
- Do not introduce Java 21-only APIs before target-JDK CI evidence exists.
- Do not mix runtime upgrades with unrelated refactors.
- Do not claim performance wins without measurements.
- Preserve the Java → Rust API and authentication contract.
- Stop for a human decision when support policy, rollback, data format, or downstream compatibility is unclear.

## Validation

```bash
mvn -Dmaven.repo.local=.m2/repository test
mvn -Dmaven.repo.local=.m2/repository clean package
```

If Compose or container files change:

```bash
docker compose config --quiet
TANUKI_INGESTION_TOKEN=replace-me docker compose up -d --build
# confirm metric_sample logs and authenticated ingest still work
docker compose down -v
```

## Completion report

In the MR description, include:

1. Baseline before the change
2. Lane changed (CI / runtime / source / deps / tests)
3. Evidence run (commands + CI jobs)
4. Remaining risks and rollback
5. Human decisions still open

## Out of scope

- Broad &quot;modernize everything to Java 21&quot; prompts
- HTTP endpoint semantics unrelated to the JDK migration
  (use `skills/http-endpoint-collector-behavior/`)
- Security triage unrelated to the migration slice
  (use `skills/security-triage-java-sensor/`)
" language="markdown" meta="" style=""><code><span class="line" line="1"><span class="sgsFI">---
</span></span><span class="line" line="2"><span class="shJU0">name</span><span class="sgsFI">: </span><span class="sYBdl">java21-modernization
</span></span><span class="line" line="3"><span class="shJU0">description</span><span class="sgsFI">: </span><span class="sD7c4">&gt;-
</span></span><span class="line" line="4"><span class="sYBdl">  Guide incremental Java 8 to Java 21+ modernization for the HTTP metrics
</span></span><span class="line" line="5"><span class="sYBdl">  collector. Use when a GitLab work item asks for Java 21 CI visibility,
</span></span><span class="line" line="6"><span class="sYBdl">  runtime/image upgrades, HttpClient migration, dependency or source API
</span></span><span class="line" line="7"><span class="sYBdl">  modernization, or review of maint-java-21 style merge requests. Do not use
</span></span><span class="line" line="8"><span class="sYBdl">  for routine Java 8 maintenance; prefer java8-maven-maintenance instead.
</span></span><span class="line" line="9"><span class="shJU0">compatibility</span><span class="sgsFI">: </span><span class="sYBdl">Requires Maven, Docker Compose, and access to the owning GitLab work item.
</span></span><span class="line" line="10"><span class="sgsFI">---
</span></span><span class="line" line="11"><span emptyLinePlaceholder>
</span></span><span class="line" line="12"><span class="surfw"># Java 21 Modernization
</span></span><span class="line" line="13"><span emptyLinePlaceholder>
</span></span><span class="line" line="14"><span class="surfw">## Overview
</span></span><span class="line" line="15"><span emptyLinePlaceholder>
</span></span><span class="line" line="16"><span class="sgsFI">Modernize in small, reviewable steps. The owning work item is authoritative.
</span></span><span class="line" line="17"><span class="sgsFI">Preserve collector → Rust metrics-store behavior unless the issue says otherwise.
</span></span><span class="line" line="18"><span emptyLinePlaceholder>
</span></span><span class="line" line="19"><span class="sgsFI">Companion skill: </span><span class="sYu0t">`skills/java8-maven-maintenance/`</span><span class="sgsFI"> for the Java 8 default path.
</span></span><span class="line" line="20"><span emptyLinePlaceholder>
</span></span><span class="line" line="21"><span class="surfw">## Before editing
</span></span><span class="line" line="22"><span emptyLinePlaceholder>
</span></span><span class="line" line="23"><span class="sqxcx">1.</span><span class="sgsFI"> Read the owning issue/epic, </span><span class="sYu0t">`AGENTS.md`</span><span class="sgsFI">, </span><span class="sYu0t">`.gitlab-ci.yml`</span><span class="sgsFI">, </span><span class="sYu0t">`pom.xml`</span><span class="sgsFI">,
</span></span><span class="line" line="24"><span class="sYu0t">   `Dockerfile`</span><span class="sgsFI">, and affected tests.
</span></span><span class="line" line="25"><span class="sqxcx">2.</span><span class="sgsFI"> Record the current baseline:
</span></span><span class="line" line="26"><span class="sqxcx">   -</span><span class="sYu0t"> `maven.compiler.source`</span><span class="sgsFI"> / </span><span class="sYu0t">`target`
</span></span><span class="line" line="27"><span class="sqxcx">   -</span><span class="sgsFI"> default CI image vs any </span><span class="sYu0t">`*:java-21`</span><span class="sgsFI"> jobs
</span></span><span class="line" line="28"><span class="sqxcx">   -</span><span class="sgsFI"> container base image
</span></span><span class="line" line="29"><span class="sqxcx">   -</span><span class="sgsFI"> observable CLI/Compose behavior
</span></span><span class="line" line="30"><span class="sqxcx">3.</span><span class="sgsFI"> Classify the change into </span><span class="sbYKK">**one**</span><span class="sgsFI"> lane:
</span></span><span class="line" line="31"><span class="sqxcx">   -</span><span class="sgsFI"> CI visibility only
</span></span><span class="line" line="32"><span class="sqxcx">   -</span><span class="sgsFI"> runtime / image switch
</span></span><span class="line" line="33"><span class="sqxcx">   -</span><span class="sgsFI"> source / API modernization
</span></span><span class="line" line="34"><span class="sqxcx">   -</span><span class="sgsFI"> dependency upgrade
</span></span><span class="line" line="35"><span class="sqxcx">   -</span><span class="sgsFI"> tests / contract checks
</span></span><span class="line" line="36"><span emptyLinePlaceholder>
</span></span><span class="line" line="37"><span class="sgsFI">Do not combine lanes in one MR unless the work item explicitly requires it.
</span></span><span class="line" line="38"><span emptyLinePlaceholder>
</span></span><span class="line" line="39"><span class="surfw">## Workflow
</span></span><span class="line" line="40"><span emptyLinePlaceholder>
</span></span><span class="line" line="41"><span class="sgsFI">Copy and track:
</span></span><span class="line" line="42"><span emptyLinePlaceholder>
</span></span><span class="line" line="43"><span class="sgsFI">```text
</span></span><span class="line" line="44"><span class="sgsFI">Modernization progress:
</span></span><span class="line" line="45"><span class="sgsFI">- [ ] Baseline recorded
</span></span><span class="line" line="46"><span class="sgsFI">- [ ] Scoped to owning work item
</span></span><span class="line" line="47"><span class="sgsFI">- [ ] Target-JDK CI evidence available before JDK-only APIs
</span></span><span class="line" line="48"><span class="sgsFI">- [ ] Java 8 lane preserved until exit criteria say otherwise
</span></span><span class="line" line="49"><span class="sgsFI">- [ ] Unit / IT / Compose checks run
</span></span><span class="line" line="50"><span class="sgsFI">- [ ] MR documents risks, rollback, human decisions
</span></span><span class="line" line="51"><span class="sgsFI">```
</span></span><span class="line" line="52"><span emptyLinePlaceholder>
</span></span><span class="line" line="53"><span class="surfw">## Guardrails
</span></span><span class="line" line="54"><span emptyLinePlaceholder>
</span></span><span class="line" line="55"><span class="sqxcx">-</span><span class="sgsFI"> Do not remove Java 8 compatibility unless the work item authorizes it.
</span></span><span class="line" line="56"><span class="sqxcx">-</span><span class="sgsFI"> Do not introduce Java 21-only APIs before target-JDK CI evidence exists.
</span></span><span class="line" line="57"><span class="sqxcx">-</span><span class="sgsFI"> Do not mix runtime upgrades with unrelated refactors.
</span></span><span class="line" line="58"><span class="sqxcx">-</span><span class="sgsFI"> Do not claim performance wins without measurements.
</span></span><span class="line" line="59"><span class="sqxcx">-</span><span class="sgsFI"> Preserve the Java → Rust API and authentication contract.
</span></span><span class="line" line="60"><span class="sqxcx">-</span><span class="sgsFI"> Stop for a human decision when support policy, rollback, data format, or downstream compatibility is unclear.
</span></span><span class="line" line="61"><span emptyLinePlaceholder>
</span></span><span class="line" line="62"><span class="surfw">## Validation
</span></span><span class="line" line="63"><span emptyLinePlaceholder>
</span></span><span class="line" line="64"><span class="sgsFI">```bash
</span></span><span class="line" line="65"><span class="s7eDp">mvn</span><span class="sYu0t"> -Dmaven.repo.local=.m2/repository</span><span class="sYBdl"> test
</span></span><span class="line" line="66"><span class="s7eDp">mvn</span><span class="sYu0t"> -Dmaven.repo.local=.m2/repository</span><span class="sYBdl"> clean</span><span class="sYBdl"> package
</span></span><span class="line" line="67"><span class="sgsFI">```
</span></span><span class="line" line="68"><span emptyLinePlaceholder>
</span></span><span class="line" line="69"><span class="sgsFI">If Compose or container files change:
</span></span><span class="line" line="70"><span emptyLinePlaceholder>
</span></span><span class="line" line="71"><span class="sgsFI">```bash
</span></span><span class="line" line="72"><span class="s7eDp">docker</span><span class="sYBdl"> compose</span><span class="sYBdl"> config</span><span class="sYu0t"> --quiet
</span></span><span class="line" line="73"><span class="sgsFI">TANUKI_INGESTION_TOKEN</span><span class="sD7c4">=</span><span class="sYBdl">replace-me</span><span class="s7eDp"> docker</span><span class="sYBdl"> compose</span><span class="sYBdl"> up</span><span class="sYu0t"> -d</span><span class="sYu0t"> --build
</span></span><span class="line" line="74"><span class="sAwPA"># confirm metric_sample logs and authenticated ingest still work
</span></span><span class="line" line="75"><span class="s7eDp">docker</span><span class="sYBdl"> compose</span><span class="sYBdl"> down</span><span class="sYu0t"> -v
</span></span><span class="line" line="76"><span class="sgsFI">```
</span></span><span class="line" line="77"><span emptyLinePlaceholder>
</span></span><span class="line" line="78"><span class="surfw">## Completion report
</span></span><span class="line" line="79"><span emptyLinePlaceholder>
</span></span><span class="line" line="80"><span class="sgsFI">In the MR description, include:
</span></span><span class="line" line="81"><span emptyLinePlaceholder>
</span></span><span class="line" line="82"><span class="sqxcx">1.</span><span class="sgsFI"> Baseline before the change
</span></span><span class="line" line="83"><span class="sqxcx">2.</span><span class="sgsFI"> Lane changed (CI / runtime / source / deps / tests)
</span></span><span class="line" line="84"><span class="sqxcx">3.</span><span class="sgsFI"> Evidence run (commands + CI jobs)
</span></span><span class="line" line="85"><span class="sqxcx">4.</span><span class="sgsFI"> Remaining risks and rollback
</span></span><span class="line" line="86"><span class="sqxcx">5.</span><span class="sgsFI"> Human decisions still open
</span></span><span class="line" line="87"><span emptyLinePlaceholder>
</span></span><span class="line" line="88"><span class="surfw">## Out of scope
</span></span><span class="line" line="89"><span emptyLinePlaceholder>
</span></span><span class="line" line="90"><span class="sqxcx">-</span><span class="sgsFI"> Broad &quot;modernize everything to Java 21&quot; prompts
</span></span><span class="line" line="91"><span class="sqxcx">-</span><span class="sgsFI"> HTTP endpoint semantics unrelated to the JDK migration
</span></span><span class="line" line="92"><span class="sgsFI">  (use </span><span class="sYu0t">`skills/http-endpoint-collector-behavior/`</span><span class="sgsFI">)
</span></span><span class="line" line="93"><span class="sqxcx">-</span><span class="sgsFI"> Security triage unrelated to the migration slice
</span></span><span class="line" line="94"><span class="sgsFI">  (use </span><span class="sYu0t">`skills/security-triage-java-sensor/`</span><span class="sgsFI">)
</span></span></code></pre><h2 id="summary">Summary</h2><p>The three use cases in this tutorial build on each other. Cursor fixed an accepted end-to-end test failure using repository context alone. Then the GitLab MCP server brought in the modernization plan, so Cursor could put quality gates in place and close the loop on Duo review feedback directly from the IDE. Finally, Cursor made one bounded Java 21 change, replacing HttpURLConnection with a reusable HttpClient, backed by focused tests, cross-service ingestion runs, pipeline, security scans, software bill of materials, review evidence, and impact analysis.</p><p>A legacy Java 8 codebase does not get safer to modernize just because an agent is writing the code. It gets safer because every change is scoped, reviewed, tested against Java 8 and Java 21, and traceable back to a work item with the decisions and evidence behind it. Cursor handles the implementation. GitLab handles the proof. Together, they make the migration something a team can trust.</p><p>If you want to try this workflow, start with one test that exposes an accepted failure in a legacy application. Make that test reliable, capture the larger modernization plan in GitLab, and choose one boundary you can change and prove independently. That gives the agent a focused task and gives the team evidence they can review.</p><blockquote><p>If you are not using GitLab Duo Agent Platform today, you can start with <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">a free trial</a>.</p><p>If you are already using GitLab in the free tier, you can sign up for GitLab Duo Agent Platform by <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#for-the-free-tier-on-gitlabcom" rel="">following a few simple steps</a>.</p><p>And if you are an existing subscriber to GitLab Premium or Ultimate, you can get started simply by <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">turning on Duo Agent Platform</a> and start using the GitLab Credits <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits" rel="">that are included</a> with your subscription.</p></blockquote><style>html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}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 .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 .shJU0, html code.shiki .shJU0{--shiki-default:#22863A}html pre.shiki code .surfw, html code.shiki .surfw{--shiki-default:#005CC5;--shiki-default-font-weight:bold}html pre.shiki code .sqxcx, html code.shiki .sqxcx{--shiki-default:#E36209}html pre.shiki code .sbYKK, html code.shiki .sbYKK{--shiki-default:#24292E;--shiki-default-font-weight:bold}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}</style>]]></content>
        <author>
            <name>Michael Friedrich</name>
            <uri>https://about.gitlab.com/blog/authors/michael-friedrich/</uri>
        </author>
        <published>2026-07-22T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Automate work item assignment with a "Work item created" trigger]]></title>
        <id>https://about.gitlab.com/blog/how-to-use-a-work-item-created-trigger/</id>
        <link href="https://about.gitlab.com/blog/how-to-use-a-work-item-created-trigger/"/>
        <updated>2026-07-20T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>A new, event-driven trigger in <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a> lets flows fire the moment a work item is created, turning triage and assignment from a manual, all-day chore into automation that runs in seconds. This comprehensive guide shows you how to use the &quot;Work item created&quot; trigger and follow along with this video demonstration:</p><iframe width="560" height="315" src="https://www.youtube.com/embed/WNDYRZpOeOo?si=o_n6IBoyeQO5UhDp" title="YouTube video player" frameBorder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerPolicy="strict-origin-when-cross-origin" allowFullScreen></iframe><p>See the flow fire, route, and assign in real time — and imagine what continuous, hands-off automation could do for your own projects.</p><h2 id="the-problem-assignment-doesnt-scale-by-hand">The problem: Assignment doesn&#39;t scale by hand</h2><p>Assigning work manually across projects is harder than it looks. It&#39;s not just a single decision; it’s dozens of them, every single day. For every new issue that pops up, someone has to pause, check team capacity, balance current workloads against incoming tasks, and then decide where that item should go. Factor in meetings, breaks, or PTO, and the whole process can lengthen even more. While this works at a small scale, it quickly falls apart as volume grows, leading to delayed triage, uneven work distribution, and team leads burning their time on routing tasks rather than tackling higher-value work.</p><p>Until recently, that friction was baked into how flows worked. Every <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/" rel="">GitLab Duo Flow</a> required a human action in the UI (e.g. a mention, an assignment, or an assign-reviewer event) to get started. Driving flows programmatically or firing them the instant something happened wasn&#39;t possible without someone manually pulling the trigger. So even a well-built assignment flow still waited on a person to kick it off.</p><h2 id="how-the-work-item-created-trigger-helps">How the &quot;Work item created&quot; trigger helps</h2><p>The &quot;Work item created&quot; trigger closes that gap. It fires automatically the moment a new work item is created in a project, with no manual handoff required. Instead of a person noticing the issue, evaluating the team’s workload, and assigning it, a flow springs into action on its own and does the routing for you. With triggers, flows run when the conditions your organization defines are met — continuously, in the background — while your developers stay focused on the work that actually requires judgment.</p><h2 id="value-and-benefits">Value and benefits</h2><p>The &quot;Work item created&quot; trigger is beneficial in the following ways:</p><p><strong>Instant, hands-off triage</strong><br />
Assignment and routing happen the second a work item is created, not whenever someone gets around to it.</p><p><strong>Scales to any volume</strong><br />
Whether it&#39;s one issue or hundreds, the trigger handles them all in seconds without adding to anyone&#39;s workload.</p><p><strong>Smarter, balanced assignment</strong><br />
The flow can weigh each team member&#39;s current load and availability before assigning; the same judgment a person would apply, applied consistently.</p><p><strong>Frees your team from busywork</strong><br />
No more manually sorting through open work items to decide who has capacity; an agent makes the call with the same information you would.</p><h2 id="automatic-assignment-in-action-a-step-by-step-tutorial">Automatic assignment in action: A step-by-step tutorial</h2><p>To make this concrete, let’s walk through a real scenario using a project called <strong>Intra-account-transfers</strong>.</p><h3 id="_1-the-trigger-configuration">1. The trigger configuration</h3><p>We&#39;ve created a flow named &quot;Work item assigner&quot; and enabled it to run whenever a work item is created in that project.</p><p><img alt="“Work item assigner” flow enabled for project intra-account-transfers" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210850/Blog/Imported/test-work-item-trigger-blog-workflow-test/image5.png" title="“Work item assigner” flow enabled for project intra-account-transfers" /></p><h3 id="_2-how-the-flow-is-built">2. How the flow is built</h3><p>The &quot;Work item assigner&quot; flow uses two agents, each with its own detailed prompt spelling out the process to follow and the tools to use. The first agent uses <a href="https://about.gitlab.com/blog/introducing-gitlab-orbit/" rel="">GitLab Orbit</a> to determine the current workload of each resource across the organization. GitLab Orbit is the lifecycle context graph for software engineering that makes AI agents in Duo Agent Platform faster and more accurate.</p><p><img alt="Definition of first agent “determine_resource_with_least_open_work”" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210858/Blog/Imported/test-work-item-trigger-blog-workflow-test/image8.png" title="Definition of first agent “determine_resource_with_least_open_work”" /></p><p><img alt="Prompt of first agent" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210866/Blog/Imported/test-work-item-trigger-blog-workflow-test/image9.png" title="Prompt of first agent" /></p><p>The second agent identifies the person who is least loaded with open work items and assigns the new item to them.</p><p><img alt="Definition of second agent “assign_work_item_prompt”" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210875/Blog/Imported/test-work-item-trigger-blog-workflow-test/image4.png" title="Definition of second agent “assign_work_item_prompt”" /></p><p><img alt="Prompt of second agent" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210883/Blog/Imported/test-work-item-trigger-blog-workflow-test/image7.png" title="Prompt of second agent" /></p><p>Because the assignment logic lives inside the flow, the trigger is all that&#39;s needed to set the whole process in motion.</p><h3 id="_3-watching-the-trigger-fire">3. Watching the trigger fire</h3><p>3.1. We create a brand-new work item.</p><p><img alt="New issue being created" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210892/Blog/Imported/test-work-item-trigger-blog-workflow-test/image2.png" title="New issue being created" /></p><p>3.2. The moment the issue is created, the trigger fires and the &quot;Work item assigner&quot; flow starts on its own. From the flow activity log, you can follow its progress step by step: The first agent pulls the project information and uses GitLab Orbit tools to count each user&#39;s open work items across the top-level group,</p><p><img alt="First agent responds with count of open work items for each user in top group" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210901/Blog/Imported/test-work-item-trigger-blog-workflow-test/image6.png" title="First agent responds with count of open work items for each user in top group" /></p><p>The second agent then identifies the least-loaded teammate — in the demo, that&#39;s William — and carries out the actual assignment.</p><p><img alt="Second agents selects William as the assignee for the newly created issue" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210908/Blog/Imported/test-work-item-trigger-blog-workflow-test/image1.png" title="Second agents selects William as the assignee for the newly created issue" /></p><h3 id="_4-verifying-issue-has-been-assigned-to-least-loaded-individual">4. Verifying issue has been assigned to least loaded individual</h3><p>A quick trip back to the issue confirms it: The new work item has been assigned to William, automatically.</p><p><img alt="The updated issue showing William as its assignee" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1784210914/Blog/Imported/test-work-item-trigger-blog-workflow-test/image3.png" title="The updated issue showing William as its assignee" /></p><h3 id="_5-the-benefit-seen-end-to-end">5. The benefit, seen end to end</h3><p>The point this scenario drives home is the shift in who does the work. Instead of a person sorting through open work items to figure out who has capacity and then assigning the issue by hand, GitLab Duo Agent Platform&#39;s <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/custom/" rel="">custom flow</a> invoked by the &quot;Work item created&quot; trigger does all of it, in a matter of seconds. It frees the team from a routine decision that an agent can make with the exact same information a human would use, so people can focus their attention where it counts.</p><h3 id="_6-extra-credit">6. Extra credit</h3><p>Potential enhancements to this custom flow could be:</p><ul><li>Adding Model Context Protocol (<a href="https://about.gitlab.com/topics/ai/model-context-protocol/" rel="">MCP</a>) connectivity to your HR system (or PTO system) so that the agent can be improved to consider resources’ PTO dates when assigning a work item.</li><li>Adding MCP connectivity to your resources’ calendars so that the agent can be improved to consider resources’ availability when assigning a work item.</li></ul><h2 id="get-started">Get started</h2><p>Assigning incoming work at scale has always been a quiet drain: dozens of small decisions a day, each requiring someone to check workloads and availability before routing an issue — and a process that breaks down as volume grows. The &quot;Work item created&quot; trigger in GitLab Duo Agent Platform removes that bottleneck by firing a flow the instant a work item is created, with no manual handoff. As the step-by-step tutorial above shows, a two-agent flow powered by GitLab Orbit can read the team&#39;s real workload and assign each new item to the person best positioned to take it, all in seconds. The result is faster triage, more balanced workloads, and a team that&#39;s free to focus on the work that genuinely needs human judgment.</p><blockquote><p><a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">Start a free trial of GitLab Duo Agent Platform today.</a></p></blockquote>]]></content>
        <author>
            <name>Cesar Saavedra</name>
            <uri>https://about.gitlab.com/blog/authors/cesar-saavedra/</uri>
        </author>
        <published>2026-07-20T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[GitLab Transcend Hackathon: What developers built on GitLab Orbit]]></title>
        <id>https://about.gitlab.com/blog/gitlab-transcend-hackathon-orbit/</id>
        <link href="https://about.gitlab.com/blog/gitlab-transcend-hackathon-orbit/"/>
        <updated>2026-07-20T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>We gave a few thousand developers GitLab Orbit. Then we got out of the way. The community responded with creative solutions to real production problems slowing down their teams. <strong>The same problems you hit every week: What does this change break, which tests actually matter, and what will this migration really cost.</strong></p><p><a href="https://about.gitlab.com/gitlab-orbit/" rel="">GitLab Orbit</a> is a live, queryable graph of your code, merge requests, pipelines, deployments, and ownership, with every relationship between them kept current. Agents write code well but are bad at understanding the system around it. Answering the connecting questions (&quot;<em>what depends on this</em>,&quot; &quot;<em>which tests cover it</em>,&quot; &quot;<em>who owns the fallout</em>&quot;) used to mean an agent crawling files or an engineer digging across four tools. Orbit turns that into one query. Agents reach Orbit through Model Context Protocol (<a href="https://about.gitlab.com/topics/ai/model-context-protocol/" rel="">MCP</a>)
), engineers query it directly, and the answer comes back in seconds instead of hours. The <a href="https://about.gitlab.com/gitlab-orbit/" rel="">Orbit home page</a> has the full story. We wanted to see what people would build once that was theirs.</p><p>The hackathon drew 1,576 registered developers, and they shipped 265 eligible Showcase Track projects built on GitLab Orbit: agents, flows, and skills. Separately, 26 contributors merged 61 improvements straight into the Orbit codebase, adding language support, fixing bugs, and sharpening the docs. The community did not just build on Orbit. It made Orbit better.</p><h2 id="the-problems-people-reached-for">The problems people reached for</h2><p>Before scoring anything, one thing jumped out to us: If we sorted the submissions by what they actually do, the distribution would be lopsided.</p><p><strong>Seventy teams</strong> built a version of the same tool: <em>Tell me what this change could break before I merge it</em>. More than 30 built onboarding and comprehension aids: The <em>help me understand this codebase</em> problem. After that came incident root-cause, architecture drift, flaky-pipeline diagnosis, and tracing a CVE across repositories.</p><p>None of that is random. Engineers ask these questions constantly and answer them poorly because the answers used to be scattered across Git, CI, deploy tooling, and a few dashboards nobody trusts. Put it in one graph, and people go straight for it.</p><p>That is orchestration with context, not orchestration alone: speed, with control built in. And when dozens of independent teams reach for the same query without being told to, that is the signal a platform owner should read: The context is where the work actually happens. The bar was high in the crowded categories. Projects stood out by beating 68 other teams, or by going somewhere nobody else did.</p><h2 id="technological-implementation">Technological implementation</h2><p><strong>Winner: <a href="https://gitlab-transcend.devpost.com/submissions/1054521-sankofa" rel="">Sankofa</a>.</strong> Three agents, each triggered by a different moment in your day, all reading from GitLab Orbit. Open a merge request and Radar hands you the blast radius: downstream callers, affected pipelines, the team that owns the fallout. Get assigned an issue and Guide writes you a brief before you start. A vulnerability surfaces and Shield traces every path to it. The context arrives where you already are, and then gets out of your way.</p><blockquote><p>&quot;When a security vulnerability gets reported, teams spend days manually tracing how far it reaches, because nothing connects the dots automatically.&quot;</p><p>Lester K, Sankofa</p></blockquote><p>Shield does it in one pass over the graph.</p><p><strong>Runner-up:</strong> <a href="https://gitlab-transcend.devpost.com/submissions/1054106-stayed-shipped" rel="">Stayed Shipped</a>. It asks a question your dashboards cannot answer: Of the changes your AI agents merged last month, how many are still in production? It tracks whether a merged change survives or gets quietly fixed forward by a senior engineer, invisible to every standard metric.</p><h2 id="design-and-usability">Design and usability</h2><p><strong>Winner: <a href="https://gitlab-transcend.devpost.com/submissions/1062163-carver-the-migration-quoting-agent" rel="">Carver</a>.</strong> Carver prices a legacy migration before you commit to it. You say what you want to move; it reads GitLab Orbit&#39;s dependency graph and gives you a quote: how many units, how long, in what order, where the risk hides. What wins this category is the output. Carver gives you one line per unit, sized and risk-flagged, and expands the detail only when you ask. Moving AngularJS to Angular comes back as roughly nine weeks of human effort against ten dollars of generation cost, with the untested load-bearing service marked in red so you know where to look first.</p><blockquote><p>&quot;It checks Orbit and, if it doesn&#39;t find the service, it asks where the real code is.&quot;</p><p>Anes Mulalic, Carver</p></blockquote><p>That is why the agent refuses to invent a number it cannot ground.</p><p><strong>Runner-up:</strong> <a href="https://gitlab-transcend.devpost.com/submissions/1062651-marshal-autonomous-migration-assistant" rel="">Marshal</a>. Same territory, opposite approach: full autonomy. Declare one org-wide goal and it finds every affected repo through GitLab Orbit, sequences the work, and lands merge requests wave by wave, making sure no target drops.</p><h2 id="potential-impact">Potential impact</h2><p><strong>Winner: <a href="https://gitlab-transcend.devpost.com/submissions/1061837-crosscut" rel="">CrossCut</a>.</strong> CrossCut runs only the tests a change could actually break. Open a merge request and it pulls the changed symbols, walks GitLab Orbit&#39;s call graph to find the true transitive impact, and builds a pipeline that runs those tests and nothing else. No model in the loop, no guessing, just traversal. On a big or cross-repo suite that trims the CI payload by 90% or more, which pays for itself almost immediately.</p><blockquote><p>&quot;You need the call graph of the whole codebase to know which tests a change can reach. That is exactly what GitLab Orbit builds, so instead of guessing, we just ask the graph.&quot;</p><p>Pritesh Kumar, CrossCut</p></blockquote><p><strong>Runner-up:</strong> <a href="https://gitlab-transcend.devpost.com/submissions/1061548-orbitweaver" rel="">OrbitWeaver</a>. It does autonomous refactoring using GitLab Orbit&#39;s exact blast radius rather than vector similarity. It maps every affected file and edits them in dependency order, the cleanest argument for why a real graph beats fuzzy retrieval when getting it wrong means a red pipeline.</p><h2 id="quality-of-the-idea">Quality of the idea</h2><p><strong>Winner: <a href="https://gitlab-transcend.devpost.com/submissions/1056751-transcend" rel="">Transcend</a>.</strong> Most teams queried GitLab Orbit directly, which is the right move for most questions. Transcend built a second reasoning engine on top of it using the semantic web stack, OWL, SPARQL, and RDF, to reach the questions the native API cannot express in a single call. Transitive closure. Joins that leave your codebase and pull in the world&#39;s structured knowledge. Its demo asks which knowledge-graph-embedding methods a codebase implements, and gets back the class names plus the papers that inspired them, the authors, and the years, joined live to the code. Treating Orbit as a foundation to build on rather than an API to call was genuinely new here, and that is precisely what this category rewards.</p><p><strong>Runner-up:</strong> <a href="https://gitlab-transcend.devpost.com/submissions/1053916-universal-agent-os" rel="">Universal Agent OS</a>. It builds the governance layer around agents rather than the agent itself: Interview first, plan before coding, keep the evidence, and force validation. As agents write a larger share of code, keeping them accountable is about to become the real problem. It is the same problem GitLab Orbit&#39;s context makes visible everywhere else on this list: Agents move fast, someone still has to answer for what they did.</p><h2 id="contribute-track">Contribute Track</h2><p>The Contribute Track ran alongside the Showcase Track, and it was not peripheral work. Twenty-six contributors merged 61 merge requests straight into the GitLab Orbit codebase: language support for C++20 concepts, Go package declarations, Kotlin coroutines, and Ruby lambdas; ontology fixes; a SIGPIPE bug in CI; the first Orbit query tutorial; and documentation cleanups so the next person does not trip over <code>max_depth</code> versus <code>max_hops</code>. Nineteen earned a cash prize. All 26 earned swag credits.</p><p>Cash prizes went to the first 40 merged contributions, so this list is as much about speed as quality. These are the contributors who got a working change reviewed and merged before anyone else. Congratulations to this round&#39;s cash-prize winners:</p><p><a href="https://gitlab.com/achalbajpai" rel="">achalbajpai</a>, <a href="https://gitlab.com/aishahsofea" rel="">aishahsofea</a>, <a href="https://gitlab.com/AlphaTheGoat27" rel="">AlphaTheGoat27</a>, <a href="https://gitlab.com/anushkrishnav" rel="">anushkrishnav</a>, <a href="https://gitlab.com/bartekp854" rel="">bartekp854</a>, <a href="https://gitlab.com/bhandari.varun04" rel="">bhandari.varun04</a>, <a href="https://gitlab.com/ChaitanyaManik17" rel="">ChaitanyaManik17</a>, <a href="https://gitlab.com/fa220" rel="">fa220</a>, <a href="https://gitlab.com/fongse" rel="">fongse</a>, <a href="https://gitlab.com/gatlavishweshwarreddy26" rel="">gatlavishweshwarreddy26</a>, <a href="https://gitlab.com/gkepas" rel="">gkepas</a>, <a href="https://gitlab.com/JonstonChan" rel="">JonstonChan</a>, <a href="https://gitlab.com/koves" rel="">koves</a>, <a href="https://gitlab.com/MattGaiser" rel="">MattGaiser</a>, <a href="https://gitlab.com/MatthewOscar" rel="">MatthewOscar</a>, <a href="https://gitlab.com/nexpectArpit" rel="">nexpectArpit</a>, <a href="https://gitlab.com/priyansh3133" rel="">priyansh3133</a>, <a href="https://gitlab.com/Vinayreddy765" rel="">Vinayreddy765</a>, <a href="https://gitlab.com/zidanesalim" rel="">zidanesalim</a>.</p><p>Check out the full set of <a href="https://gitlab.com/gitlab-org/orbit/knowledge-graph/-/merge_requests?scope=all&amp;state=merged&amp;label_name%5B%5D=orbit::hackathon" rel="">merged contributions</a>.</p><h2 id="what-the-community-taught-us">What the community taught us</h2><p>You learn something about a tool by watching what people build with it, before anyone tells them what it is for.</p><p>Nobody built a chatbot. The strong submissions all made the same move underneath. They took a question that used to mean an afternoon of digging across four tools. They answered it in one query.</p><ul><li>What breaks if I merge this?</li><li>Which tests actually matter?</li><li>What does this migration really cost?</li><li>Is last month&#39;s change still alive.</li></ul><p><strong>We did not ship those as features.</strong> The community found them the moment the graph was in reach. That tells us more about GitLab Orbit than any benchmark could.</p><p>The full field is in the <a href="https://gitlab-transcend.devpost.com/project-gallery" rel="">project gallery</a> if you want to dig around. Plenty of good projects did not fit into eight slots.</p><h2 id="what-you-can-build-on-gitlab-orbit">What you can build on GitLab Orbit</h2><p>Every winner above is one answer to the same question: What can an agent do when it reasons from first-party context across your whole system, instead of guessing from fragments? GitLab Orbit continuously maps your code, work items, merge requests, pipelines, deployments, and ownership into one graph, so agents and engineers draw from a single source of truth. You do not need a hackathon to start. Here are the patterns the community proved out, each grounded in a use case Orbit was built for.</p><ul><li><strong>Change-aware delivery: See what a change breaks before you push.</strong> Ask GitLab Orbit for every downstream caller of a function, the pipelines it feeds, and the team that owns them, in one query. Sankofa&#39;s Radar does this on a merge request; CrossCut takes the same call graph and runs only the tests a change can reach, cutting a CI run by 90%. Catch the hidden dependencies early instead of discovering them at the end of CI.</li><li><strong>Safer migrations with full system context.</strong> Ask which services depend on the one you want to move, in what order, and where the risk sits. Carver turns that into a priced quote; Marshal drives it repo by repo. Both scope the blast radius from the real dependency graph, so a platform team can commit to a migration date instead of discovering hidden dependents three weeks in.</li><li><strong>Fast blast-radius analysis for vulnerabilities.</strong> From a vulnerable function, follow the graph to every reachable endpoint, the pipelines that build them, and the teams that own them. Sankofa&#39;s Shield does in one pass what used to be a project-by-project correlation exercise across days.</li></ul><p>The common thread: The answer was never in the code alone. It is in how code connects to pipelines, deployments, vulnerabilities, and ownership, and GitLab Orbit keeps those connections current so you can ask in a single query. Agents on the <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a> query it natively, external agents connect through MCP, and engineers query the same graph directly through the Data Explorer. One graph, one source of truth, for every agent and every person on the team.</p><h2 id="try-gitlab-orbit">Try GitLab Orbit</h2><p>To everyone who entered, thank you. If you want to build your own, start with <a href="https://about.gitlab.com/gitlab-orbit/" rel="">GitLab Orbit</a> on the <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a>: The same context these teams used is already live in your software development lifecycle. We will do this again. Sign up at <a href="https://contributors.gitlab.com" rel="">contributors.gitlab.com</a> to hear about it first.</p><p>Already have access to the GitLab Duo Agent Platform and GitLab Orbit and want to see how far you can take it? <a href="https://about.gitlab.com/community/co-create/" rel="">Apply for Co-Create</a>.</p>]]></content>
        <author>
            <name>Mattias Michaux</name>
            <uri>https://about.gitlab.com/blog/authors/mattias-michaux/</uri>
        </author>
        <published>2026-07-20T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Turn multi-step software delivery into agentic flows you can trust]]></title>
        <id>https://about.gitlab.com/blog/multi-step-software-delivery-with-agentic-flows/</id>
        <link href="https://about.gitlab.com/blog/multi-step-software-delivery-with-agentic-flows/"/>
        <updated>2026-07-16T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Knowing what to do next in software development is rarely the hard part. Doing it again in the exact same steps — implement an issue, fix a pipeline, review a merge request — is. Chat that only provides answers still leaves every handoff to you. Homegrown scripts don’t inherit changes in access controls, new triggers, or updated review gates. In both cases, the multi-step paths teams rely on continue to stay stuck as runbooks in someone’s head.</p><p><a href="https://docs.gitlab.com/releases/19/gitlab-19-2-released/" rel="">GitLab 19.2</a> closes that gap as <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/custom/" rel="">Custom Flows</a> reach general availability: AI-powered workflows you define once, trigger from native GitLab events, and run in CI/CD pipeline. A self-healing pipeline pattern like <em>analyze failed test → generate fix → commit → notify team</em> becomes something the platform can run end to end.</p><p>In addition, <a href="https://docs.gitlab.com/releases/19/gitlab-19-2-released/#start-foundational-flows-from-agentic-chat" rel="">Foundational Flows</a> no longer start only from a button, mention, or assignment. Now, when your request in GitLab Duo Agentic Chat matches specialist work — implement a change, review a merge request, fix a failed pipeline — Duo recommends the flow, you approve the handoff, and you follow it from the conversation.</p><p>As a result, agentic software delivery gets past single-turn chat. Teams encode the sequences they already trust, kick them off from events or chat, and keep humans on approval instead of on every intermediate step.</p><h2 id="why-multi-step-software-delivery-stays-manual">Why multi-step software delivery stays manual</h2><p>Agentic demos favor single turns. Real delivery work is a chain: gather context, change code, open a merge request, wait on CI, and respond to review. Without flows, every link in that chain is a person clicking, pasting, or remembering tribal steps.</p><p>Building those chains used to feel provisional while custom flows within GitLab Duo Agent Platform were still maturing. Teams delayed encoding the paths they already trust, such as self-healing pipelines, “implement this issue,” and event-driven follow-ups, because production readiness and event coverage weren’t there yet.</p><h2 id="what-agentic-flows-change-for-engineering-teams">What agentic flows change for engineering teams</h2><ul><li><strong>Automate the sequences you already trust.</strong> Custom flows run multi-step tasks across projects, triggered by GitLab events you already work with: mentions, assignments, pipelines, merge request lifecycle, work item changes, and more. They run under composite identity, so access stays bounded and actions stay attributable.</li><li><strong>Start specialist work from chat.</strong> Ask Agentic Chat to use the Developer Flow to implement work, the Code Review Flow to review a merge request, or Fix CI/CD Pipeline Flow to diagnose and repair a failed pipeline. Approve the handoff, then keep working while progress shows inline.</li><li><strong>Keep automatic review intentional.</strong> In GitLab 19.2, exclusion rules let you skip auto-review for bot-authored or branch-pattern merge requests you don’t want burning credits. <a href="https://docs.gitlab.com/user/duo_agent_platform/customize/review_instructions/" rel="">Custom review instructions</a> shape what review looks for, so you’re not only choosing <em>which</em> merge requests get reviewed, but <em>how</em>.</li></ul><p><strong>See Duo agentic flows in action:</strong></p><iframe src="https://player.vimeo.com/video/1210303097?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share" referrerPolicy="strict-origin-when-cross-origin" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="19.2 Custom Flows Reach GA Status"></iframe><script src="https://player.vimeo.com/api/player.js"></script><h2 id="how-do-they-work">How do they work?</h2><p><strong>Custom flows.</strong> Create one from a project or the <a href="https://docs.gitlab.com/user/duo_agent_platform/ai_catalog/" rel="">AI Catalog</a>, choose visibility, enable it where you need it, and attach a <a href="https://docs.gitlab.com/user/duo_agent_platform/triggers/" rel="">trigger</a> so the right GitLab events start it. You can add human-in-the-loop checkpoints at sensitive steps. In 19.2, custom flows also pick up a &quot;work item status changed&quot; trigger and bulk enablement for public flows across up to 100 projects. Looking ahead, a Flow Creation Agent is on the roadmap so teams can describe a flow in plain language and get a runnable definition, without hand-writing the full schema first.</p><p><strong>Foundational Flows in Agentic Chat.</strong> When your request matches specialist work, it can be handed to a foundational flow, you approve before anything runs, and you stay in the conversation while it works. That’s the difference from chat that only answers: The multi-step part leaves your hands without leaving GitLab.</p><p><strong>Updated Automation for Code Review Flow.</strong> Exclusion rules keep bot-driven or out-of-scope merge requests from burning code review cycles you didn’t mean to spend. And, <a href="https://docs.gitlab.com/user/duo_agent_platform/customize/review_instructions/" rel="">custom review instructions</a> shape what “good” looks like for your team, so that expanding automation doesn’t mean reviewing everything the same way.</p><h2 id="start-encoding-the-paths-you-already-run">Start encoding the paths you already run</h2><p>Custom Flows are now generally available, and Foundational Flows can now start from Agentic Chat which routes your request to the right specialist flow as you describe what you need — translating the agentic software delivery sequences your team already trusts to predictable automation, beyond tribal knowledge.</p><p>Ready to learn more? Start by reviewing our documentation for <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/custom/" rel="">Custom Flows</a> and <a href="https://docs.gitlab.com/user/duo_agent_platform/flows/foundational_flows/" rel="">Foundational Flows</a>. One thing to plan for: Event-driven flows consume credits based on the work they do. Try them on a few projects before you turn them loose across a large group.</p><p>Similar to other capabilities of Duo Agent Platform, you can get access to agentic flows with a <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">free trial of GitLab Duo Agent Platform</a>. On the Free tier, you can <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#for-the-free-tier-on-gitlabcom" rel="">sign up in a few simple steps</a>.</p><p>Already on GitLab Premium or Ultimate? Start by <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">turning on Duo Agent Platform</a> and use the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits/" rel="">GitLab Credits included with your subscription</a>.</p>]]></content>
        <author>
            <name>Ozer Dondurmacioglu</name>
            <uri>https://about.gitlab.com/blog/authors/ozer-dondurmacioglu/</uri>
        </author>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[GitLab Duo Security Review spots logic flaws scanners miss]]></title>
        <id>https://about.gitlab.com/blog/gitlab-duo-security-review-flow/</id>
        <link href="https://about.gitlab.com/blog/gitlab-duo-security-review-flow/"/>
        <updated>2026-07-16T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Static scanners excel at catching vulnerabilities that fit a known pattern, like unsanitized query inputs, hardcoded secrets, and unsafe deserialization. They struggle against flaws in your application’s logic, where there is no pattern to match — only valid code doing the wrong thing for your domain. Undetected, these flaws surface late and cost more to fix.</p><p>Security Review Flow, now in public beta, scrutinizes code changes the way a security engineer would. It traces intent rather than matching signatures to catch logic flaws before they hit production. It&#39;s a major step toward uncovering dangerous flaws that scanners usually miss.</p><h2 id="where-pattern-based-scanners-go-blind">Where pattern-based scanners go blind</h2><p>The most damaging application vulnerabilities often look correct line by line, but violate context the code doesn&#39;t contain, like your authorization model, data sensitivity rules, and intended workflows. Consider three of the most common vulnerability classes:</p><p><strong>Access and authorization:</strong> Whether a user may read or change a resource is defined by your authorization model, not any language construct. Broken object level authorization (accessing another user&#39;s data by changing an ID) has topped the <a href="https://owasp.org/API-Security/editions/2023/en/0x11-t10/" rel="">OWASP API Security Top 10</a> since 2019.</p><p><strong>Data exposure:</strong> Serializing an object and returning it is ordinary, correct-looking code. Whether it leaks depends on which fields are sensitive and who receives them — facts about your domain, not your syntax.</p><p><strong>Control flow and workflow:</strong> Business-logic and race-condition flaws occur when valid operations run in the wrong order, repeat unexpectedly, or get manipulated. Examples include checkout reachable without payment, a state re-entered under a race, or a parameter tweaked to change a price.</p><p>Catching these flaws has previously required manual security review, which is expensive to scale across every merge request (MR), or penetration testing and bug bounties, which arrive too late. The result is a growing gap between the pace of development and how quickly security expertise can be applied.</p><h2 id="bring-security-judgment-to-every-mr">Bring security judgment to every MR</h2><p>Security Review Flow, a foundational flow on GitLab Duo Agent Platform, closes that gap by reasoning about what your code is meant to do. It detects exactly the classes of flaws described above: Broken object level authorization and function level authorization, missing authorization on state-changing operations, information disclosure, mass assignment, business logic errors, and race conditions in stateful workflows.</p><p>It complements traditional scanners and human analysis rather than replacing them, and it reviews code at the point of change, when a fix is cheapest. GitLab&#39;s own application security team has used Security Review Flow across internal MRs throughout its development.</p><p><strong>See Security Review Flow in action:</strong></p><iframe src="https://player.vimeo.com/video/1209923383?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share" referrerPolicy="strict-origin-when-cross-origin" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="19.2 Security Review Flow"></iframe><script src="https://player.vimeo.com/api/player.js"></script><h2 id="how-it-works">How it works</h2><p>When your MR is ready, request a review from <code>Duo Security Review</code>, the same way you would from a person. It analyzes the diff in context: the original files, changed lines, MR discussion, and related code. Its reasoning is optimized for precision, and an independent validation pass examines each finding to filter out likely false positives.</p><p>Findings appear as diff threads on the relevant lines, along with a summary in an internal note. On public projects, they’re confined to the internal note, so security details aren’t exposed.</p><p>Each finding arrives with the context reviewers need:</p><ul><li><strong>Vulnerability type</strong>, with a CWE reference</li><li><strong>Severity</strong>: critical, high, medium, or low</li><li><strong>Tier</strong>: Tier 1 (Exploitable), Tier 2 (Logic Flaw), or Tier 3 (Design Issue)</li><li><strong>A plain-language explanation</strong> of the issue</li><li><strong>A suggested fix</strong>, when one is available</li></ul><p>Severity determines the reviewer state: A critical or high finding sets it to <em>Request changes</em>, while medium or low findings result in <em>Comment</em>. The flow never approves, even when it finds nothing — a human always owns the final call.</p><p>From there, mention your organization’s Duo Security Review service account in a comment thread to ask a question, discuss remediation, or challenge a finding. Resolve each finding by applying the fix as a standard MR suggestion, dismissing it as a false positive, or accepting the risk. After committing your fixes, request a fresh review to check what changed.</p><h2 id="run-your-first-security-review-flow">Run your first Security Review Flow</h2><p>Security Review Flow is in public beta for GitLab Ultimate customers. It is available on GitLab.com, GitLab Self-Managed, and GitLab Dedicated.</p><p>Learn how to get started in the <a href="https://docs.gitlab.com/ee/user/duo_agent_platform/flows/foundational_flows/security_review/" rel="">Security Review Flow documentation</a>.</p><p>You can get access to Security Review Flow with a <a href="https://gitlab.com/-/trials/new?glm_content=default-saas-trial&amp;glm_source=about.gitlab.com/gitlab-duo-agent-platform/" rel="">free trial of GitLab Duo Agent Platform</a>. Already a GitLab Ultimate subscriber? <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">Turn on Duo Agent Platform</a> and use the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits" rel="">GitLab Credits included with your subscription</a>.</p><p>Cost varies with the complexity of the diff and the model you select, so try it on a few MRs before running it broadly. Pricing may be updated at general availability.</p><p>Share what you find in our <a href="https://gitlab.com/gitlab-org/gitlab/-/work_items/600304" rel="">feature feedback issue</a>, so your input shapes what we build.</p>]]></content>
        <author>
            <name>Mark Settle</name>
            <uri>https://about.gitlab.com/blog/authors/mark-settle/</uri>
        </author>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Bring GitLab Duo Agent Platform to your terminal]]></title>
        <id>https://about.gitlab.com/blog/gitlab-duo-cli-generally-available/</id>
        <link href="https://about.gitlab.com/blog/gitlab-duo-cli-generally-available/"/>
        <updated>2026-07-16T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>Most of the work for software delivery doesn’t happen only in the editor. Pipelines fail. Tests break. Vulnerabilities show up. And a lot of that work starts and ends at the command line.</p><p>Agentic AI in the terminal that only understands code can’t help with any of that. A standalone assistant doesn’t know your agents across the entire software lifecycle, your permissions across many projects in your organization, or a specific project context you’ve already set up in GitLab.</p><p>That’s what changes in <a href="https://docs.gitlab.com/releases/19/gitlab-19-2-released/" rel="">GitLab 19.2</a>. <a href="https://docs.gitlab.com/user/gitlab_duo_cli/" rel="">GitLab Duo CLI</a> is generally available, and it brings <a href="https://docs.gitlab.com/user/gitlab_duo_chat/agentic_chat/" rel="">GitLab Duo Agentic Chat</a> straight into your terminal. Unlike tools bolted on from the outside, it already knows your project, your pipelines, and your agent setup. You can use it interactively when you’re exploring and building, or headless when you want it running in a job or script.</p><p>As a result, developers stay in the shell where the failure showed up, and their work continues across the terminal, the UI, and your editor. Platform teams govern rollout like everything else on GitLab, and agentic help finally covers more of the delivery lifecycle than “write this function.”</p><h2 id="why-agentic-ai-in-the-terminal-stopped-at-code">Why agentic AI in the terminal stopped at code</h2><p>Agentic tools matured first where demos look best: editing files. The lifecycle after the commit is messier and more operational. When the failure is a pipeline, a dependency, or a CI config, context lives in GitLab — not in a coding agent’s training set or local context.</p><p>Teams that tried to bridge that gap with generic CLI assistants paid another cost: no shared admin control, no MCP/setup diagnostics aligned with the platform, and no single identity model with the rest of the agentic software lifecycle. Agentic work in the terminal stayed stuck on coding, instead of helping across the rest of delivery.</p><h2 id="what-teams-get-when-duo-cli-is-generally-available">What teams get when Duo CLI is generally available</h2><ul><li><strong>Stay in the terminal for the work that already lives there.</strong> Dig into how the codebase fits together, build and refactor, chase down pipeline failures, tidy up CI/CD, and knock out multi-step tasks — without jumping to the browser for every answer.</li><li><strong>Pick up where you left off, on any surface.</strong> Sessions are shared across the GitLab Duo CLI, the GitLab UI, and editor extensions. Start in the browser. Continue in your shell. Same conversation.</li><li><strong>Plan first, then build.</strong> Interactive mode works like Agentic Chat: Plan mode looks around without changing anything, build mode makes the changes. Need it unattended? Headless mode drops into CI jobs and scripts.</li><li><strong>Turn it on when you’re ready.</strong> Duo CLI works on GitLab.com, GitLab Self-Managed, and GitLab Dedicated. On Self-Managed and Dedicated, admins can switch instance access on or off. Anywhere you use it, developers can run <code>/doctor</code> to check their setup and <code>/mcp</code> to see their MCP configuration.</li></ul><p><strong>See GitLab Duo CLI in action:</strong></p><iframe src="https://player.vimeo.com/video/1210314517?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share" referrerPolicy="strict-origin-when-cross-origin" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Demo - Duo CLI goes GA with 19.2"></iframe><script src="https://player.vimeo.com/api/player.js"></script><h2 id="how-duo-cli-works">How Duo CLI works</h2><p>The easiest path is through the <a href="https://docs.gitlab.com/cli/duo/cli/" rel="">GitLab CLI</a>: Run <code>glab duo cli</code> and <code>glab</code> handles authentication for you. You can also install and run <code>duo</code> as a standalone tool with a personal access token. Both setups support the same modes and capabilities.</p><ul><li><strong>Interactive mode</strong> — chat in the terminal, and approve tools before anything runs. Explore the codebase, plan a fix, then switch to build mode when you’re ready to make changes.</li><li><strong>Headless mode</strong> — non-interactive execution for runners, scripts, and automation. Use <code>glab duo cli run --goal</code> or <code>duo run --goal</code>.</li></ul><p>For instance, when a pipeline fails, ask from the same shell:</p><pre className="language-shell shiki shiki-themes github-light" code="$ glab duo cli
&gt; The pipelines in MR 23 are failing. Please help me fix them.
" language="shell" meta="" style=""><code><span class="line" line="1"><span class="s7eDp">$</span><span class="sYBdl"> glab</span><span class="sYBdl"> duo</span><span class="sYBdl"> cli
</span></span><span class="line" line="2"><span class="sD7c4">&gt;</span><span class="sgsFI"> The pipelines in MR 23 are failing. Please help me fix them.
</span></span></code></pre><p>Duo CLI looks at what’s going on, figures out what went wrong, and proposes changes you can review before applying. It follows your custom instructions (<code>chat-rules.md</code>, <code>AGENTS.md</code>, <a href="http://SKILL.md" rel=""><code>SKILL.md</code></a>) as you scale, and you can extend its interactive sessions with <a href="https://docs.gitlab.com/user/gitlab_duo_cli/#custom-slash-commands" rel="">custom slash commands</a>.</p><h2 id="start-using-duo-cli-today">Start using Duo CLI today</h2><p>Head over to the <a href="https://docs.gitlab.com/user/gitlab_duo_cli/" rel="">GitLab Duo CLI documentation</a> to install and authenticate — and if you already use the GitLab CLI, start with <a href="https://docs.gitlab.com/cli/duo/cli/" rel=""><code>glab duo cli</code></a>.</p><p>New to GitLab? <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">Start a free trial of GitLab Duo Agent Platform</a>. Already on Premium or Ultimate? <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">Turn on Duo Agent Platform</a> and use the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits/" rel="">GitLab Credits included with your subscription</a>.</p><style>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 .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}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);}</style>]]></content>
        <author>
            <name>Ozer Dondurmacioglu</name>
            <uri>https://about.gitlab.com/blog/authors/ozer-dondurmacioglu/</uri>
        </author>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[Forrester Consulting: GitLab Duo Agent Platform delivers 400% ROI]]></title>
        <id>https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/</id>
        <link href="https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/"/>
        <updated>2026-07-16T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>A new <a href="https://about.gitlab.com/resources/study-forrester-tei-gitlab-dap/" rel="">Forrester Consulting Total Economic Impact™ study</a> found that organizations using GitLab Duo Agent Platform achieve a 400% return on investment and $7.5 million in net present value over three years — with payback in under six months.</p><p>Agentic coding makes developers faster. The harder problem is how enterprises turn speed into return. Faster commits are only part of the equation when it comes to shipping production-grade software. One senior systems engineer in insurance and financial services put it plainly: Code review that used to take hours now takes a fraction of the time, with 80% to 90% of code generation handled by the platform.</p><p>To help leaders understand returns achievable by using GitLab, Forrester interviewed four decision-makers across the financial services, software development, entertainment, and insurance industries who use GitLab Duo Agent Platform in production, then combined their experiences into a single composite organization: a global company with $3 billion in annual revenue and 3,000 employees, scaling from 150 to 250 GitLab Duo Agent Platform users over three years.</p><h2 id="weighing-cost-with-roi">Weighing cost with ROI</h2><p>The study is transparent about the investment required: three-year, risk-adjusted costs of $1.3 million in consumption credits and $589,000 in implementation and ongoing management, including internal labor for the pilot program, training, and support. Weighed against $9.4 million in benefits, that&#39;s the basis for the 400% ROI and $7.5 million net present value.</p><p><img alt="Graphic showing benefits of GitLab Duo Agent Platform" src="https://res.cloudinary.com/about-gitlab-com/image/upload/v1783954053/j8qizamomxpvqcxjabeu.png" /></p><h2 id="before-manual-tasks-interruptions-code-review-bottlenecks">Before: Manual tasks, interruptions, code review bottlenecks</h2><p>Before adopting GitLab Duo Agent Platform, interviewees described familiar bottlenecks: teams that depended on manual processes, senior-engineer expertise, and ad-hoc knowledge sharing to build, review, and secure software. New hires couldn&#39;t get unstuck without pulling a senior engineer off their own work. Security fixes sat in a queue until one of a handful of people with the right context had time to look at them. And code review, not writing code, was often the hindrance to shipping. These dependencies are what Forrester&#39;s composite organization addressed, resolved, and measured.</p><h2 id="after-faster-onboarding-migration-security-remediation-and-time-saved">After: Faster onboarding, migration, security remediation, and time saved</h2><p><a href="https://about.gitlab.com/resources/study-forrester-tei-gitlab-dap/" rel="">Forrester quantified four benefit areas</a> for the composite organization, totaling $9.4 million in risk-adjusted benefits against $1.9 million in costs:</p><p><strong>New developers onboarded 80% faster.</strong> Instead of pulling a colleague off their own work, new team members used agentic chat embedded in their IDEs and repositories to get context to work through unfamiliar codebases and conventions on their own — a $582,000 savings.</p><p><strong>A migration budgeted for eight months finished in two, a 75% reduction in timeline.</strong> The composite organization used GitLab Duo Agent Platform to diagnose pipeline failures and resolve issues in real time during a large-scale migration from an on-prem GitLab environment to GitLab SaaS, saving $157,000 in labor costs.</p><p><strong>Security and QA engineers got 40% of their time back.</strong> QA and security engineers cut remediation time using GitLab Duo Agent Platform&#39;s contextual explanations and suggested fixes, reducing their dependence on senior engineers — a $1.3 million labor savings over three years.</p><p><strong>Every developer got 20% more of their week back for feature work.</strong> Agentic chat and AI agents took over code review, testing, and troubleshooting that used to eat into build time — a $7.4 million combined gain across all developers as adoption grew over the three-year span.</p><p>Forrester also identified benefits it didn&#39;t quantify for this study, including savings from consolidating overlapping AI development tools, improved developer satisfaction, and better cross-team knowledge sharing.</p><blockquote><p><em>&quot;Feature releases that used to take a couple of weeks are now completed in a couple of days. So we&#39;re seeing high multipliers of productivity.&quot; - Head of automation at a financial services company</em></p></blockquote><h2 id="compounded-returns-for-shipping-secure-software-faster">Compounded returns for shipping secure software faster</h2><p>The interviewees didn&#39;t just code faster, they shipped features in days instead of weeks, remediated vulnerabilities in minutes, onboarded new hires in a fraction of the time, and compressed an eight-month migration into two months. The pattern this study captures is that while agentic coding accelerates individual output, the return only compounds when that speed runs through infrastructure built for the full software lifecycle.</p><p>If you&#39;re building the business case for agentic infrastructure for software engineering at your own organization, this study gives you a framework grounded in what four enterprises actually did, so you can turn forecasts into reality.</p><blockquote><p><a href="https://about.gitlab.com/resources/study-forrester-tei-gitlab-dap/" rel="">Read the full Forrester Total Economic Impact™ study of GitLab Duo Agent Platform</a> to see the complete methodology, financial model, and interview findings.</p></blockquote><p><em>This study is commissioned by GitLab and delivered by Forrester Consulting. It is not meant to be used as a competitive analysis. Forrester makes no assumptions as to the potential ROI that other organizations will receive; results are representative of the experiences of the interviewed organizations and the composite they inform. GitLab provided customer names for the interviews but did not participate in them, and Forrester maintains editorial control over the study&#39;s findings.</em></p>]]></content>
        <author>
            <name>Jessica Taylor</name>
            <uri>https://about.gitlab.com/blog/authors/jessica-taylor/</uri>
        </author>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[GitLab 19.2 released]]></title>
        <id>https://docs.gitlab.com/releases/19/gitlab-19-2-released/</id>
        <link href="https://docs.gitlab.com/releases/19/gitlab-19-2-released/"/>
        <updated>2026-07-16T00:00:00.000Z</updated>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
    <entry>
        <title type="html"><![CDATA[When a version bump breaks your build, GitLab fixes it]]></title>
        <id>https://about.gitlab.com/blog/dependency-scanning-auto-remediation/</id>
        <link href="https://about.gitlab.com/blog/dependency-scanning-auto-remediation/"/>
        <updated>2026-07-16T00:00:00.000Z</updated>
        <content type="html"><![CDATA[<p>AI is writing more code and pulling in more dependencies, increasing application risk. Most of that exposure isn&#39;t from code your team actively chose. A 2025 <a href="https://arxiv.org/abs/2503.22134" rel="">study of the Maven ecosystem</a> found vulnerabilities reaching roughly 63% of latest releases through transitive dependencies, versus 31% through direct ones.</p><p><a href="https://docs.gitlab.com/user/application_security/remediate/dependency_scanning_auto_remediation/" rel="">Dependency Scanning Auto-Remediation</a>, now in beta, closes the loop for security. When <a href="https://about.gitlab.com/blog/sbom-based-dependency-scanning/" rel="">dependency scanning</a> finds a vulnerable package, GitLab opens a merge request to update it, uses AI to fix any build-breaking changes, and iterates until your pipeline passes — with every change governed by your existing gates and audit trail.</p><p>As a result, security backlogs shrink without diverting developers, high-severity vulnerabilities get fixed within compliance deadlines, and breaking upgrades arrive as merge requests ready for approval.</p><h2 id="why-the-dependency-backlog-keeps-growing">Why the dependency backlog keeps growing</h2><p>Vulnerable and outdated components are a longstanding <a href="https://about.gitlab.com/blog/2025-owasp-top-10-whats-changed-and-why-it-matters/" rel="">OWASP Top 10</a> risk and a leading source of remediation backlogs. Clearing findings is slow, manual work that competes with feature delivery, leaving high-severity vulnerabilities unresolved beyond the 30-day deadlines of PCI-DSS and <a href="https://about.gitlab.com/blog/gitlab-dedicated-for-government-now-fedramp-authorized/" rel="">FedRAMP</a>. Meanwhile, even in established libraries, AI-assisted exploit engineering is accelerating disclosure and weaponization.</p><p>Roughly one in eight <a href="https://link.springer.com/article/10.1007/s10664-024-10563-4" rel="">dependency updates introduce a breaking change</a>, and many labeled backward-compatible still break the build. Teams tend to defer complex changes, and the longer those vulnerabilities sit, the more serious they become.</p><h2 id="from-backlog-to-fix-without-diverting-developers">From backlog to fix, without diverting developers</h2><p>Dependency Scanning Auto-Remediation turns vulnerable dependencies into reviewed, ready-to-merge fixes, so your team clears findings faster and spends less time resolving breaking changes. Teams see benefits in speed, effort, and control:</p><ul><li><strong>Shrink the dependency backlog.</strong> Vulnerable dependencies get upgraded as they&#39;re found, so findings don&#39;t pile up and high-severity issues stay within compliance deadlines.</li><li><strong>Reclaim time lost to breaking-change rewrites.</strong> When a bump breaks the build, <a href="https://about.gitlab.com/gitlab-duo-agent-platform/" rel="">GitLab Duo Agent Platform</a> commits a fix, so developers review a working change instead of authoring one from scratch.</li><li><strong>Keep every change governed.</strong> Auto-remediation drafts the change, but nothing merges until a reviewer signs off, and every MR leaves an audit trail of what changed and who approved it.</li></ul><h2 id="quickly-close-vulnerabilities-even-when-they-require-code-changes">Quickly close vulnerabilities, even when they require code changes</h2><p>Dependency Scanning Auto-Remediation bumps vulnerabilities and fixes breaking changes in two stages:</p><p><strong>Automated dependency version bumping</strong> runs automatically when scanning detects a vulnerable dependency, opening a merge request to upgrade it to the nearest fixed version. When no eligible fix exists, the finding stays in your vulnerability report until a safe upgrade path becomes available. Every MR is attributed to a dedicated service account, making each change traceable to a distinct identity.</p><p><strong>Agentic breaking change resolution</strong> handles the tough cases when a version bump introduces breaking changes. When a remediation MR&#39;s pipeline fails because the new version breaks your project, GitLab Duo Agent Platform automatically analyzes the pipeline errors, the dependency&#39;s changelog, and how your code uses the dependency. Then, within the same MR, it commits fixes to your code so your project works with the updated version. If it can&#39;t get the pipeline passing, it stops and posts what it found to the MR so you can take it from there. Supported ecosystems include Bundler, Maven, Gradle, and major Python and JavaScript/TypeScript package managers, with <a href="https://gitlab.com/gitlab-org/gitlab/-/work_items/604602" rel="">Rust</a> and <a href="https://gitlab.com/gitlab-org/gitlab/-/work_items/604601" rel="">Go</a> planned in the months ahead.</p><p>Auto-remediation never merges on its own. To speed up review, each MR spells out the vulnerability it addresses, the version it moves to, and the code GitLab Duo Agent Platform suggested to keep the build passing, so approvers don&#39;t have to reverse-engineer the change.</p><h2 id="how-dependency-scanning-auto-remediation-works">How Dependency Scanning Auto-Remediation works</h2><p>Auto-remediation runs automatically when SBOM-based dependency scanning detects a vulnerable dependency with an available fix. Practitioners can also initiate it for an individual finding from the vulnerability report. GitLab then opens a remediation MR that flows through your normal review and merge process; when agentic breaking-change resolution is enabled and the version bump breaks the pipeline, GitLab Duo Agent Platform attempts to fix the resulting code changes in that same merge request.</p><p>Built-in safeguards keep remediation automation from becoming noise. Cooldown periods stop busy projects from triggering remediation on every pipeline, and GitLab won’t re-create a closed MR unless a newer fix is available.</p><p>Configure remediation to match your risk tolerance. You can target vulnerabilities of any severity from low to critical, cap how far version bumps are allowed to go (patch, minor, or major), and store settings in project- or group-level configuration profiles (via API during beta).</p><p>Remediation runs through your organization&#39;s own pipeline, so it inherits your existing access controls and approval gates. You also get a complete, auditable record of what changed, who approved it, and why.</p><p>See Dependency Scanning Auto-Remediation in action:</p><iframe src="https://player.vimeo.com/video/1210291456?badge=0&amp;autopause=0&amp;player_id=0&amp;app_id=58479" frameBorder="0" allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share" referrerPolicy="strict-origin-when-cross-origin" style="position:absolute;top:0;left:0;width:100%;height:100%;" title="Dependency Scanning Auto Remediation"></iframe><script src="https://player.vimeo.com/api/player.js"></script><h2 id="start-clearing-your-dependency-backlog-today">Start clearing your dependency backlog today</h2><p>Dependency Scanning Auto-Remediation is in public beta. It is available on <a href="http://GitLab.com" rel="">GitLab.com</a> and rolling out to GitLab Self-Managed and GitLab Dedicated.</p><p>Ready to try it? Check out the <a href="https://docs.gitlab.com/user/application_security/remediate/dependency_scanning_auto_remediation/" rel="">Dependency Scanning Auto-Remediation documentation</a>.</p><p>Automated dependency version bumping is included with GitLab Ultimate at no additional cost.</p><p>You can get access to agentic breaking-change resolution with a <a href="https://gitlab.com/-/trials/new?glm_content=default-saas-trial&amp;glm_source=about.gitlab.com/gitlab-duo-agent-platform/" rel="">free trial of GitLab Duo Agent Platform</a>. Already a GitLab Ultimate subscriber? <a href="https://docs.gitlab.com/user/duo_agent_platform/turn_on_off/" rel="">Turn on Duo Agent Platform</a> and use the <a href="https://docs.gitlab.com/subscriptions/gitlab_credits/#included-credits" rel="">GitLab Credits included with your subscription</a>.</p><p>Have feedback? Share it in the <a href="https://gitlab.com/gitlab-org/gitlab/-/work_items/600511" rel="">feature feedback epic</a>.</p>]]></content>
        <author>
            <name>Mark Settle</name>
            <uri>https://about.gitlab.com/blog/authors/mark-settle/</uri>
        </author>
        <published>2026-07-16T00:00:00.000Z</published>
    </entry>
</feed>