CodeSonar GitLab CI/CD Documentation

Overview

CodeSonar can be used in a GitLab CI/CD pipeline to perform static analysis of project source code. GitLab provides this capability through its Static Application Security Testing (SAST) feature. GitLab can display the results of static analysis associated with your pipeline jobs. This feature is made possible by providing GitLab with a specially formatted SAST report artifact after a static analysis pipeline job completes.

The CodeSonar GitLab Integration package provides a utility for representing CodeSonar analysis results in GitLab's SAST report format. The package also provides some templates for setting-up your CI/CD pipelines to use CodeSonar, which are intended to make it easier for you to get started.

A typical way to use a GitLab CI/CD pipeline is to arrange for it to be executed whenever new Git commits are submitted to a Merge Request. When you add CodeSonar static analysis to your merge request pipeline, GitLab will display the new analysis warnings that are introduced by your merge request on the merge request page. The full set of warnings is always available on the pipeline page.

Contents

Download

You can download the integration kit using this link which requires a support portal login.

Prerequisites

  1. You must setup a working instance of GitLab Ultimate edition. GitLab provides a 30-day free trial of their Ultimate edition license. Instructions can be found at https://about.gitlab.com/install.

  2. You must have a source code project in your GitLab instance that you wish to analyze. You must setup a GitLab CI/CD pipeline for your project that can build your source code successfully. This will include configuration of one or more GitLab pipeline job Runners.

  3. If you use Docker, then please ensure you have Docker Engine version 19.03.12 or later.

  4. You must have a copy of the CodeSonar software package which is appropriate for your GitLab pipeline job runner's operating platform.

  5. You must setup a dedicated, "persistent" CodeSonar Hub to coordinate and receive the results of your analysis. See your CodeSonar manual for how to setup and license a Hub.

  6. You will need a valid CodeSonar Hub license appropriate to your configuration.

  7. You must have a copy of the CodeSonar GitLab Integration software package.

Basic Setup using Docker

I: Basic Docker pipeline setup before adding CodeSonar

We assume that you have performed the following steps to setup a new project for your source code in GitLab with a CI/CD pipeline:

1. Create a GitLab project and push your source code to the projects repository on your GitLab server.

For more information see: https://docs.gitlab.com/ee/user/project/

2. Configure one or more GitLab pipeline job runners to run pipeline jobs using Docker.

For information about GitLab CI/CD see: https://docs.gitlab.com/ee/ci/

For information about GitLab pipeline job runners see: https://docs.gitlab.com/ee/ci/runners/

3. Create a base Docker image that has all the necessary requirements to build your source code.

For information about using Docker in your GitLab pipeline see: https://docs.gitlab.com/ee/ci/docker/

An example Dockerfile for building a simple C/C++ project looks like:

FROM ubuntu:18.04
RUN apt-get update && apt-get install -y gcc make

4. Build, Tag, and Push your Docker image to your GitLab project's container registry.

For information about GitLab container registries see: https://docs.gitlab.com/ee/user/packages/container_registry/

You'll need to know the URL for your GitLab project's container registry. You can find the container registry URL in the GitLab UI for your project under the "Packages & Registries" menu. Usually, the URL takes the form: HOST/GROUP/PROJECT. Example commands to build, tag, and push your image to the container registry look like:

> CI_REGISTRY=gitlab.yourdomain.tld
> CI_REGISTRY_IMAGE=$CI_REGISTRY/group/project
> CI_IMAGE_TAG=v1
> docker login $CI_REGISTRY
> docker build -t $CI_REGISTRY_IMAGE:$CI_IMAGE_TAG - < Dockerfile
> docker push $CI_REGISTRY_IMAGE:$CI_IMAGE_TAG

5. Configure a CI/CD pipeline that can build your code in a Docker pipeline job using your base Docker image.

This involves creating a GitLab .gitlab-ci.yml file with instructions to build your source code. This file must be saved in the root of your repository.

For information about the .gitlab-ci.yml file see: https://docs.gitlab.com/ee/ci/yaml/gitlab_ci_yaml.html

If you are not familiar with YAML format, you may want to read about it at: https://yaml.org/spec/1.2/spec.html#Preview

Be sure to configure the pipeline to execute for Merge Requests. You can use the workflow:rules keywords for this. See: https://docs.gitlab.com/ee/ci/merge_request_pipelines/ and see the additional comments in "Addendum A" further below.

An example .gitlab-ci.yml file file looks like:

workflow:
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

stages:
   - build

build_job:
   stage: build
   image: $CI_REGISTRY_IMAGE:v1
   script:
       - ./configure
       - make all

6. Commit and push your .gitlab-ci.yml file to your GitLab project's repository.

For example:

> git checkout -b basic_ci
> git add .gitlab-ci.yml
> git commit -m "Add gitlab-ci configuration"
> git push origin basic_ci

7. Create a Merge Request for the branch you just pushed.

The git push command may print a URL to help you create a merge request. Otherwise, you can use the GitLab GUI to create a new merge request associated with your new branch.

8. Verify that your pipeline executes and builds your source code successfully from your merge request.

II: Add CodeSonar to your base Docker pipeline configuration:

With your project and pipeline configuration setup and working, we can now add CodeSonar to the pipeline with the following steps:

1. Extract the CodeSonar GitLab Integration .tar file.

2. Find the distro-image subdirectory in the extracted files.

This directory contains a Dockerfile that can be used to create a new Docker image from your project's base image with CodeSonar installed added to it.

3. Copy your CodeSonar software install package .tar file into the distro-image directory.

The Dockerfile contains instructions to extract the CodeSonar programs from the CodeSonar install package and copy them into the "/opt" directory in the Docker image. It will also set the default system $PATH environment variable in the image to include the CodeSonar commandline tools.

4. Copy your CodeSonar Hub license into a file named license.txt and save it in the distro-image directory.

5. Build a new CodeSonar Docker image using the Dockerfile found in the distro-image subdirectory:

This new CodeSonar Docker image will be based on your project's base Docker image.

Consult the comments in distro-image/Dockerfile for descriptions of the Docker build arguments used in this section.

Note also that some of the variables used here were initialized in a previous step (see above).

If your CodeSonar Hub HTTPS certificate is not trusted by CodeSonar, you may want to see Addendum B (further below). This is important if you are using a self-signed HTTPS certificate or if your certificate is not signed by a well-established Certificate Authority.

To build the image, modify the following commands as needed and execute:

> CODESONAR_PACKAGE=codesonar-5.4p0.20200911-x86_64-pc-linux.tar.gz
> CODESONAR_IMAGE_TAG=$CI_IMAGE_TAG-codesonar
> docker build --tag $CI_REGISTRY_IMAGE:$CODESONAR_IMAGE_TAG \
      --build-arg BASE_IMAGE=$CI_REGISTRY_IMAGE:$CI_IMAGE_TAG \
      --build-arg CODESONAR_PACKAGE=$CODESONAR_PACKAGE \
      --build-arg CODESONAR_LICENSE=license.txt \
      --build-arg CODESONAR_HUB_CACERT=cacert.pem \
      --build-arg HUB=1 \
      --build-arg PYTHON_API=1 \
      --build-arg TELEMETRY=1 \
      --build-arg JAVA_ANALYSIS=0 \
      --build-arg PYTHON_ANALYSIS=0 \
      --build-arg JAVA_API=0 \
      --build-arg CSHARP_API=0 \
      --build-arg GITHUB_SARIF=0 \
      --build-arg ECLIPSE=0 \
      --build-arg CMDLINE_UTILITIES=0 \
      --build-arg CONFIG_TOOL=0 \
      --build-arg GENERATE_CERT=0 \
      .

6. Push the new CodeSonar Docker image to your container registry:

> docker login $CI_REGISTRY
> docker push $CI_REGISTRY_IMAGE:$CODESONAR_IMAGE_TAG

7. Setup your CI/CD pipeline to use CodeSonar with your new Docker image.

Look in the example directory of the CodeSonar GitLab integration directory. Find the file named .codesonar_persistent_hub.yml (you may need to use "ls -a" to see it).

This file is a template which defines a GitLab pipeline job which will execute CodeSonar to analyze your code. Copy this file into your repository directory.

8. Open the .yml file that you copied to your repository in a text editor.

Note that this .yml file will make use of several custom environment variables which you must configure on your GitLab project. You may need to make several changes, including:

  • Update the docker image item so that it correctly refers to the CodeSonar Docker image you created above. You may want to replace the CODESONAR_CI_REGISTRY variable with the predefined CI_REGISTRY_IMAGE variable if you are using your GitLab container registry to host your Docker images. You will also want to replace the "tag" part of the image name. In the examples above, the tag for the codesonar image is v1-codesonar.
  • Update the codesonar commands to ensure they specify Hub authentication options appropriate to your CodeSonar Hub.
  • Look for the codesonar analyze command and modify it so that it executes the build command you use for your project.

An example, modified .codesonar_persistent_hub.yml looks like:

.codesonar_sast:
  stage: test
  image: $CI_REGISTRY_IMAGE:v1-codesonar
  variables:
    SARIF2SAST: "/opt/cso-sarif2sast"
  before_script:
    - codesonar create-conf ${CI_PROJECT_NAME}
  script:
    - ./configure
    - >
        codesonar analyze ${CI_PROJECT_NAME}
        -foreground
        -auth password
        -hubuser ${CODESONAR_HUBUSER}
        -hubpwfile ${CODESONAR_HUBPWFILE}
        ${CODESONAR_HUB_URL}
        make all |& tee analysis.log
    - export A_ID=$(cat ${CI_PROJECT_NAME}.prj_files/aid.txt)
    - >
        codesonar get
        -auth password
        -hubuser ${CODESONAR_HUBUSER}
        -hubpwfile ${CODESONAR_HUBPWFILE}
        -o allwarnings.sarif
        ${CODESONAR_HUB_URL}/analysis/${A_ID}-allwarnings.sarif?filter=${CODESONAR_VISIBILITY_FILTER}
    - >
        cspython $SARIF2SAST/sarif2sast.py
        --sarif allwarnings.sarif
        --output gl-sast-report.json
        --summary-report sast-summary-report.md
        --codesonar-url ${CODESONAR_HUB_URL}
        --analysis-id ${A_ID}
        --max ${CODESONAR_MAX_WARNINGS}
        --threshold ${CODESONAR_WARNING_THRESHOLD}
  after_script:
    - >
        cspython $SARIF2SAST/upload_gitlab_mr_notes.py
        --api-token-variable GITLAB_TOKEN
        --report sast-summary-report.md
  artifacts:
    reports:
      sast: gl-sast-report.json

9. Update your gitlab-ci.yml file to include the .codesonar_persistent_hub.yml file that you just added to your repository.

You will need to add instructions to invoke your new CodeSonar job definition. For example, adding the CodeSonar job to the example .gitlab-ci.yml file shown further above might look like:

workflow:
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

include:
  - local: '.codesonar_persistent_hub.yml'

stages:
  - build
  - codesonar

build_job:
  stage: build
  image: $CI_REGISTRY_IMAGE:v1
  script:
    - ./configure
    - make all

codesonar_job:
  stage: codesonar
  extends: .codesonar_sast

10. Before you commit and push your changes to these .yml files, you should add the custom variables used by the .yml files to your GitLab project via the GitLab UI.

See the comments in the template .yml file for a description of what these variables represent.

Note that the CODESONAR_HUBPWFILE must be configured as a File-type variable.

Type Key Example value
Variable CODESONAR_CI_REGISTRY gitlab.example.com:5050/acmeinc/codesonar-ci
Variable CODESONAR_HUB_URL https://codesonar.example.com:7443
Variable CODESONAR_HUBUSER gitlab
File CODESONAR_HUBPWFILE password
Variable CODESONAR_MAX_WARNINGS 5
Variable CODESONAR_VISIBILITY_FILTER 2
Variable CODESONAR_WARNING_THRESHOLD 60
Variable GITLAB_TOKEN BSDrHhFPWJkq3F9w5kfy

Some of these variables contain sensitive information that must be secured.

The GITLAB_TOKEN variable is used to automatically generate a Merge Request comment containing a summary of the CodeSonar analysis. To use this feature, you will need to generate an a GitLab API Access Token. GitLab provides several ways to do this. For Personal (User) Access Tokens, see https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html.

Consider using a restricted user account for the the Hub user and for any GitLab user associated with the GITLAB_TOKEN. Also consider using GitLab's Masked and Protected options for sensitive variable values when possible.

11. Before commiting your changes, create a new branch for your .yml files:

For example, if you decide to name your branch "codesonar_ci":

> git checkout -b codesonar_ci

12. Add and commit your .yml files to your Git repository and push the changes to GitLab.

For example:

> git add .gitlab-ci.yml .codesonar_persistent_hub.yml
> git commit -m "Add CodeSonar pipeline job"
> git push origin codesonar_ci

13. Follow GitLab instructions to create a Merge Request for your new branch.

14. When the pipeline completes, you should see "security scanning" results on the Merge Request Overview page.

Click the "View Full Report" button to see the analysis results. Notice that the results shown in the "Full Report" are associated with a pipeline.

Addendum A: Merge Request Pipeline and workflow:rules

By default, GitLab will trigger a pipeline whenever a branch is updated. However, a simple "Branch Pipeline" is not quite the same as a "Merge Request Pipeline". The CodeSonar GitLab Integration tools can post a summary report of analysis results from your pipeline to your Merge Request, but they can only do this for Merge Request pipelines.

For more information about configuring Merge Request pipelines, see: https://docs.gitlab.com/ee/ci/merge_request_pipelines/

There are several ways to configure Merge Request piplines. The example above showed how to use the workflow:rules keywords to restrict your pipelines to either of two conditions:

  1. Merge Request Pipelines (which contain special Merge Request environment variables)
  2. Or any pipeline executed on the default branch.

This configuration is reasonable for teams that work heavily through Merge Requests, but it may not be sufficient if you rely on simple branch updates to trigger pipelines outside of a Merge Request.

Addendum B: Trusted HTTPS Hub Certificate

If you are using a self-signed HTTPS certificate for your Hub, or if your Hub certificate is not otherwise trusted by default, then you can add the certificate to the Hub when you build the CodeSonar Docker image.

One way to do this is to replace the distro-image/cacert.pem file with a copy of your HTTPS certificate in .pem format.

The .pem certificate can be downloaded from the CodeSonar Hub. Go to Settings -> HTTP -> Configure HTTPS.

Addendum C: Trusted HTTPS GitLab Certificate

The CodeSonar GitLab Integration tools will attempt to post a summary report of the analysis to your merge request. If the CodeSonar cspython does not trust your GitLab server's HTTPS certificate you will see an "SSL" error in your pipeline job log. You can optionally provide a custom ASCII-encoded certificate authority (CA) file to the upload_gitlab_mr_notes.py script using the --cafile option. The CA file should include the root certificate of the certificate authority signing chain for your GitLab HTTPS certificate.

Most browsers provide a way to download an HTTPS certificate in ASCII format. The instructions for downloading the certificate are dependent on both the type of browser and the operating system. For example, using Google Chrome on Linux, you can "Export" the top certificate in the "Certificate Hierarchy" in "Base64-encoded ASCII, single certificate" format. Using Google Chrome on Windows, you can "View" the top certificate in the "Certificate Path", and "Copy to File" using "Base-64 encoded X.509 (.CER)" format.

Example YAML configuration:

  ...
  after_script:
    - >
        cspython $SARIF2SAST/upload_gitlab_mr_notes.py
        --api-token-variable GITLAB_TOKEN
        --report sast-summary-report.md
        --cafile path/to/your/gitlab_certificate.pem

More Information:

Merge requests and security dashboard

GitLab uses merge requests to make requests for changes, as well as running the pipeline. When you create a merge request in GitLab, the pipeline will automatically be triggered. When the job has finished, you'll see a section with security warnings. The integration does not offer configuration to mark a build as successful or failed, hence every analysis will have a green checkmark unless there were errors executing any of the commands in the pipeline.

Under a merge request, you can see the warnings that were found by CodeSonar. There are two identifiers for every warning, however, GitLab only shows the first in the overview, which is also points to a warning in CodeSonar. The other identifier refers not to a single warning, but to the general overview of the analysis page to which a warning belongs.

overview-vulnerabilities-gitlab.png

When you click one of them, a pop-up is shown that contains more details, as well as links to both the specific line in the file, and a link to the warning in CodeSonar and the general analysis page.

gitlab-popup-warning.png

Note that the link in the warning points to a specific line of a file in GitLab.

In case of CodeSonar problems, e.g., the launch daemon not running correctly, the pipeline may be marked as failed. Pipelines can be started manually under a CI/CD -> Pipeline, and then Run Pipeline. Merge requests and pipelines are often linked together, so the overall status of a pipeline influences if a merge request is marked as either successful or failed. Note also that a failed pipeline can be restarted manually, which re-runs only the failed jobs.

Security dashboard

GitLab provides a dashboard that has quite a few visualization options. The dashboard can be used to visualize the number of security issues across many different projects, e.g., under an organization in GitLab. In addition, you can see the number of security issues in different time intervals, for instance every 30 days.

The identifier for a warning is equivalent to the warning class in CodeSonar, e.g., Missing Return Statement. The link points to a detailed overview of the warning in CodeSonar.

In the Security Dashboard under a project, it is possible to select other types of scanners. CodeSonar warnings are in the SAST category. In case that you enabled other security scanners in GitLab, it may be convenient to select only SAST to getting a better overview. You can sort the list by any of the columns.

security-panel-overview.png

Three icons are present for each warning in the overview. These icons can be used to either create an issue, delete the warning

gitlab-warning-icons-issue.png

The details about the warnings are available in the dashboard. This will refer to the most recent report of the project. GitLab groups warnings into six categories. Note that Critical, Info and Unknown are not used in the warnings that come from CodeSonar. The warnings are translated based on the rank in CodeSonar::

CodeSonar GitLab
0 - 20 Low
21 - 55 Medium
56 - 100 High

The Security Dashboard is accessible using the left-side menu.

project-panel-overview-sec-compliance.png

There are a few key differences to the dashboard compared to the interface in CodeSonar. The interface in GitLab does not allow to filter on function names. Instead, you'll be presented with a list of warnings, which just presents the warnings with an identifier.


Using Windows

Be sure to install Git on your Windows pipeline job runner machine.

You must also install CodeSonar. Installation of CodeSonar is described in the CodeSonar manual under Getting Started With CodeSonar -> Setting Up -> Setting Up The Hub -> Starting a New Hub and it may be convenient to read How Codesonar Works -> CodeSonar As A Windows Service.

In Windows, it may be necessary to check settings in Windows Defender to enable access to your CodeSonar Hub (default port 7340).

Under Windows Defender, you may also need to configure network access for the following CodeSonar programs:

  • cshub.exe
  • codesonar.exe
  • cslaunchd.exe.

You will need to setup a GitLab runner for Windows. This will involve several steps. See https://docs.gitlab.com/runner/install/windows.html

Windows Pipeline configuration

The pipeline configuration is slightly different for Windows. When CodeSonar runs the analysis, a folder with the ${CI_PROJECT_NAME}.prj_files is written in the build directory of the runner.

Installing the sarif2sast conversion script on Windows

The CodeSonar GitLab Integration package includes a set of "sarif2sast" scripts which convert from the CodeSonar Sarif-formatted results into GitLab SAST report format. The sarif2sast conversion scripts are embedded in the distro-image/cso-sarif2sast.tar archive file. The main script of interest is sarif2sast.py which implements a commandline tool that does the Sarif to SAST conversion. You may need a suitable "archiver" program to extract the files from the .tar file on Windows. You should copy entire the contents of this .tar file to your target Windows machine. The files may be placed anywhere in the system, as long as they can be referenced by the pipeline.

Trusted Hub HTTPS Certificate (Windows)

If the CodesSonar Hub is configured to use HTTPS, and if the certificate is not trusted by default, then the certificate must be added to the CodeSonar trust store. This is necessary if your Hub uses a self-signed HTTPS certificate.

You can append the PEM-formatted HTTPS certificate to the gtr\cacerts.pem trusted certificate store file in the CodeSonar installation directory. In the trust-store, the certificate can be given a title to distinguish it from the other certificates in that file. For example:

CodeSonar TLS certificate
=========================
-----BEGIN CERTIFICATE-----
MIIFSDCCBDCg........................................
-----END CERTIFICATE-----

The HTTPS certificate can be downloaded in PEM format from the CodeSonar Hub. Go to Settings -> HTTP -> Configure HTTPS. Read more about CodeSonar Hub Server Certificates in the CodeSonar manual under How CodeSonar works -> CodeSonar Structure -> Hub -> TLS Certificates.

Configuring the CodeSonar Pipeline Job on Windows

We provide an example GitLab pipeline configuration YAML file below which demonstrates how to execute CodeSonar to analyze your code and to convert the analysis results to SAST format for GitLab. Please note that this example uses Powershell. GitLab exposes a number of predefined environment variables through the runner, which we conveniently use in the YAML file. The Powershell Get-Content -Path ... -RAW command ensures that we get the latest analysis id without the final newline. In this example, we use a few custom GitLab project variables to control access to the Hub. The command codesonar get is limited to run for 5 minutes, which can be too short to download results from aa large analysis. You may be able to use Powershell's Invoke-WebRequest command as an alternative.

.codesonar_sast:
  stage: test
  variables:
    SARIF2SAST: 'C:\gitlab-runner\bin\cso-sarif2sast'
  script:
    # Run build with CodeSonar Analyze
    - >
        codesonar analyze ${CI_PROJECT_NAME}
        -foreground
        -auth password
        -hubuser ${CODESONAR_HUBUSER}
        -hubpwfile ${CODESONAR_HUBPASS}
        "${CODESONAR_HUB_URL}"
        make -C test all | tee -FilePath analysis.log
    -  $A_ID = Get-Content -Path ./${CI_PROJECT_NAME}.prj_files/aid.txt -RAW
    - >
        codesonar get
        -auth password
        -hubuser ${CODESONAR_HUBUSER}
        -hubpwfile ${CODESONAR_HUBPASS}
        -O allwarnings.sarif
        "${CODESONAR_HUB_URL}/analysis/${A_ID}-allwarnings.sarif?filter=${CODESONAR_VISIBILITY_FILTER}"
    - >
        cspython "${SARIF2SAST}\sarif2sast.py"
        --sarif allwarnings.sarif
        --output gl-sast-report.json
        --summary-report sast-summary-report.md
        --codesonar-url "${CODESONAR_HUB_URL}"
        --analysis-id ${A_ID}
        --max ${CODESONAR_MAX_WARNINGS}
        --threshold ${CODESONAR_WARNING_THRESHOLD}
  after_script:
    - >
        cspython "${SARIF2SAST}\upload_gitlab_mr_notes.py"
        --api-token-variable GITLAB_TOKEN
        --report sast-summary-report.md
  artifacts:
    reports:
      sast: gl-sast-report.json

CodeSonar ships with a Python distribution called cspython which we use here to convert analysis results to GitLab's SAST format. Please make sure all the tools are in the environment variable PATH, so they can be invoked from either the command line or PowerShell.

PowerShell may be problematic with interactive shells, and in this case, you may switch to the regular command prompt instead. Either PowerShell or the command prompt can be started as the administrator user, which may be required.

Troubleshooting the integration

The Sarif file is the basis of what is rendered in GitLab. The conversion may include warnings that are not relevant for the project. If you see warnings for files that are not in the repository. In this case, you can configure the variable SYSTEM_INCLUDE_PATHS as described under Using CodeSonar -> General -> Compiler-Independent Configuration File Parameters. This variable applies to both a Unix setup and a Windows configuration. CodeSonar is by default configured with a set of paths for common compiler tool chains. We recommend that you review the list and possible add any paths that you see in the output of the pipeline.

We recommend verifying the setup with a project that can be compiled quite quickly, e.g., a program that computes the Fibonacci sequence. That way, it is faster to verify the setup compared to compiling a large program, as well as tweaking the configuration of the project in CodeSonar, e.g., the variable SYSTEM_INCLUDE_PATHS, see the CodeSonar tree Using CodeSonar -> Building and Analyzing a CodeSonar Project -> Options, Preferences, and Configuration Files -> Contents: Compiler-Independent Configuration File Parameters.


Was this article helpful?
0 out of 0 found this helpful

Articles in this section

GrammaTech Resource Library
Welcome to GrammaTech's resource library. Here you will find useful information about software development in the IoT era, where devices must not only function with impeccable quality and safety but also remain resilient to cyber attacks.
Shift Left Academy
Shift Left Academy is an educational resource to help implement a security first approach. Shift Left focuses on finding and preventing defects and security vulnerabilities early in the software development process
Blog
Posts by topic including static analysis, software assurance, and binary analysis