GitLab SAST and application security scanning

GitLab SAST and application security scanning help teams find code weaknesses in merge requests and track them to resolution, but advanced analysis and vulnerability management depend on your tier. This page explains which capabilities sit on Free, Premium and Ultimate and what your runners need.

On this page

What GitLab SAST gives you and when self-managed teams need it

GitLab SAST (static application security testing) reads your source code during a CI/CD pipeline and reports likely vulnerabilities without running the application. For a security or platform lead running self-managed GitLab, the practical question is whether static analysis should run on every merge request, which findings block a merge, and what infrastructure must exist before any of that works. The answer depends on the edition, the analyzers you enable and the runner capacity that executes them. The SAST model is analyzer-based. GitLab includes a template that adds an analysis job to a pipeline, and each job runs a language-specific analyzer as a container image on a runner. Analyzers are selected by the languages present in the project, and their output is converted into a common report format that GitLab reads. Scans are CPU and memory work, so a fleet with too few runners, or runners limited to small machines, shows up as queued or slow security jobs rather than as a visible security gap. Confirm the runner executor, image pull path and offline image handling before you commit to a design, especially on air-gapped networks.

Findings appear in merge requests as a widget showing new results compared with the target branch, which lets reviewers see what a change introduced. Triage and tracking happen in the vulnerability management views. Per the GitLab pricing page, application security testing and vulnerability management sit in the Ultimate tier, while Free and Premium differ on what is included, so check which SAST capabilities, including Advanced SAST, are available in each tier before you size licenses. Exact feature lists change between releases, so confirm them against the current pricing page and the SAST documentation for the version you run. When you plan the rollout, decide three things first: which tier your security requirements actually need, whether findings should block merges or only inform reviewers, and how many runners you will dedicate to security jobs so they do not delay build and test pipelines. Ask your DeployOpen or internal team to test these settings on a representative project before enabling them across the instance.

Which scanning capabilities sit on Free, Premium and Ultimate

GitLab Free costs 0 US dollars and is available for self-managed installations, so it is the cost baseline for the instance itself. Do not assume that scanning features come with it. Treat scanning on Free as an open question until GitLab confirms which SAST analyzers and merge request findings apply to the exact version you plan to install.

  • Licensing cost: there is no subscription fee, so the spend is infrastructure, administration and any scanning tooling you run yourself.
  • Scanner availability: confirm whether any SAST analyzers run at this tier and whether their results appear in merge requests.
  • Self-managed fit: Free can host repositories and CI/CD, while scanning entitlements are decided separately.
  • Self-run tools: teams often run open-source scanners as CI jobs on Free. Those jobs need their own runner capacity and a process for handling results.
  • Version drift: scanner behavior can change between releases, so check entitlements against your target release, not an older one.

Record the Free entitlement answer in your design document before you assume any scanning gap is covered.

How the SAST job runs inside your pipeline

SAST runs as an ordinary CI/CD job in the pipeline of each project that includes the scanner template. The job checks out the code, runs the analyzers that match the languages it finds, and writes its results to a report artifact in a machine-readable format. GitLab reads that artifact to populate merge request widgets and the security dashboard, so the scan is only as visible as the job that produces the report. Plan for the job to run in a pipeline stage that completes before any merge decision depends on it, and confirm in the current GitLab documentation which report type and artifact path the SAST template uses for your GitLab version, since those details change between releases.

Analyzer selection and configuration live in the project's .gitlab-ci.yml file, usually as an include of the SAST template followed by variable overrides for the job. Variables such as SAST_EXCLUDED_PATHS and analyzer-specific settings are set there, or at group and instance level where your administrators have standardized them. Decide early which settings are locked centrally and which teams may tune them, because a project that excludes large directories or disables an analyzer changes what the report can show. Check the analyzer list and language coverage in the current GitLab SAST documentation before you rely on any language being scanned, and test the job on a representative repository to see which analyzers actually run.

Findings appear on the merge request as a widget that compares the source branch with the target branch, so reviewers see new issues introduced by the change. Confirmed or triaged findings then flow into the project's vulnerability management views, where status, ownership and history are tracked over time. Ask your administrators to confirm which roles can dismiss findings and whether dismissal requires a comment, because that decision determines the audit trail. Also plan the runner capacity the scan needs: SAST jobs compete with build and test jobs for the same runners, so the runner configuration for your pipelines should be sized with the scan included.

Scanning configuration options and when each fits

This table compares the main ways to configure GitLab security scanning, from the default included template to Advanced SAST and offline analyzer delivery. Read each row for the situation it suits, the cost it carries in scan time or coverage, and the tier or infrastructure it depends on. Confirm analyzer names and variables against the current GitLab documentation for your release before you write pipeline configuration.

OptionWhen it fitsTrade-offTier or infrastructure needs
Default analyzers through the included SAST templateFirst rollout, or teams that want language-specific SAST results with little pipeline design workCoverage is what the default analyzers detect for your languages, and results may include findings you must triageConfirm the analyzers included for your languages and whether the template is available on your tier
Customized analyzer variablesTeams that need to exclude test paths, tune rulesets or adjust analyzer behavior for a known codebaseEach tuning choice must be reviewed and maintained, and loose exclusions can hide real findingsSet in the CI/CD configuration; confirm variable names for your analyzer version
Advanced SAST on UltimateOrganizations that need deeper cross-file analysis and have the budget and tier for itHigher licensing cost and a longer analysis step than the default analyzers in most pipelinesRequires the Ultimate tier; the pricing page lists application security testing as an Ultimate feature
Scans on merge requestsDevelopers need feedback before code merges and reviewers want findings in the reviewAdds scan time to every merge request pipeline, and branch-specific findings may need triage before mergeNeeds runner capacity that can run scans on each merge request pipeline
Scans on the default branch onlyTeams with long scan times or limited runner capacity that still need a complete record of the main branchVulnerabilities reach the main branch before they are caught, so review relies on later detectionLower runner load; still requires vulnerability management setup to track results
Offline or air-gapped analyzer deliveryInstances with no internet access that must run scanners inside the network boundaryAnalyzer images and rulesets must be mirrored and updated by your team on a planned cycleFollow GitLab's offline guidance for scanners; confirm the images and update process with your administrators

How much runner capacity scans need and what drives it

Scan runtime on a self-managed GitLab depends on what runs each time code changes, not on a fixed number of machines. The cards below cover the workload, executor and version decisions that determine how much Runner capacity your scans consume, and what to confirm in your own environment before you size the fleet.

Projects and merge requests per day

Scan load follows how often pipelines start. A project that opens many merge requests each day runs its SAST jobs on every push to those branches, so the daily count of merge requests across all projects is the first number to collect. Ask teams to count pipelines per day for the last month, then separate scheduled scans from merge request pipelines, because scheduled full scans often run longer than incremental ones.

Language and repository size

Analyzer runtime varies with the languages in each project and the size of the code it must parse. Large monorepos and projects with many build targets take longer per job than small services, even when they run the same analyzer. Run one representative scan per language and record the job duration, then multiply by expected daily runs rather than assuming a single average for the whole estate.

Concurrent pipelines

Queue time matters as much as job duration. When many merge requests open at the same time, scan jobs wait for free Runner slots, which delays merge request feedback for developers. Confirm the concurrency limit each Runner and the instance will allow, and identify peak windows such as release days, so the fleet is sized for the busiest hour rather than the average day.

Executor type and autoscaling

The executor decides how jobs are isolated and how capacity grows. Docker executors run each analyzer in a container and suit most scan jobs, shell executors share the host and need tighter hygiene, and autoscaling executors add machines on demand. Autoscaling on cloud VMs or hypervisors reduces idle cost but adds start-up latency, so test how long a fresh machine takes to become ready for a scan.

Runner version alignment

GitLab Runner is distributed under the MIT license and is a separate component from the GitLab server. The documentation advises keeping the Runner major and minor versions aligned with GitLab, so an upgrade of the instance usually requires a planned Runner upgrade in the same change window. Record the Runner versions in the fleet inventory and check them against each GitLab upgrade stop before scans start failing on mismatched components.

Setting up SAST on a self-managed instance

This sequence takes a self-managed GitLab instance from tier confirmation to working static analysis, with findings visible in merge requests and, on Ultimate, triaged in vulnerability management. Each step closes with a check so you know it is safe to move on.

  1. Confirm tier and scanner entitlements

    Before any pipeline work, confirm which edition and license your instance runs and which security scanning features that tier includes. The GitLab pricing page groups application security testing and vulnerability management under Ultimate, while Free and Premium cover a narrower set, so check the feature matrix for your exact version with your GitLab account team or the pricing page. Record the result, including whether Advanced SAST is in scope. The check: a written entitlement list that the security and platform leads have both signed off on.

  2. Register a runner with a suitable executor

    SAST jobs run as CI/CD jobs, so they need a GitLab Runner that your instance can reach. Your platform team registers a runner using an executor suited to your infrastructure, such as Docker on a dedicated VM or the Kubernetes executor if you already operate clusters. Keep the Runner version aligned with your GitLab version, as the Runner documentation advises. Use a runner that is isolated from production deployment credentials. The check: the runner appears as online in the instance admin area and picks up a trivial test job.

  3. Include the SAST template in a pipeline

    In a test project, add the SAST template to the project's .gitlab-ci.yml so the analyzers run as part of the normal pipeline. Confirm that the analyzers needed for your languages are pulled from a registry your runners can reach, which matters for offline installs later. Keep the template changes in a separate branch so reviewers can see exactly what was added. The check: a pipeline completes with a SAST job that reports success or a clear, documented failure reason.

  4. Run scans on a test project

    Run the pipeline on a project with known, seeded weaknesses or with code your developers already understand, so you can judge whether the output is useful. Review the job logs for analyzer errors, unsupported languages and timeouts, and adjust runner resources if jobs are slow. Note which findings are false positives so the team can tune the approach before rollout. The check: the SAST report artifact is produced and the findings match what you expected from the seeded test code.

  5. Review findings in merge requests

    Open a merge request containing a deliberate change and confirm that SAST findings appear in the merge request widget with severity and location. Have a developer and a security reviewer each check that a finding is understandable enough to act on. Decide the team's rule for blocking merges, and document it before enforcing anything. The check: findings show on the merge request, link to the affected lines, and the team agrees on which severities block a merge.

  6. Configure vulnerability management triage on Ultimate

    On an Ultimate tier instance, open the project's vulnerability report and set up the triage workflow your security team uses. Assign owners, set states such as detected, confirmed, dismissed or resolved, and record a reason for each dismissal so auditors can follow the decision. Confirm who can change vulnerability states, since this is an access decision as well as a workflow one. The check: a test finding moves through the full state lifecycle and the dismissal reason is visible in the audit trail.

  7. Confirm scanners work offline

    If the instance runs air-gapped, repeat the pipeline run with network egress blocked, using the offline guidance GitLab publishes for its security scanners. Verify that analyzer images, rulesets and any advisory data are mirrored into your internal registry and reachable from the runner. Ask GitLab or your partner to confirm the exact mirroring steps for your version, since they change between releases. The check: a SAST job completes on the isolated network and produces the same report format as the connected run.

Security and operational considerations for scanning runners

Scanners run as CI/CD jobs, so the runner that executes them, the variables it can read and the network it can reach shape the risk as much as the scanner itself. The cards below cover the decisions to make before scans run on merge requests from people outside your trust boundary.

Isolate runners for untrusted merge requests

Merge requests from forks or external contributors can change the scanner configuration and the code being analyzed. Run those jobs on runners that are separate from production deployment runners, and use ephemeral executors such as autoscaled VMs or Kubernetes pods so no state survives between jobs. Check whether untrusted pipelines can reach protected variables and whether the runner shares a host or network with internal services. The runner must never be shared between untrusted and deployment workloads.

Limit secrets exposed in CI variables

Scan jobs inherit whatever CI/CD variables their pipeline can see, so a scanner or a malicious change to a job script can print or transmit them. Mark sensitive values as protected and masked, scope them to specific environments, and avoid placing deployment credentials in project-wide variables that scan jobs can read. Review which variables scan jobs receive before enabling scanning on existing projects, and rotate any value that has appeared in job logs.

Plan egress for analyzers and advisory data

Scanning on self-managed or offline instances needs access to analyzer container images and, for some scanners, vulnerability advisory data. Decide whether runners reach these from a internal registry mirror, a proxy or the open internet, and document each destination. In air-gapped environments, GitLab's offline guidance covers separate steps for security scanners. Confirm with GitLab exactly which images and data sources each scanner version needs before you open or close any firewall rule.

Control retention and access to findings

Scan reports, vulnerability records and merge request widgets can reveal unpatched weaknesses in your code to anyone with project access. Decide who can view and triage findings, which roles can dismiss them, and how long artifacts stay in the pipeline before expiry. Align artifact expiration and project visibility with your data classification, and confirm how dismissal reasons are recorded for audit purposes.

Keep the scanner stack on the release cadence

Scanner analyzers and the GitLab instance move together, and GitLab ships minor releases on a monthly schedule. Security fixes are backported to the previous two monthly releases, while bug fixes go only to the current stable release, so falling behind leaves known weaknesses unpatched. Schedule a monthly review of minor releases, keep Runner versions aligned with the instance, and check required upgrade stops before planning larger jumps.

Questions teams ask before scoping SAST work

How much does adding SAST cost on Free or Premium compared with Ultimate?

The cost depends first on which tier includes the scanning features you need, so confirm that on GitLab's pricing page before you budget. GitLab Free costs nothing, Premium is listed at 29 US dollars per user per month billed annually, and Ultimate is custom priced, which means its quote depends on seat count, add-ons and contract terms. The page places application security testing under Ultimate, so a Premium plan may not cover every scanner you want. The total also includes one-time implementation effort, recurring runner compute, and recurring time for developers and security staff to triage findings. Ask any partner for a quote that lists the tier, the scanners, the seat count, the runner plan and the training as separate lines.

How long does a SAST rollout take, and what drives the timeline?

The timeline depends mainly on how many projects and pipelines will be scanned, how many languages those projects use, and how much tuning the team expects before findings reach developers. Each project with its own CI/CD configuration adds review work, and shared pipeline templates can reduce it if they already exist. Runner capacity, approval workflows and any offline or air-gapped constraints also add steps. A rollout that starts with a pilot group of projects, then widens in stages, is easier to plan than an all-at-once switch. Ask for a phased plan in writing, with the pilot scope, the exit criteria for each phase and the decisions the client team must make before each phase begins.

What does the client team need to provide for a SAST engagement?

The client team needs to provide access and decisions. Expect to name a GitLab administrator who can change instance settings, a group owner for each set of projects in scope, and a pipeline owner who knows each project's CI/CD configuration. Someone must decide which tier the organization will buy and which scanners it needs. The security team should own the triage policy, including severity thresholds and who may suppress a finding. If runners will run on your infrastructure, the platform team must provide hosts or accounts, network paths and access to the image sources your jobs use. For offline instances, the team must also arrange how analyzer images and updates reach the network.

Can an internal team add SAST without outside help?

An internal team can add SAST alone if it already administers GitLab, writes CI/CD pipelines confidently and has someone who can run a pilot without disrupting releases. The harder parts usually lie elsewhere: confirming which features each tier includes, hardening the runners that execute scans, setting up scanning on an offline instance, and tuning results so developers trust them. Teams without recent experience in these areas often take longer to reach a usable state. A useful middle path is to run one pilot project internally, record every decision and configuration change, and then decide whether the remaining projects need outside help. Whichever route you choose, write down the ownership of the scanning pipeline before the pilot begins.

How many GitLab Runners does security scanning need?

No single number fits every instance, because scan jobs compete with build and test jobs for the same runner capacity. Capacity depends on how many pipelines run at the same time, how long each scan takes, and how many scans run on each merge request. Start by measuring queue time during the pilot, then add capacity where jobs wait. Autoscaling executors let the fleet grow and shrink with demand, and the Runner documentation describes the executor options. Keep Runner major and minor versions aligned with the GitLab version, since the documentation advises that. Also plan the runner hosts for isolation, because scan jobs run code from your repositories. Ask any partner to size the fleet from measured pipeline volume, not from an assumed count.

How should teams triage SAST findings without blocking every merge?

Start in a report-only mode, where findings appear on the merge request but do not stop the merge. Use that period to measure how many results are real, which rules produce noise, and which teams need training on the flagged patterns. Then set blocking rules only for high-severity findings in the projects where the team has tuned results. Assign each finding to a named owner, and require a reason for every suppression so that false positives can be reviewed later. Ultimate includes the vulnerability management features that track findings across projects, and the tier question affects how much of this workflow you can run in the platform. Agree on these rules with the security team before the first blocking rule goes live.

Does SAST work on an offline or air-gapped GitLab instance?

GitLab documents running self-managed instances in offline, air-gapped environments and publishes separate guidance for its security scanners, so offline scanning is a supported path to plan for, not an assumption to make. The practical questions are how analyzer images get into the environment, how rule and analyzer updates reach it, and who approves each transfer. Confirm each step against the offline guidance for your GitLab version before you commit to a design. Plan the update cadence, since an offline instance also has to follow GitLab's release and upgrade schedule. Ask for a written list of the artifacts that will cross the network boundary and the approval steps for each one.

How scope and quote follow the written plan

DeployOpen scopes SAST work in writing before any delivery starts. The written scope names the GitLab tier you will run, the projects and groups that will be scanned, the runners that will execute the scan jobs, and the environment the scanners must work in. Most engagements are fixed-scope, so the deliverables and the acceptance checks are agreed on paper before a quote is final. A quote follows from that document, not from a general estimate of what security scanning usually costs.

The quote depends on four inputs. The first is the tier decision: Free and Premium do not include Advanced SAST, merge request vulnerability management or the wider application security testing features that Ultimate adds, so the work on each tier differs. The second is the number of projects and the languages they use, since onboarding, analyzer tuning and triage of first results scale with that count. The third is the runner fleet, including whether capacity already exists or must be built, because scan jobs need runner capacity of their own. The fourth is offline need: air-gapped installs require the offline guidance for the scanners and a plan for updating analyzer content, which adds build and verification work. Ask each bidder to state which of these inputs they assumed.

Before you sign, confirm which items are one-time and which recur. Initial configuration, pipeline changes and the first triage are one-time costs. Tier licensing is billed per user per month on Premium (the pricing page lists 29 US dollars per user per month billed annually) and on Ultimate is custom priced, so ask your GitLab account team for the current Ultimate figure. Retained support, analyzer upgrades and rule tuning recur. Ask the bidder to show the change control path for scope changes, such as adding a project mid-engagement, so that a later request does not silently reopen the quote.

How DeployOpen delivers GitLab security scanning

DeployOpen plans, implements and hands over GitLab security scanning inside your own infrastructure, including runner capacity and the offline setup where it applies. Engagements are fixed-scope, so the scanners, tier decisions, runner design and evidence you receive are agreed in writing before work starts.

How we scope

  • Confirm your GitLab tier and which scanners you need on Free, Premium or Ultimate before any build work begins
  • Map languages, repositories and pipelines to the SAST analyzers and Advanced SAST coverage you plan to use
  • Agree in writing whether merge request findings, vulnerability management and security policies are in or out of scope
  • Identify whether the instance runs air-gapped, which changes how scanner content and updates reach your runners

How we build

  • Configure SAST templates and analyzer settings in pipelines, with exclusions reviewed and recorded for each project
  • Size and secure the runner fleet that executes scans, including isolation, tags and capacity for peak merge request volume
  • Test findings on sample repositories so developers see merge request results that match the agreed scanner configuration
  • Document each analyzer version and the update procedure so scanner changes follow your GitLab upgrade and change process

How we hand over

  • Deliver a written runbook covering pipeline configuration, runner setup, triage workflow and vulnerability management ownership
  • Provide test evidence showing scans ran, findings surfaced in merge requests and runners completed jobs as designed
  • Walk your security and platform engineers through triage, false-positive handling and how to add new projects
  • Record the agreed scope, tier assumptions and open items so your team can audit what was built and why

How we support

  • Ongoing support, upgrades and continuous testing are available as retainers, scoped separately from the implementation
  • Review scanner and runner versions against GitLab release cycles and required upgrade stops when your instance moves
  • Re-run agreed scan tests after GitLab, runner or analyzer upgrades to confirm findings and pipelines still behave as documented
  • Confirm with GitLab which capabilities your tier and offline setup support before planning changes to scanning scope

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.