github.com/khulnasoft-lab/tunnel-db@v0.0.0-20231117205118-74e1113bd007/pkg/vulnsrc/ghsa/ghsa.go (about)

     1  package ghsa
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	"golang.org/x/xerrors"
    10  
    11  	"github.com/khulnasoft-lab/tunnel-db/pkg/types"
    12  	"github.com/khulnasoft-lab/tunnel-db/pkg/vulnsrc/osv"
    13  	"github.com/khulnasoft-lab/tunnel-db/pkg/vulnsrc/vulnerability"
    14  )
    15  
    16  const (
    17  	sourceID       = vulnerability.GHSA
    18  	platformFormat = "GitHub Security Advisory %s"
    19  	urlFormat      = "https://github.com/advisories?query=type%%3Areviewed+ecosystem%%3A%s"
    20  )
    21  
    22  var (
    23  	ghsaDir = filepath.Join("ghsa", "advisories", "github-reviewed")
    24  
    25  	// Mapping between Tunnel ecosystem and GHSA ecosystem
    26  	ecosystems = map[types.Ecosystem]string{
    27  		vulnerability.Composer:  "Composer",
    28  		vulnerability.Go:        "Go",
    29  		vulnerability.Maven:     "Maven",
    30  		vulnerability.Npm:       "npm",
    31  		vulnerability.NuGet:     "NuGet",
    32  		vulnerability.Pip:       "pip",
    33  		vulnerability.RubyGems:  "RubyGems",
    34  		vulnerability.Cargo:     "Rust", // different name
    35  		vulnerability.Erlang:    "Erlang",
    36  		vulnerability.Pub:       "Pub",
    37  		vulnerability.Swift:     "Swift",
    38  		vulnerability.Cocoapods: "Swift", // Use Swift advisories for CocoaPods
    39  	}
    40  )
    41  
    42  type DatabaseSpecific struct {
    43  	Severity string `json:"severity"`
    44  }
    45  
    46  type GHSA struct{}
    47  
    48  func NewVulnSrc() GHSA {
    49  	return GHSA{}
    50  }
    51  
    52  func (GHSA) Name() types.SourceID {
    53  	return vulnerability.GHSA
    54  }
    55  
    56  func (GHSA) Update(root string) error {
    57  	dataSources := map[types.Ecosystem]types.DataSource{}
    58  	for ecosystem, ghsaEcosystem := range ecosystems {
    59  		src := types.DataSource{
    60  			ID:   sourceID,
    61  			Name: fmt.Sprintf(platformFormat, ghsaEcosystem),
    62  			URL:  fmt.Sprintf(urlFormat, strings.ToLower(ghsaEcosystem)),
    63  		}
    64  		dataSources[ecosystem] = src
    65  	}
    66  
    67  	t, err := newTransformer(root)
    68  	if err != nil {
    69  		return xerrors.Errorf("transformer error: %w", err)
    70  	}
    71  
    72  	return osv.New(ghsaDir, sourceID, dataSources, t).Update(root)
    73  }
    74  
    75  type transformer struct {
    76  	// cocoaPodsSpecs is a map of Swift git URLs to CocoaPods package names.
    77  	cocoaPodsSpecs map[string][]string
    78  }
    79  
    80  func newTransformer(root string) (*transformer, error) {
    81  	cocoaPodsSpecs, err := walkCocoaPodsSpecs(root)
    82  	if err != nil {
    83  		return nil, xerrors.Errorf("CocoaPods spec error: %w", err)
    84  	}
    85  	return &transformer{
    86  		cocoaPodsSpecs: cocoaPodsSpecs,
    87  	}, nil
    88  }
    89  
    90  func (t *transformer) TransformAdvisories(advisories []osv.Advisory, entry osv.Entry) ([]osv.Advisory, error) {
    91  	var specific DatabaseSpecific
    92  	if err := json.Unmarshal(entry.DatabaseSpecific, &specific); err != nil {
    93  		return nil, xerrors.Errorf("JSON decode error: %w", err)
    94  	}
    95  
    96  	severity := convertSeverity(specific.Severity)
    97  	for i, adv := range advisories {
    98  		advisories[i].Severity = severity
    99  
   100  		// Replace a git URL with a CocoaPods package name in a Swift vulnerability
   101  		// and store it as a CocoaPods vulnerability.
   102  		if adv.Ecosystem == vulnerability.Swift {
   103  			adv.Severity = severity
   104  			adv.Ecosystem = vulnerability.Cocoapods
   105  			for _, pkgName := range t.cocoaPodsSpecs[adv.PkgName] {
   106  				adv.PkgName = pkgName
   107  				advisories = append(advisories, adv)
   108  			}
   109  		}
   110  	}
   111  
   112  	return advisories, nil
   113  }
   114  
   115  func convertSeverity(severity string) types.Severity {
   116  	switch severity {
   117  	case "LOW":
   118  		return types.SeverityLow
   119  	case "MODERATE":
   120  		return types.SeverityMedium
   121  	case "HIGH":
   122  		return types.SeverityHigh
   123  	case "CRITICAL":
   124  		return types.SeverityCritical
   125  	default:
   126  		return types.SeverityUnknown
   127  	}
   128  }