Howdy,Kloudy!
September 14, 2023

GitLab Custom SAST Analyzer for PowerShell Project

Posted on September 14, 2023  •  6 minutes  • 1102 words  
Views
Table of contents

Introduction

In the ever-evolving landscape of infrastructure as code, software development and cybersecurity, ensuring the robust security of your codebase has become paramount. My journey into enhancing the security posture of my PowerShell projects led me to explore the world of GitLab Custom SAST Analyzers.

As a GitLab Security Specialist, I was well-versed in the importance of securing code repositories and the pivotal role that Static Application Security Testing (SAST) plays in this endeavour. GitLab’s commitment to providing a secure DevOps platform is evident, yet I found a particular gap regarding PowerShell projects. There was no default SAST analyzer readily available for this scripting language.

Driven by the need to bridge this gap and bolster the security of my PowerShell projects, I embarked on a journey of innovation and customization. I had already cleared the GitLab Security Specialist certification, which empowered me with the knowledge and expertise to address this challenge effectively.

In this journey, I discovered the power of custom SAST analysis using PSScript Analyzer. Armed with this open-source static code analysis tool designed specifically for PowerShell, I crafted a tailored solution to scan my PowerShell projects for potential security vulnerabilities. PSScriptAnalyzer module offered the flexibility and extensibility needed to create a custom SAST analyzer aligned with my project’s unique requirements.

In this exploration, I enhanced the security of my PowerShell code and realized the potential to contribute to the broader GitLab community by sharing my custom SAST analyzer. This journey represents the essence of DevSecOps - continuous improvement, collaboration, and empowerment.

In the following sections, I will delve into the process of creating a GitLab Custom SAST Analyzer for PowerShell projects, highlighting the steps, challenges, and insights gained along the way. Together, we’ll unlock the power of customized security analysis in the GitLab ecosystem, strengthening the defences of our code one script at a time.

Video

I respect your time and recorded the demonstration of implementing a custom SAST analyzer for the PowerShell project.

What is SAST?

SAST stands for Static Application Security Testing. It is a security testing methodology used in software development and cybersecurity to identify and mitigate security vulnerabilities in source code or compiled binaries before deploying the application. SAST is also known as “white-box testing” because it analyzes an application’s code’s internal structure and logic without executing the software. Highlights of SAST are as follows.

What is PSScriptAnalyzer?

PSScriptAnalyzer is a valuable module in PowerShell scripting and development. It is a powerful static code analysis tool for PowerShell scripts and modules. PSScriptAnalyzer empowers developers and administrators to enhance their PowerShell code’s quality, readability, and security.

I need to implement custom PowerShell rules for the organization’s needs. How to do it? Refer this link

Custom SAST Analyzer report schema

sast-report-format

JSON Schema

{
    "version": "",
    "scan": {
        "start_time": "",
        "end_time": "",
        "status": "success",
        "type": "sast",
        "scanner": {
            "id": "",
            "name": "",
            "url": "",
            "version": "",
            "vendor": {
                "name": ""
            }
        },
        "analyzer": {
            "id": "",
            "name": "",
            "url": "",
            "vendor": {
                "name": ""
            },
            "version": ""
        }
    },
    "vulnerabilities": [
        {
            "id": "",
            "name": "",
            "severity": "",
            "cve": "",
            "location": {
                "file": "",
                "commit": ""
            },
            "start_line": ,
            "identifiers": [
                {
                    "type": "",
                    "name": "",
                    "value": ""
                }
            ],
            "scanner": {
                "id": "",
                "name": ""
            }
        }
    ]
}

PowerShell Script to generate GL-SAST-REPORT.JSON

Install-Module -Name PSScriptAnalyzer -Scope CurrentUser -Repository PSGallery -Force
$Collection = @()
$vulnerabilities = (Get-ChildItem -Path . -Exclude test.ps1 | Invoke-ScriptAnalyzer )
for ($i = 0; $i -lt $vulnerabilities.Count; $i++) {  
    $vulnerability = [PSCustomObject]@{
        id          = $(New-Guid).Guid
        name        = $($vulnerabilities[$i].RuleName)
        severity    = $(
            switch ($vulnerabilities[$i].Severity.ToString()) {
                'Error' {
                    'Critical'
                }
                'Warning' {
                    'Low'
                }
                'Information' {
                    'Info'
                }
                default {
                    'Unknown'
                }
            }
        )
        cve         = $([string]::Concat('id:', $((New-Guid).Guid), ':' , $(Get-Random -Maximum 10 -Minimum 1)))
        location    = [pscustomobject]@{
            file   = $([string]::Concat($($vulnerabilities[$i].ScriptName), '-' , $($vulnerabilities[$i].Line)))
            commit = '0000000'
        }
        start_line  = $($vulnerabilities[$i].Line)
        identifiers = @([pscustomobject]@{
                type  = $(New-Guid).Guid
                name  = $($vulnerabilities[$i].RuleName)
                value = $([string]::Concat('id:', $((New-Guid).Guid), ':' , $(Get-Random -Maximum 10 -Minimum 1)))
            })
        scanner     = [pscustomobject]@{
            id   = $(New-Guid).Guid
            name = "Gitleaks"
        }
    }
    $Collection += $vulnerability
}

$jsonObject = [PSCustomObject]@{
    version         = "15.0.4"
    scan            = [pscustomobject]@{
        start_time = $(Get-Date -Format 'yyyy-MM-dd%THH:mm:ss')
        end_time   = $(Get-Date -Format 'yyyy-MM-dd%THH:mm:ss')
        status     = "success"
        type       = "sast"
        scanner    = [pscustomobject]@{
            id      = $(New-Guid).Guid
            name    = "PowerShell Script Analyzer - $((New-Guid).Guid)"
            url     = "https://learn.microsoft.com/en-us/powershell/module/psscriptanalyzer/?view=ps-modules"
            version = "development"
            vendor  = [pscustomobject]@{
                name = "Microsoft"
            }
        }
        analyzer   = [PSCustomObject]@{
            "id"      = $(New-Guid).Guid
            "name"    = "PSScriptAnalyzer"
            "url"     = "https://gitlab.com/gitlab-org/security-products/analyzers/secrets"
            "vendor"  = [PSCustomObject]@{
                "name" = "Microsoft"
            }
            "version" = "1.21.0"
    
        }
    }
    vulnerabilities = $Collection
}
$jsonObject | ConvertTo-Json -Depth 9 | Out-File "gl-sast-report.json"

Install PSScriptAnalyzer

This command installs the PSScriptAnalyzer module from the PowerShell Gallery for the current user.

Install-Module -Name PSScriptAnalyzer -Scope CurrentUser -Repository PSGallery -Force

Initialize Variables

This initializes an empty array called $Collection to store vulnerability information.

$Collection = @()

Run Script Analyzer

This command runs PSScriptAnalyzer on all PowerShell script files in the current directory (excluding test.ps1) and stores the results in the $vulnerabilities variable. Iterate Through Vulnerabilities

$vulnerabilities = (Get-ChildItem -Path . -Exclude test.ps1 | Invoke-ScriptAnalyzer)
for ($i = 0; $i -lt $vulnerabilities.Count; $i++) {

This starts a loop to iterate through the detected vulnerabilities.

Create Vulnerability Object

$vulnerability = [PSCustomObject]@{ ... }

Inside the loop, a custom object is created to represent each vulnerability. The object includes fields such as ID, name, severity, location, identifiers, and scanner information. Severity is also mapped from ‘Error’, ‘Warning’, and ‘Information’ to ‘Critical’, ‘Low’, and ‘Info’, respectively.

Add Vulnerability to Collection

$Collection += $vulnerability

Each vulnerability object is added to the $Collection array.

Create JSON Report

$jsonObject = [PSCustomObject]@{ ... }

After processing all vulnerabilities, a JSON report object is created. It includes version information, scan details, and the list of vulnerabilities from the $Collection array. Convert to JSON and Save

$jsonObject | ConvertTo-Json -Depth 9 | Out-File "gl-sast-report.json"

The report object is converted to JSON with a depth of 9 (usually sufficient), and the JSON content is saved to a file named “gl-sast-report.json.” When you run this PowerShell script, it will analyze your PowerShell scripts using PSScriptAnalyzer module , convert the results into a GitLab-compatible SAST report in JSON format, and save it to the specified file. You can then use this report to integrate security analysis into your GitLab CI/CD pipelines.

GitLab Pipeline

.gitlab-ci.yml

image: mcr.microsoft.com/powershell
 
stages:
  - "ps_sast"
 
ps_sast:
  stage: ps_sast
  script: 
    - pwsh -f ".\test.ps1"
  artifacts:
    reports:
      sast: gl-sast-report.json
    paths:
      - gl-sast-report.json

Output

Output

References

Social Networking

Let us stay connected to learn, share and grow!