Skip to content

Commit

Permalink
add cargo.lock support
Browse files Browse the repository at this point in the history
  • Loading branch information
luotianqi committed Apr 2, 2022
1 parent f3ebcb8 commit 5df0afb
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 4 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module opensca
go 1.16

require (
github.com/BurntSushi/toml v1.0.0
github.com/Masterminds/semver/v3 v3.1.1
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394
github.com/dsnet/compress v0.0.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU=
github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
Expand Down
60 changes: 60 additions & 0 deletions internal/analyzer/rust/analyzer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package rust

import (
"opensca/internal/enum/language"
"opensca/internal/filter"
"opensca/internal/srt"
)

type Analyzer struct{}

func New() Analyzer {
return Analyzer{}
}

/**
* @description: Get language of Analyzer
* @return {language.Type} language type
*/
func (a Analyzer) GetLanguage() language.Type {
return language.Rust
}

/**
* @description: Check if it is a parsable file
* @param {string} filename file name
* @return {bool} is a parseable file returns true
*/
func (a Analyzer) CheckFile(filename string) bool {
return filter.RustCargoLock(filename)
}

/**
* @description: filters the files that the current parser needs to parse
* @param {*srt.DirTree} dirRoot directory tree node
* @param {*srt.DepTree} depRoot Dependency tree node
* @return {[]*srt.FileData} List of files to parse
*/
func (a Analyzer) FilterFile(dirRoot *srt.DirTree, depRoot *srt.DepTree) []*srt.FileData {
files := []*srt.FileData{}
for _, f := range dirRoot.Files {
if a.CheckFile(f.Name) {
files = append(files, f)
}
}
return files
}

/**
* @description: Parse the file
* @param {*srt.DirTree} dirRoot directory tree node
* @param {*srt.DepTree} depRoot Dependency tree node
* @param {*srt.FileData} file data to parse
* @return {[]*srt.DepTree} parsed dependency list
*/
func (a Analyzer) ParseFile(dirRoot *srt.DirTree, depRoot *srt.DepTree, file *srt.FileData) []*srt.DepTree {
if filter.RustCargoLock(file.Name) {
return parseCargoLock(dirRoot, depRoot, file)
}
return []*srt.DepTree{}
}
93 changes: 93 additions & 0 deletions internal/analyzer/rust/cargo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package rust

import (
"opensca/internal/logs"
"opensca/internal/srt"
"sort"
"strings"

"github.com/BurntSushi/toml"
)

type cargoPkg struct {
Name string `toml:"name"`
Version string `toml:"version"`
DepStr []string `toml:"dependencies"`
Dependencies []struct {
Name string
Version string
} `toml:"-"`
}

func parseCargoLock(dirRoot *srt.DirTree, depRoot *srt.DepTree, file *srt.FileData) []*srt.DepTree {
cargo := struct {
Pkgs []*cargoPkg `toml:"package"`
}{}
cdepMap := map[string]*cargoPkg{}
depMap := map[string]*srt.DepTree{}
directMap := map[string]*srt.DepTree{}
if err := toml.Unmarshal(file.Data, &cargo); err != nil {
logs.Warn(err)
}
for _, pkg := range cargo.Pkgs {
dep := srt.NewDepTree(nil)
dep.Name = pkg.Name
dep.Version = srt.NewVersion(pkg.Version)
pkg.Dependencies = make([]struct {
Name string
Version string
}, len(pkg.DepStr))
for i, str := range pkg.DepStr {
name, version := str, ""
index := strings.Index(str, " ")
if index > -1 {
name, version = str[:index], str[index+1:]
}
pkg.Dependencies[i] = struct {
Name string
Version string
}{Name: name, Version: version}
}
depMap[dep.Name] = dep
directMap[dep.Name] = dep
cdepMap[dep.Name] = pkg
}
// 找出未被依赖的作为直接依赖
for _, pkg := range cargo.Pkgs {
for _, d := range pkg.Dependencies {
delete(directMap, d.Name)
}
}
directDeps := []*srt.DepTree{}
for _, v := range directMap {
directDeps = append(directDeps, v)
}
sort.Slice(directDeps, func(i, j int) bool {
return directDeps[i].Name < directDeps[j].Name
})
for _, d := range directDeps {
d.Parent = depRoot
depRoot.Children = append(depRoot.Children, d)
}
// 从顶层开始构建
q := make([]*srt.DepTree, len(directDeps))
copy(q, directDeps)
exist := map[string]struct{}{}
for len(q) > 0 {
n := q[0]
exist[n.Name] = struct{}{}
if cdep, ok := cdepMap[n.Name]; ok {
for _, d := range cdep.Dependencies {
if _, ok := exist[d.Name]; !ok {
exist[d.Name] = struct{}{}
if sub, ok := depMap[d.Name]; ok {
sub.Parent = n
n.Children = append(n.Children, sub)
}
}
}
}
q = append(q[1:], n.Children...)
}
return directDeps
}
2 changes: 2 additions & 0 deletions internal/engine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"opensca/internal/analyzer/javascript"
"opensca/internal/analyzer/php"
"opensca/internal/analyzer/ruby"
"opensca/internal/analyzer/rust"
"opensca/internal/args"
"opensca/internal/enum/language"
"opensca/internal/filter"
Expand Down Expand Up @@ -44,6 +45,7 @@ func NewEngine() Engine {
php.New(),
ruby.New(),
golang.New(),
rust.New(),
},
}
}
Expand Down
8 changes: 7 additions & 1 deletion internal/enum/language/language.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
Php
Ruby
Golang
Rust
)

/**
Expand All @@ -39,6 +40,8 @@ func (l Type) String() string {
return "Ruby"
case Golang:
return "Golang"
case Rust:
return "Rust"
default:
return "None"
}
Expand All @@ -62,6 +65,8 @@ func (l Type) Vuln() string {
return "ruby"
case Golang:
return "golang"
case Rust:
return "rust"
default:
return ""
}
Expand All @@ -77,7 +82,8 @@ func init() {
lm[JavaScript] = []string{"js", "node", "nodejs", "javascript", "npm", "vue", "react"}
lm[Php] = []string{"php", "composer"}
lm[Ruby] = []string{"ruby"}
lm[Golang] = []string{"golang", "go"}
lm[Golang] = []string{"golang", "go", "gomod"}
lm[Rust] = []string{"rust", "cargo"}
for t, ls := range lm {
for _, l := range ls {
lanMap[l] = t
Expand Down
5 changes: 5 additions & 0 deletions internal/filter/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,8 @@ var (
GoMod = filterFunc(strings.HasSuffix, "go.mod")
GoSum = filterFunc(strings.HasSuffix, "go.sum")
)

// rust
var (
RustCargoLock = filterFunc(strings.HasSuffix, "Cargo.lock")
)
7 changes: 4 additions & 3 deletions internal/vuln/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ func loadVulnDB() {
}
// 将漏洞信息存到vulnDB中
name := strings.ToLower(info.Product)
if _, ok := vulnDB[info.Language]; !ok {
vulnDB[info.Language] = map[string][]vulnInfo{}
language := strings.ToLower(info.Language)
if _, ok := vulnDB[language]; !ok {
vulnDB[language] = map[string][]vulnInfo{}
}
vulns := vulnDB[info.Language]
vulns := vulnDB[language]
vulns[name] = append(vulns[name], info)
}
}
Expand Down

0 comments on commit 5df0afb

Please sign in to comment.