As cyber threats become increasingly sophisticated, the “Shift-left” approach of DevSecOps is no longer a luxury that is good to have. Security practices early in the Software Development Life Cycle (SDLC) are the most important in modern application development. As one of the most beloved source repositories in the world, GitHub has a great feature called Advanced Security, a powerful suite of security features designed to bolster the DevSecOps practices for enterprise developers using GitHub. The best part is that it’s completely free of charge for public repositories, providing developers with unprecedented access to cutting-edge security tools to protect their open-source projects.
In this article, we’ll delve into GitHub Advanced Security and explore how it empowers developers to embrace the “Shift-left” with their source code. I will be using the Spring Pet Clinic sample app for the demo.
The sample code and workflows are at https://github.com/eggboy/spring-petclinic
These days, developers can’t avoid using OSS when it comes to developing Enterprise applications so that developers should ensure what they consume is safe and secure to be used in the production environment. One of the great features of GitHub Advanced Security is “Dependabot,” which effectively addresses this concern. By scanning the software dependencies in your repository, Dependabot alerts developers about any known vulnerabilities present in the used dependencies.
Let’s configure Dependabot with the repository. Go to Settings > Code Security & analysis > Dependabot alerts and enable the feature.
Setting up Dependabot requires another step in the GitHub Action: uploading the dependency graph using Dependency submission API. This step ensures more accurate identification of dependencies, including transitive ones. GitHub offers two distinct actions, one for Maven and another for Gradle, making it seamless and convenient for developers using each tool. At the time of writing, the Dependency submission API is in public preview and supports only Golang, Maven, Gradle, Scala, and Mill. Remember, IT DOES NOT MEAN Depandabot doesn’t support other languages.
name: Java CI with Maven
branches: [ main ]
branches: [ main ]
- uses: actions/checkout@v3
- name: Set up JDK 17
- name: Submit Dependency Snapshot
Before we run this workflow, one last thing should be done regarding permission. Dependency submission API requires additional permission to your repository. You can add the permission by going to Settings > Actions > General and enabling Workflow permissions as “Read and write permissions.”
After workflow runs, Dependabot shows alerts in the Security tab. Dependabot creates two alerts for our sample Petclinic demo.
Dependabot suggests upgrading the H2 dependency version to 2.2.220, so we will fix it in the
<!-- Omitted -->
<!-- Databases - Uses H2 by default -->
<!-- Omitted -->
After the fix, the H2 alert disappeared, as what we would expect to happen exactly.
Code Scanning with CodeQL
CodeQL originally came from Semmle, which was acquired by GitHub in 2019. It’s an Advanced code analysis engine that allows developers to find vulnerabilities using a community-driven query set powered by a world-class security team. Code Query Language treats code as data in the graph database, then uses a query to find the patterns and vulnerabilities. Let’s look at one of the CodeQL examples that could help you understand how query language works. Here is an example of CodeQL that detects the wrong declaration of serialVersionUID in the Serializable classes. Basically, SerialVersionUID must be declared as a private static final long in Java.
from Field f
not f.isFinal() or
not f.isStatic() or
f.getDeclaringType().getAStrictAncestor() instanceof TypeSerializable
select f, "'serialVersionUID' should be final, static, and of type long."
Let’s enable CodeQL on the repository. Go to Settings > Code Security & analysis > Code scanning, and Set up as ‘
CodeQL requires the ‘Advanced’ for compiled languages like Java, as it relies on analyzing compiled code (bytecode) instead of working solely with the source code. When CodeQL runs, it analyzes the code, builds the database, and executes queries against it. The provided template has
autobuild action which builds the projects using Maven or Gradle. This template needs some changes if your project has a complicated build process. With our sample, we need a single change to make it use JDK 17, instead of the default version of JDK 11.
To see how CodeQL works, we need to introduce some vulnerable code, as Petclinic by default has none. I will use the code snippet below and test the CodeQL.
Once the CodeQL workflow finishes, Go to the Security tab will show one new issue as below.
As we have seen from the test, CodeQL workflows allow you to find vulnerabilities before they are merged into the code base and integrate the results directly into the developer workflow. One thing to note is that code scanning is not limited to just CodeQL, developers can also use third-party SAST tools that support SARIF format.
There is an interesting article regarding how fast hackers can find the leaked credential on the GitHub repository and abuse it — “It takes hackers 1 minute to find and abuse credentials exposed on GitHub” I do have my own experiences where I accidentally committed AWS IAM on GitHub that cost me $6000 in a short span of 2days in 2015. GitHub Advanced Security provides a protection that can quickly detect the secrets in the source code and reject the commit.
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.
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.
Push protection should be able to detect the secrets, and block the commits.
$ 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: GITHUB PUSH PROTECTION
remote: Resolve the following secrets before pushing again.
remote: (?) Learn how to resolve a blocked push
remote: —— Azure Event Hub Key Identifiable ——————————————————
remote: - commit: a487dd42cf70a0dc2db923a23e1a1a4d62eac9f3
remote: path: src/main/resources/application.properties:1
Secret scanning can detect secrets not only in the code but also anywhere in the project.
What I personally love the most about GitHub Advanced Security is having these security features tightly integrated with the source code repository, giving developers the experience of achieving “Shift left” seamlessly. In case you’re using Azure DevOps, GH Advanced security is coming to Azure DevOps as well, and I will cover it in a separate post.