GitHub has many features that help you improve and maintain the quality of your code. Some of these are included in all plans, such as dependency graph and Dependabot alerts. Other security features require a GitHub Advanced Security (GHAS) license to run on repositories apart from public repositories on GitHub.com. A GitHub Advanced Security provides the following additional features:

  1. Code scanning - Search for potential security vulnerabilities and coding errors in your code.

  2. Secret scanning - Detect secrets, for example keys and tokens, that have been checked into private repositories. Secret scanning alerts for users and secret scanning alerts for partners are available and free of charge for public repositories on GitHub.com. If push protection is enabled, also detects secrets when they are pushed to your repository.

  3. Dependency review - Show the full impact of changes to dependencies and see details of any vulnerable versions before you merge a pull request.

This labs will show you how to use these features to secure your Spring Boot application.

1. Dependabot

You can use Dependabot to alert you when your repository is using a software dependency with a known vulnerability. Enabling Dependabot for the repository requires a bit of configuration which is described at https://docs.github.com/en/code-security/getting-started/dependabot-quickstart-guide#enabling-dependabot-for-your-repository

Let’s configure Dependabot with the repository. Go to Settings > Code Security & analysis > Dependabot alerts and enable the feature.

dependabot 1

Enabling Dependabot on repository is not the end of the story. Not all dependencies are automatically detected for ecosystems like Maven. You should configure GitHub Actions to add your dependencies using the dependency submission API, so you can receive Dependabot alerts for known vulnerabilities.

Dependency submission API requires additional permission to your repository. You can add the permission by going to Settings > Actions > General and enable Workflow permissions as "Read and write permissions"

Then open the GitHub Actions workflow file and add a new job security as below to submit the dependencies to GitHub.

name: Java CI with Maven

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
#### Redacted ####
  security:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Submit Dependency Snapshot
        uses: advanced-security/maven-dependency-submission-action@v3
        with:
          ignore-maven-wrapper: true

If GitHub Actions workflow runs successfully, you should see the Dependabot alerts in the repository.

dependabot 2

Challenge 1 : Choose one of the alert, and fix the vulnerability by updating the dependency version.

2. Secret Scanning

You can configure how GitHub scans your repositories for leaked secrets and generates alerts. Secret scanning alerts for users are available for free on all public repositories. Organizations using GitHub Enterprise Cloud with a license for GitHub Advanced Security can also enable secret scanning alerts for users on their private and internal repositories.

Let’s configure Secret Scanning with the repository. Go to Settings > Code Security & analysis and enable Secret Scanning. Enable "Push Protection" as well which will prevent secrets from being pushed to the repository.

secret 1

Let’s test if Secret Scanning with Push Protection is working. Open the application.properties, add the following property and push it to the repository. This is the fake connection string for Azure Event Hub.

connection-string=Endpoint=sb://eh.servicebus.windows.net/;SharedAccessKeyName=sas;SharedAccessKey=ZIb/QY6xq4qonPVB7T2xLg2aeT3KbXmWq+AEhNtnVYc=;EntityPath=monitoring-test

You should see the following error message when you git push your source code.

$ git push -u origin main
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 12 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (6/6), 593 bytes | 593.00 KiB/s, done.
Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
remote: error GH009: Secrets detected! This push failed.
remote:
remote:             GITHUB PUSH PROTECTION
remote: ——————————————————————————————————————————————————————
remote:  Resolve the following secrets before pushing again.
remote:
remote:  (?) Learn how to resolve a blocked push
remote:  https://docs.github.com/code-security/secret-scanning/pushing-a-branch-blocked-by-push-protection
remote:
remote:
remote: —— Azure Event Hub Key Identifiable ——————————————————
remote:  locations:
remote:    - commit: a487dd42cf70a0dc2db923a23e1a1a4d62eac9f3
remote:      path: src/main/resources/application.properties:1
remote:

GitHub is working closely with partners like Azure, AWS, Atlassian, Dropbox, Slack, Datadog, etc. to detect secrets for their services.

Challenge 2 : Add a fake secret of your choice to the repository and see if Secret Scanning detects it.

3. CodeQL

Code scanning is a feature that you use to analyze the code in a GitHub repository to find security vulnerabilities and coding errors. Any problems identified by the analysis are shown in GitHub.

You can use code scanning to find, triage, and prioritize fixes for existing problems in your code. Code scanning also prevents developers from introducing new problems. You can schedule scans for specific days and times, or trigger scans when a specific event occurs in the repository, such as a push.

If code scanning finds a potential vulnerability or error in your code, GitHub displays an alert in the repository. After you fix the code that triggered the alert, GitHub closes the alert.

Let’s configure Code Scanning with the repository. Go to Settings > Code Security & analysis > Code scanning and enable the feature. Java requires Advanced Setup to run CodeQL analysis.

code 1

Advanced Setup gives more detailed control over the CodeQL analysis, and this is the recommended option for Java as it allows you to specify the Java version. We need to set up JDK17 for CodeQL to run the analysis. Look at the below example.

code 2

Make sure the CodeQL Workflow runs successfully. To verify the CodeQL analysis, we need to introduce some vulnerabilities to the source code. Here is an example of a vulnerable code.

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.io.IOException;

@Controller
public class ExampleController
{
    @GetMapping(value = "/find")
    public void find(@RequestParam("filename") String filename) throws IOException {

        Runtime.getRuntime().exec("/usr/bin/find . -iname " + filename);
    }
}

This code is vulnerable to command injection. Let’s push this code to the repository and see if CodeQL detects the vulnerability. You should see the following alert in the repository.

code 3

Challenge 3 : Try to introduce a new vulnerability to the source code and see if CodeQL detects it.

Congratulations!! You have completed the second challenge!!