Architecting Application Security via GitLab Static Application Security Testing

Static Application Security Testing, commonly referred to by the acronym SAST, represents a fundamental pillar of the DevSecOps pipeline. In the context of GitLab, SAST functions as a mechanism to search for known vulnerabilities within the source code of a project before the application is ever deployed to a production environment. By analyzing the code in a non-running state, GitLab SAST analyzers can identify security flaws—such as Cross Site Scripting (XSS), insecure API usage, or hardcoded credentials—allowing developers to separate false positives from genuine threats that require immediate remediation.

The integration of SAST into the GitLab CI/CD pipeline ensures that security is not a final checkpoint but a continuous process. This "shifting left" approach minimizes the cost and complexity of fixing bugs, as vulnerabilities are discovered during the coding phase rather than after a breach in a live environment. The process relies on a series of analyzer jobs that scan the codebase and produce detailed JSON report files, which are then processed to provide actionable insights into the security posture of the application.

Implementing SAST Analyzers in GitLab CI/CD

The deployment of SAST within a GitLab project is primarily managed through the .gitlab-ci.yml configuration file. To activate these security scans, a project must include the standardized SAST template, which defines the necessary jobs and stages for the analyzers to execute.

To initiate the process, the following configuration is applied to the .gitlab-ci.yml file:

yaml include: - template: Security/SAST.gitlab-ci.yml variables: SAST_DEFAULT_ANALYZERS: "eslint,nodejs-scan,phpcs-security-audit"

This specific configuration triggers three distinct analyzers: eslint, nodejs-scan, and phpcs-security-audit. These analyzers operate within the test stage of the pipeline, each executing as an independent job. The immediate result of these operations is the generation of a report file named gl-sast-report.json.

The impact of this configuration is that it automates the detection of language-specific vulnerabilities. For instance, a nodejs-scan report might identify a vulnerability in a Vue.js template where an unescaped variable exists. This specific flaw allows untrusted user input to be passed to the variable, directly resulting in a Cross Site Scripting (XSS) vulnerability. Such a finding is delivered in a structured JSON format, detailing the vulnerability ID, category, name, and a descriptive message to guide the developer toward a fix.

The Architecture of Analyzers and Checkers

A sophisticated implementation of GitLab SAST involves a two-tier process consisting of analyzers and checkers. The analyzer is the initial tool that scans the code and produces the gl-sast-report.json artifact. However, to effectively manage these findings, "checker" jobs (such as sast-vuln:nodejs-scan-sast) are utilized.

The relationship between these jobs is defined by the needs keyword. The presence of the needs keyword indicates that the checker job can start immediately after the corresponding analyzer job finishes. This architectural choice ensures a streamlined pipeline where the checker retrieves all generated job artifacts from the analyzer to process the results.

This pattern is applicable across all GitLab SAST analyzers. While the logic remains the same, the specific job names and the analyzer images used in the test stage must be adjusted to match the language being scanned.

Advanced SAST and Specialized Tooling

GitLab provides a tiered approach to security scanning, with the Ultimate tier offering GitLab Advanced SAST. This advanced offering provides more accurate results and is available across GitLab.com, GitLab Self-Managed, and GitLab Dedicated offerings.

The toolset varies based on the language and framework being utilized:

  • Semgrep: Used as the primary analyzer with GitLab-managed rules unless otherwise specified.
  • SpotBugs: Utilizes the find-sec-bugs plugin and supports Gradle, Maven, and SBT. It is also compatible with the Gradle wrapper, Grails, and the Maven wrapper. However, SpotBugs has documented limitations when used against Ant-based projects. For Java or Scala projects using Ant, users are directed toward the GitLab Advanced SAST or Semgrep-based analyzers.
  • Android Support: SAST capabilities extend to include Android project scanning.
  • Kubesec: The SAST CI/CD template includes an analyzer job for scanning Kubernetes manifests and Helm charts, although this is disabled by default. Users can enable the Kubesec analyzer or transition to IaC (Infrastructure as Code) scanning for broader platform support.

Managing SAST in Offline and Restricted Environments

For organizations with strict network security policies, GitLab allows the operation of SAST in offline environments. This requires the use of local Docker registries to host the analyzer images, preventing the runner from attempting to pull images from the public internet.

The following images should be imported from registry.gitlab.com into a local Docker container registry:

Image Path Version/Tag
registry.gitlab.com/security-products/gitlab-advanced-sast 2
registry.gitlab.com/security-products/kubesec 6
registry.gitlab.com/security-products/pmd-apex 6
registry.gitlab.com/security-products/semgrep 6
registry.gitlab.com/security-products/sobelow 6
registry.gitlab.com/security-products/spotbugs 5

In these offline environments, the GitLab Runner pull_policy must be set to if-not-present. This ensures the runner uses locally available images. Conversely, in online environments, the policy should remain as always to ensure that the most updated and secure scanners are utilized in the CI/CD pipelines.

FIPS Compliance and Image Configuration

For environments requiring FIPS 140-validated cryptographic modules, GitLab offers specialized images based on the Red Hat UBI base image. These FIPS-compliant images are exclusively available for the GitLab Advanced SAST and Semgrep-based analyzers.

To implement FIPS compliance, the SAST_IMAGE_SUFFIX variable must be configured:

yaml variables: SAST_IMAGE_SUFFIX: '-fips' include: - template: Jobs/SAST.gitlab-ci.yml

Alternatively, the -fips extension can be added directly to the default image name. To ensure a fully FIPS-compliant operation, all other non-FIPS analyzers must be excluded from the run. Furthermore, if the FIPS-enabled image is running in a Kubernetes runner with a non-root user, the run_as_user attribute under runners.kubernetes.pod_security_context must be updated to use the ID 1000, which corresponds to the gitlab user created by the image.

Customizing Rulesets and Excluding Paths

To reduce noise and eliminate false positives, GitLab allows developers to customize the rulesets and exclude specific files from being scanned.

Rule Customization

Customization is handled via the .gitlab/sast-ruleset.toml file. For example, to disable a specific rule such as gosec.G107-1, the following configuration is used:

toml [semgrep] [[semgrep.ruleset]] disable = true [semgrep.ruleset.identifier] type = "semgrep_id" value = "gosec.G107-1"

Path Exclusion

To prevent the scanning of temporary code, test suites, or specific files that are known to be safe, the SAST_EXCLUDED_PATHS variable is used. This requires the user to have a Developer, Maintainer, or Owner role.

Example for excluding a specific file:

yaml variables: SAST_EXCLUDED_PATHS: "rule-template-injection.go"

Handling Vulnerability Tracking and False Positives

Because source code is volatile, vulnerabilities may move between files or shift positions as developers modify the codebase. GitLab's Advanced Vulnerability Tracking (available in the Ultimate tier) links vulnerabilities to specific problematic code fragments, ensuring they can be tracked and fixed even as the code evolves.

When a vulnerability is automatically resolved, the Vulnerability Management system leaves a comment to maintain a historical record. If a previously disabled rule is re-enabled, the associated findings are reopened for triage.

To manage false positives within the code itself, analyzers use specific tags to ignore portions of the source. However, these tags vary by analyzer, which can create a cognitive burden for developers.

Common examples include:

  • ESLint: const res = eval('42'); // eslint-disable-line
  • PHPCS: $toParse = file_get_contents($argv[1]); // phpcs:ignore

The recommended approach is to standardize these ignores into a consistent tag that specifies the reason for the exclusion, simplifying the process of auditing ignored security warnings.

Rule Governance and Bug Reporting

The definitions for GitLab Advanced SAST rules are stored in a private repository, meaning they are not available for public browsing. This has led to challenges for users attempting to review the specific logic of rules, such as the java_xxe_rule-XMLInputFactoryExternalEntitiesEnabled rule, which identifies improper restrictions of XML external entity references (XXE).

Because these rules are proprietary and part of the Ultimate tier, the process for reporting bugs in a rule is as follows:

  1. Open a bug report in the GitLab issue tracker.
  2. Assign the issue to the group /label ~“group::vulnerability research”.
  3. For further assistance, users are encouraged to open a customer support ticket to coordinate with the product and engineering teams.

Scaling SAST Implementation

Once a project has been successfully secured and the SAST results are validated, the implementation can be scaled across the organization using the following methods:

  • Enforced Scan Execution: This allows security settings to be applied across entire groups, ensuring no project bypasses security scanning.
  • Centralized Rulesets: Organizations can share and reuse a central ruleset by referencing a remote configuration file.
  • Environmental Adaptation: SAST can be configured to run under SELinux constraints or within completely offline environments to meet unique corporate security requirements.

Summary of SAST Report Accessibility

The output of every SAST analyzer is a JSON report generated as a job artifact. To download and review these reports, the user must possess one of the following roles:

  • Developer
  • Maintainer
  • Owner

These reports provide the raw data necessary for security auditors to understand the depth and nature of the vulnerabilities detected within the application.

Conclusion

The integration of GitLab SAST transforms the security process from a manual, periodic audit into an automated, continuous verification system. By leveraging a variety of analyzers—ranging from Semgrep and SpotBugs to specialized tools like Kubesec—GitLab provides a comprehensive shield against a wide array of vulnerabilities. The system's flexibility is evident in its support for FIPS compliance, offline registries, and granular rule customization via TOML files. While the proprietary nature of the advanced rules necessitates a formal bug-reporting process through the vulnerability research group, the overall framework allows for a scalable and rigorous security posture. The transition from simple analyzer jobs to a sophisticated "analyzer and checker" architecture ensures that vulnerabilities are not only detected but tracked through the volatility of the development lifecycle, ultimately reducing the attack surface of the deployed application.

Sources

  1. Secure your project with the GitLab SAST analyzers
  2. GitLab SAST Documentation
  3. GitLab Forum - Advanced SAST Rules Repository

Related Posts