Skip to content

Commit

Permalink
Provider Vulnerability Scanning (#90)
Browse files Browse the repository at this point in the history
* add provider and provider version to opa call

* added provider vulnerability detection

* documentation

* add latest ghes vulnerability

* proper dates

* renamed both vuln rules for better clarity

* renamed build platform

* to support older versions of gitlab if we get a 404 for the metadata api we use the deprecated version endpoint
  • Loading branch information
SUSTAPLE117 authored May 24, 2024
1 parent 36d3c7f commit 7401277
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 22 deletions.
6 changes: 3 additions & 3 deletions analyze/analyze.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func (a *Analyzer) AnalyzeOrg(ctx context.Context, org string, numberOfGoroutine
return err
}
pkgsupplyClient := pkgsupply.NewStaticClient()
inventory := scanner.NewInventory(opaClient, pkgsupplyClient)
inventory := scanner.NewInventory(opaClient, pkgsupplyClient, provider, providerVersion)

log.Debug().Msgf("Starting repository analysis for organization: %s on %s", org, provider)
bar := progressbar.NewOptions(
Expand Down Expand Up @@ -192,7 +192,7 @@ func (a *Analyzer) AnalyzeRepo(ctx context.Context, repoString string) error {
}
pkgsupplyClient := pkgsupply.NewStaticClient()

inventory := scanner.NewInventory(opaClient, pkgsupplyClient)
inventory := scanner.NewInventory(opaClient, pkgsupplyClient, provider, providerVersion)

log.Debug().Msgf("Starting repository analysis for: %s/%s on %s", org, repoName, provider)
bar := progressbar.NewOptions(
Expand Down Expand Up @@ -247,7 +247,7 @@ func (a *Analyzer) AnalyzeLocalRepo(ctx context.Context, repoPath string) error
}
pkgsupplyClient := pkgsupply.NewStaticClient()

inventory := scanner.NewInventory(opaClient, pkgsupplyClient)
inventory := scanner.NewInventory(opaClient, pkgsupplyClient, provider, providerVersion)

log.Debug().Msgf("Starting repository analysis for: %s/%s on %s", org, repoName, provider)
bar := progressbar.NewOptions(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
---
title: "CI Component with a Known Vulnerability used"
slug: known_vulnerability
url: /rules/known_vulnerability/
rule: known_vulnerability
title: "Build Component with a Known Vulnerability used"
slug: known_vulnerability_in_build_component
url: /rules/known_vulnerability_in_build_component/
rule: known_vulnerability_in_build_component
severity: warning
---

Expand All @@ -14,7 +14,7 @@ A CI component was found to be vulnerable to a publicly known security vulnerabi

GitHub Actions workflows using third-party GitHub Actions with known vulnerabilities could compromise the security of the workflow and the repository.

## Remmediation
## Remediation

Upgrade the affected component to a non-vulnerable version or remove the component from the workflow.

Expand Down
19 changes: 19 additions & 0 deletions docs/content/en/rules/known_vulnerability_in_build_platform.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: "Build Platform with a Known Vulnerability used"
slug: known_vulnerability_in_build_platform
url: /rules/known_vulnerability_in_build_platform/
rule: known_vulnerability_in_build_platform
severity: warning
---

## Description

A Build/SCM Provider was found to be vulnerable to a publicly known security vulnerability from the [Open Source Vulnerability Database (OSV)](https://osv.dev/)

## Remediation

Upgrade the self-hosted provider to a non-vulnerable version.

## See Also
- [Upgrade Gitlab](https://docs.gitlab.com/ee/update/)
- [Upgrade Github Enterprise Server](https://docs.github.com/en/enterprise-server@3.13/admin/overview/about-upgrades-to-new-releases)
32 changes: 32 additions & 0 deletions opa/rego/external/build_platform.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package external.build_platform

advisories = {
"gitlab": {"CVE-2024-2651": {
"osv_id": "CVE-2024-2651",
"published": "2024-05-14T00:00:00Z",
"aliases": [],
"summary": "It was possible for an attacker to cause a denial of service using maliciously crafted markdown content.",
"severity": [{
"type": "CVSS_V3",
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
}],
"cwe_ids": ["CWE-400"],
"vulnerable_versions": [],
"vulnerable_version_ranges": [">=0,<16.9.7"],
"vulnerable_commit_shas": [],
}},
"github": {"CVE-2024-4985": {
"osv_id": "CVE-2024-4985",
"published": "2024-05-20T00:00:00Z",
"aliases": [],
"summary": "It was possible for an attacker to cause a denial of service using maliciously crafted markdown content.",
"severity": [{
"type": "CVSS_V4",
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H/R:U/V:C/RE:M/U:Red",
}],
"cwe_ids": ["CWE-303"],
"vulnerable_versions": [],
"vulnerable_version_ranges": ["<3.9.15","<3.10.12","<3.11.10","<3.12.4"],
"vulnerable_commit_shas": [],
}},
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# METADATA
# title: CI Component with a Known Vulnerability used
# title: Build Component with a Known Vulnerability used
# description: |-
# The workflow or action depends on a GitHub Action with known vulnerabilities.
# related_resources:
# - ref: https://osv.dev/
# description: Source Advisory Database
# custom:
# level: warning
package rules.known_vulnerability
package rules.known_vulnerability_in_build_component

import data.external.osv.advisories
import data.poutine
Expand Down
32 changes: 32 additions & 0 deletions opa/rego/rules/known_vulnerability_in_build_platform.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# METADATA
# title: Build Platform with a Known Vulnerability used
# description: |-
# The build or SCM provider used has a known vulnerability.
# related_resources:
# - ref: https://osv.dev/
# description: Source Advisory Database
# custom:
# level: warning
package rules.known_vulnerability_in_build_platform

import data.external.build_platform.advisories
import data.poutine
import rego.v1

rule := poutine.rule(rego.metadata.chain())

provider_advisory(provider, provider_version) = advisory if {
version := provider_version
advisory := advisories[provider][osv_id]

regex.match("^[0-9]+(\\.[0-9]+)*?$", version)

semver.constraint_check(advisory.vulnerable_version_ranges[_], version)
}

results contains poutine.finding(rule, input.provider, {
"osv_id": advisory.osv_id,
"details": sprintf("Provider: %s", [input.provider]),
}) if {
advisory := provider_advisory(input.provider, input.version)
}
23 changes: 21 additions & 2 deletions providers/gitlab/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"net/http"
"strings"

"github.com/boostsecurityio/poutine/analyze"
Expand Down Expand Up @@ -85,12 +86,30 @@ func (gl GitLabRepo) GetProviderName() string {
}

func (s *ScmClient) GetProviderVersion(ctx context.Context) (string, error) {
met, _, err := s.client.client.Metadata.GetMetadata()

met, res, err := s.client.client.Metadata.GetMetadata()
if err != nil {
if res != nil && res.StatusCode == http.StatusNotFound {
version, _, err := s.client.client.Version.GetVersion()
if err != nil {
return "", fmt.Errorf("failed to get gitlab version: %w", err)
}
versionString := removeGitlabEditionFromVersion(version.Version)
return versionString, nil
}
return "", fmt.Errorf("failed to get gitlab metadata: %w", err)
}

return met.Version, nil
versionString := removeGitlabEditionFromVersion(met.Version)
return versionString, nil
}

func removeGitlabEditionFromVersion(version string) string {
index := strings.Index(version, "-")
if index != -1 {
version = version[:index]
}
return version
}

func (gl GitLabRepo) GetRepoIdentifier() string {
Expand Down
10 changes: 8 additions & 2 deletions scanner/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@ type ReputationClient interface {
}

type Inventory struct {
Packages []*models.PackageInsights
Packages []*models.PackageInsights
providerVersion string
provider string

opa *opa.Opa
pkgsupplyClient ReputationClient
}

func NewInventory(opa *opa.Opa, pkgsupplyClient ReputationClient) *Inventory {
func NewInventory(opa *opa.Opa, pkgsupplyClient ReputationClient, provider string, providerVersion string) *Inventory {
return &Inventory{
Packages: make([]*models.PackageInsights, 0),
opa: opa,
pkgsupplyClient: pkgsupplyClient,
provider: provider,
providerVersion: providerVersion,
}
}

Expand Down Expand Up @@ -71,6 +75,8 @@ func (i *Inventory) Findings(ctx context.Context) (*opa.FindingsResult, error) {
map[string]interface{}{
"packages": i.Packages,
"reputation": reputation,
"provider": i.provider,
"version": i.providerVersion,
},
results,
)
Expand Down
25 changes: 17 additions & 8 deletions scanner/inventory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

func TestPurls(t *testing.T) {
o, _ := opa.NewOpa()
i := NewInventory(o, nil)
i := NewInventory(o, nil, "", "")
pkg := &models.PackageInsights{
Purl: "pkg:github/org/owner",
}
Expand Down Expand Up @@ -52,7 +52,7 @@ func TestPurls(t *testing.T) {

func TestFindings(t *testing.T) {
o, _ := opa.NewOpa()
i := NewInventory(o, nil)
i := NewInventory(o, nil, "gitlab", "16.9.6")
purl := "pkg:github/org/owner"
pkg := &models.PackageInsights{
Purl: purl,
Expand All @@ -73,8 +73,9 @@ func TestFindings(t *testing.T) {
assert.ElementsMatch(t, rule_ids, []string{
"default_permissions_on_risky_events",
"if_always_true",
"known_vulnerability",
"known_vulnerability_in_build_component",
"pr_runs_on_self_hosted",
"known_vulnerability_in_build_platform",
"unpinnable_action",
"untrusted_checkout_exec",
"injection",
Expand Down Expand Up @@ -125,7 +126,7 @@ func TestFindings(t *testing.T) {
},
},
{
RuleId: "known_vulnerability",
RuleId: "known_vulnerability_in_build_component",
Purl: purl,
Meta: opa.FindingMeta{
Path: "composite/action.yml",
Expand All @@ -136,7 +137,7 @@ func TestFindings(t *testing.T) {
},
},
{
RuleId: "known_vulnerability",
RuleId: "known_vulnerability_in_build_component",
Purl: purl,
Meta: opa.FindingMeta{
Path: ".github/workflows/valid.yml",
Expand All @@ -148,7 +149,7 @@ func TestFindings(t *testing.T) {
},
},
{
RuleId: "known_vulnerability",
RuleId: "known_vulnerability_in_build_component",
Purl: purl,
Meta: opa.FindingMeta{
Path: ".github/workflows/valid.yml",
Expand Down Expand Up @@ -232,6 +233,14 @@ func TestFindings(t *testing.T) {
Details: "Used in 1 repo(s)",
},
},
{
RuleId: "known_vulnerability_in_build_platform",
Purl: "gitlab",
Meta: opa.FindingMeta{
OsvId: "CVE-2024-2651",
Details: "Provider: gitlab",
},
},
{
RuleId: "injection",
Purl: purl,
Expand Down Expand Up @@ -296,10 +305,10 @@ func TestFindings(t *testing.T) {

func TestSkipRule(t *testing.T) {
o, _ := opa.NewOpa()
i := NewInventory(o, nil)
i := NewInventory(o, nil, "", "")
ctx := context.TODO()
purl := "pkg:github/org/owner"
rule_id := "known_vulnerability"
rule_id := "known_vulnerability_in_build_component"
pkg := &models.PackageInsights{
Purl: purl,
}
Expand Down

0 comments on commit 7401277

Please sign in to comment.