mirror of
https://github.com/redhat-developer/odo.git
synced 2025-10-19 03:06:19 +03:00
Go: Bump github.com/securego/gosec/v2 from 2.15.0 to 2.17.0 (#7033)
* Go: Bump github.com/securego/gosec/v2 from 2.15.0 to 2.17.0 Bumps [github.com/securego/gosec/v2](https://github.com/securego/gosec) from 2.15.0 to 2.17.0. - [Release notes](https://github.com/securego/gosec/releases) - [Changelog](https://github.com/securego/gosec/blob/master/.goreleaser.yml) - [Commits](https://github.com/securego/gosec/compare/v2.15.0...v2.17.0) --- updated-dependencies: - dependency-name: github.com/securego/gosec/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Go: Bump github.com/securego/gosec/v2 from 2.15.0 to 2.17.0 Bumps [github.com/securego/gosec/v2](https://github.com/securego/gosec) from 2.15.0 to 2.17.0. - [Release notes](https://github.com/securego/gosec/releases) - [Changelog](https://github.com/securego/gosec/blob/master/.goreleaser.yml) - [Commits](https://github.com/securego/gosec/compare/v2.15.0...v2.17.0) --- updated-dependencies: - dependency-name: github.com/securego/gosec/v2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> * Ignore gosec error --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Philippe Martin <phmartin@redhat.com>
This commit is contained in:
5
vendor/github.com/ccojocar/zxcvbn-go/.gitignore
generated
vendored
Normal file
5
vendor/github.com/ccojocar/zxcvbn-go/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
zxcvbn
|
||||
debug.test
|
||||
|
||||
# SBOMs generated during CI
|
||||
/bom.json
|
||||
39
vendor/github.com/ccojocar/zxcvbn-go/.golangci.yml
generated
vendored
Normal file
39
vendor/github.com/ccojocar/zxcvbn-go/.golangci.yml
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- dogsled
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errorlint
|
||||
- exportloopref
|
||||
- gci
|
||||
- ginkgolinter
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gosimple
|
||||
- govet
|
||||
- importas
|
||||
- ineffassign
|
||||
- megacheck
|
||||
- misspell
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- wastedassign
|
||||
|
||||
linters-settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/ccojocar)
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
27
vendor/github.com/ccojocar/zxcvbn-go/.goreleaser.yml
generated
vendored
Normal file
27
vendor/github.com/ccojocar/zxcvbn-go/.goreleaser.yml
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
project_name: zxcvbn-go
|
||||
|
||||
release:
|
||||
extra_files:
|
||||
- glob: ./bom.json
|
||||
github:
|
||||
owner: ccojocar
|
||||
name: zxcvbn-go
|
||||
|
||||
builds:
|
||||
- main: ./testapp/
|
||||
binary: zxcvbn-go
|
||||
goos:
|
||||
- darwin
|
||||
- linux
|
||||
- windows
|
||||
goarch:
|
||||
- amd64
|
||||
- arm64
|
||||
- s390x
|
||||
ldflags: -X main.Version={{.Version}} -X main.GitTag={{.Tag}} -X main.BuildDate={{.Date}}
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
|
||||
gomod:
|
||||
proxy: true
|
||||
61
vendor/github.com/ccojocar/zxcvbn-go/Makefile
generated
vendored
Normal file
61
vendor/github.com/ccojocar/zxcvbn-go/Makefile
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
GIT_TAG?= $(shell git describe --always --tags)
|
||||
BIN = zxcvbn-go
|
||||
FMT_CMD = $(gofmt -s -l -w $(find . -type f -name '*.go' -not -path './vendor/*') | tee /dev/stderr)
|
||||
IMAGE_REPO = ccojocar
|
||||
DATE_FMT=+%Y-%m-%d
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "$(DATE_FMT)" 2>/dev/null || date -u "$(DATE_FMT)")
|
||||
else
|
||||
BUILD_DATE ?= $(shell date "$(DATE_FMT)")
|
||||
endif
|
||||
BUILDFLAGS := "-w -s -X 'main.Version=$(GIT_TAG)' -X 'main.GitTag=$(GIT_TAG)' -X 'main.BuildDate=$(BUILD_DATE)'"
|
||||
CGO_ENABLED = 0
|
||||
GO := GO111MODULE=on go
|
||||
GO_NOMOD :=GO111MODULE=off go
|
||||
GOPATH ?= $(shell $(GO) env GOPATH)
|
||||
GOBIN ?= $(GOPATH)/bin
|
||||
GO_MINOR_VERSION = $(shell $(GO) version | cut -c 14- | cut -d' ' -f1 | cut -d'.' -f2)
|
||||
GOVULN_MIN_VERSION = 17
|
||||
GO_VERSION = 1.20
|
||||
|
||||
default:
|
||||
$(MAKE) test
|
||||
|
||||
install-govulncheck:
|
||||
@if [ $(GO_MINOR_VERSION) -gt $(GOVULN_MIN_VERSION) ]; then \
|
||||
go install golang.org/x/vuln/cmd/govulncheck@latest; \
|
||||
fi
|
||||
|
||||
test-all: fmt vet lint sec govulncheck test
|
||||
|
||||
test:
|
||||
go test -v ./...
|
||||
|
||||
fmt:
|
||||
@echo "FORMATTING"
|
||||
@FORMATTED=`$(GO) fmt ./...`
|
||||
@([ ! -z "$(FORMATTED)" ] && printf "Fixed unformatted files:\n$(FORMATTED)") || true
|
||||
|
||||
vet:
|
||||
@echo "VETTING"
|
||||
$(GO) vet ./...
|
||||
|
||||
lint:
|
||||
@echo "LINTING: golangci-lint"
|
||||
golangci-lint run
|
||||
|
||||
sec:
|
||||
@echo "SECURITY SCANNING"
|
||||
gosec ./...
|
||||
|
||||
govulncheck: install-govulncheck
|
||||
@echo "CHECKING VULNERABILITIES"
|
||||
@if [ $(GO_MINOR_VERSION) -gt $(GOVULN_MIN_VERSION) ]; then \
|
||||
govulncheck ./...; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -rf build vendor dist coverage.txt
|
||||
rm -f release image $(BIN)
|
||||
|
||||
.PHONY: test test-all fmt vet govulncheck clean
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/data"
|
||||
"github.com/ccojocar/zxcvbn-go/data"
|
||||
)
|
||||
|
||||
// Graph holds information about different graphs
|
||||
@@ -25,7 +25,7 @@ func init() {
|
||||
GraphMap["l33t"] = BuildLeet()
|
||||
}
|
||||
|
||||
//BuildQwerty builds the Qwerty Graph
|
||||
// BuildQwerty builds the Qwerty Graph
|
||||
func BuildQwerty() Graph {
|
||||
data, err := data.Asset("data/Qwerty.json")
|
||||
if err != nil {
|
||||
@@ -34,7 +34,7 @@ func BuildQwerty() Graph {
|
||||
return getAdjancencyGraphFromFile(data, "qwerty")
|
||||
}
|
||||
|
||||
//BuildDvorak builds the Dvorak Graph
|
||||
// BuildDvorak builds the Dvorak Graph
|
||||
func BuildDvorak() Graph {
|
||||
data, err := data.Asset("data/Dvorak.json")
|
||||
if err != nil {
|
||||
@@ -43,7 +43,7 @@ func BuildDvorak() Graph {
|
||||
return getAdjancencyGraphFromFile(data, "dvorak")
|
||||
}
|
||||
|
||||
//BuildKeypad builds the Keypad Graph
|
||||
// BuildKeypad builds the Keypad Graph
|
||||
func BuildKeypad() Graph {
|
||||
data, err := data.Asset("data/Keypad.json")
|
||||
if err != nil {
|
||||
@@ -52,7 +52,7 @@ func BuildKeypad() Graph {
|
||||
return getAdjancencyGraphFromFile(data, "keypad")
|
||||
}
|
||||
|
||||
//BuildMacKeypad builds the Mac Keypad Graph
|
||||
// BuildMacKeypad builds the Mac Keypad Graph
|
||||
func BuildMacKeypad() Graph {
|
||||
data, err := data.Asset("data/MacKeypad.json")
|
||||
if err != nil {
|
||||
@@ -61,7 +61,7 @@ func BuildMacKeypad() Graph {
|
||||
return getAdjancencyGraphFromFile(data, "mac_keypad")
|
||||
}
|
||||
|
||||
//BuildLeet builds the L33T Graph
|
||||
// BuildLeet builds the L33T Graph
|
||||
func BuildLeet() Graph {
|
||||
data, err := data.Asset("data/L33t.json")
|
||||
if err != nil {
|
||||
@@ -71,7 +71,6 @@ func BuildLeet() Graph {
|
||||
}
|
||||
|
||||
func getAdjancencyGraphFromFile(data []byte, name string) Graph {
|
||||
|
||||
var graph Graph
|
||||
err := json.Unmarshal(data, &graph)
|
||||
if err != nil {
|
||||
@@ -82,9 +81,9 @@ func getAdjancencyGraphFromFile(data []byte, name string) Graph {
|
||||
}
|
||||
|
||||
// CalculateAvgDegree calclates the average degree between nodes in the graph
|
||||
//on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1.
|
||||
//this calculates the average over all keys.
|
||||
//TODO double check that i ported this correctly scoring.coffee ln 5
|
||||
// on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1.
|
||||
// this calculates the average over all keys.
|
||||
// TODO double check that i ported this correctly scoring.coffee ln 5
|
||||
func (adjGrp Graph) CalculateAvgDegree() float64 {
|
||||
if adjGrp.averageDegree != float64(0) {
|
||||
return adjGrp.averageDegree
|
||||
@@ -92,14 +91,12 @@ func (adjGrp Graph) CalculateAvgDegree() float64 {
|
||||
var avg float64
|
||||
var count float64
|
||||
for _, value := range adjGrp.Graph {
|
||||
|
||||
for _, char := range value {
|
||||
if len(char) != 0 || char != " " {
|
||||
avg += float64(len(char))
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
adjGrp.averageDegree = avg / count
|
||||
@@ -33,7 +33,7 @@ func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
_, err = io.Copy(&buf, gz) // #nosec
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
@@ -345,11 +345,13 @@ var _bindata = map[string]func() (*asset, error){
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
//
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
//
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
@@ -1,12 +1,13 @@
|
||||
package entropy
|
||||
|
||||
import (
|
||||
"github.com/nbutton23/zxcvbn-go/adjacency"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/nbutton23/zxcvbn-go/utils/math"
|
||||
"math"
|
||||
"regexp"
|
||||
"unicode"
|
||||
|
||||
"github.com/ccojocar/zxcvbn-go/adjacency"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
zxcvbnmath "github.com/ccojocar/zxcvbn-go/utils/math"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -27,7 +28,7 @@ var (
|
||||
func DictionaryEntropy(match match.Match, rank float64) float64 {
|
||||
baseEntropy := math.Log2(rank)
|
||||
upperCaseEntropy := extraUpperCaseEntropy(match)
|
||||
//TODO: L33t
|
||||
// TODO: L33t
|
||||
return baseEntropy + upperCaseEntropy
|
||||
}
|
||||
|
||||
@@ -46,18 +47,18 @@ func extraUpperCaseEntropy(match match.Match) float64 {
|
||||
return float64(0)
|
||||
}
|
||||
|
||||
//a capitalized word is the most common capitalization scheme,
|
||||
//so it only doubles the search space (uncapitalized + capitalized): 1 extra bit of entropy.
|
||||
//allcaps and end-capitalized are common enough too, underestimate as 1 extra bit to be safe.
|
||||
// a capitalized word is the most common capitalization scheme,
|
||||
// so it only doubles the search space (uncapitalized + capitalized): 1 extra bit of entropy.
|
||||
// allcaps and end-capitalized are common enough too, underestimate as 1 extra bit to be safe.
|
||||
|
||||
for _, matcher := range []*regexp.Regexp{startUpperRx, endUpperRx, allUpperRx} {
|
||||
if matcher.MatchString(word) {
|
||||
return float64(1)
|
||||
}
|
||||
}
|
||||
//Otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters with U uppercase letters or
|
||||
//less. Or, if there's more uppercase than lower (for e.g. PASSwORD), the number of ways to lowercase U+L letters
|
||||
//with L lowercase letters or less.
|
||||
// Otherwise calculate the number of ways to capitalize U+L uppercase+lowercase letters with U uppercase letters or
|
||||
// less. Or, if there's more uppercase than lower (for e.g. PASSwORD), the number of ways to lowercase U+L letters
|
||||
// with L lowercase letters or less.
|
||||
|
||||
countUpper, countLower := float64(0), float64(0)
|
||||
for _, char := range word {
|
||||
@@ -71,21 +72,21 @@ func extraUpperCaseEntropy(match match.Match) float64 {
|
||||
var possibililities float64
|
||||
|
||||
for i := float64(0); i <= math.Min(countUpper, countLower); i++ {
|
||||
possibililities += float64(zxcvbnmath.NChoseK(totalLenght, i))
|
||||
possibililities += zxcvbnmath.NChoseK(totalLenght, i)
|
||||
}
|
||||
|
||||
if possibililities < 1 {
|
||||
return float64(1)
|
||||
}
|
||||
|
||||
return float64(math.Log2(possibililities))
|
||||
return (math.Log2(possibililities))
|
||||
}
|
||||
|
||||
// SpatialEntropy calculates the entropy for spatial matches
|
||||
func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
|
||||
var s, d float64
|
||||
if match.DictionaryName == "qwerty" || match.DictionaryName == "dvorak" {
|
||||
//todo: verify qwerty and dvorak have the same length and degree
|
||||
// todo: verify qwerty and dvorak have the same length and degree
|
||||
s = float64(len(adjacency.BuildQwerty().Graph))
|
||||
d = adjacency.BuildQwerty().CalculateAvgDegree()
|
||||
} else {
|
||||
@@ -97,8 +98,8 @@ func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
|
||||
|
||||
length := float64(len(match.Token))
|
||||
|
||||
//TODO: Should this be <= or just < ?
|
||||
//Estimate the number of possible patterns w/ length L or less with t turns or less
|
||||
// TODO: Should this be <= or just < ?
|
||||
// Estimate the number of possible patterns w/ length L or less with t turns or less
|
||||
for i := float64(2); i <= length+1; i++ {
|
||||
possibleTurns := math.Min(float64(turns), i-1)
|
||||
for j := float64(1); j <= possibleTurns+1; j++ {
|
||||
@@ -108,8 +109,8 @@ func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
|
||||
}
|
||||
|
||||
entropy := math.Log2(possibilities)
|
||||
//add extra entropu for shifted keys. ( % instead of 5 A instead of a)
|
||||
//Math is similar to extra entropy for uppercase letters in dictionary matches.
|
||||
// add extra entropu for shifted keys. ( % instead of 5 A instead of a)
|
||||
// Math is similar to extra entropy for uppercase letters in dictionary matches.
|
||||
|
||||
if S := float64(shiftCount); S > float64(0) {
|
||||
possibilities = float64(0)
|
||||
@@ -134,7 +135,7 @@ func RepeatEntropy(match match.Match) float64 {
|
||||
}
|
||||
|
||||
// CalcBruteForceCardinality calculates the brute force cardinality
|
||||
//TODO: Validate against python
|
||||
// TODO: Validate against python
|
||||
func CalcBruteForceCardinality(password string) float64 {
|
||||
lower, upper, digits, symbols := float64(0), float64(0), float64(0), float64(0)
|
||||
|
||||
@@ -157,12 +158,12 @@ func CalcBruteForceCardinality(password string) float64 {
|
||||
// SequenceEntropy calculates the entropy for sequences such as 4567 or cdef
|
||||
func SequenceEntropy(match match.Match, dictionaryLength int, ascending bool) float64 {
|
||||
firstChar := match.Token[0]
|
||||
baseEntropy := float64(0)
|
||||
var baseEntropy float64
|
||||
if string(firstChar) == "a" || string(firstChar) == "1" {
|
||||
baseEntropy = float64(0)
|
||||
} else {
|
||||
baseEntropy = math.Log2(float64(dictionaryLength))
|
||||
//TODO: should this be just the first or any char?
|
||||
// TODO: should this be just the first or any char?
|
||||
if unicode.IsUpper(rune(firstChar)) {
|
||||
baseEntropy++
|
||||
}
|
||||
@@ -183,7 +184,7 @@ func ExtraLeetEntropy(match match.Match, password string) float64 {
|
||||
if string(char) != string(match.Token[index]) {
|
||||
subsitutions++
|
||||
} else {
|
||||
//TODO: Make this only true for 1337 chars that are not subs?
|
||||
// TODO: Make this only true for 1337 chars that are not subs?
|
||||
unsub++
|
||||
}
|
||||
}
|
||||
@@ -210,7 +211,7 @@ func DateEntropy(dateMatch match.DateMatch) float64 {
|
||||
}
|
||||
|
||||
if dateMatch.Separator != "" {
|
||||
entropy += 2 //add two bits for separator selection [/,-,.,etc]
|
||||
entropy += 2 // add two bits for separator selection [/,-,.,etc]
|
||||
}
|
||||
return entropy
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/data"
|
||||
"github.com/ccojocar/zxcvbn-go/data"
|
||||
)
|
||||
|
||||
// List holds a frequency list
|
||||
@@ -28,8 +28,8 @@ func init() {
|
||||
Lists["Surname"] = getStringListFromAsset(surnameFilePath, "Surname")
|
||||
Lists["English"] = getStringListFromAsset(englishFilePath, "English")
|
||||
Lists["Passwords"] = getStringListFromAsset(passwordsFilePath, "Passwords")
|
||||
|
||||
}
|
||||
|
||||
func getAsset(name string) []byte {
|
||||
data, err := data.Asset(name)
|
||||
if err != nil {
|
||||
@@ -38,8 +38,8 @@ func getAsset(name string) []byte {
|
||||
|
||||
return data
|
||||
}
|
||||
func getStringListFromAsset(data []byte, name string) List {
|
||||
|
||||
func getStringListFromAsset(data []byte, name string) List {
|
||||
var tempList List
|
||||
err := json.Unmarshal(data, &tempList)
|
||||
if err != nil {
|
||||
@@ -1,14 +1,16 @@
|
||||
package match
|
||||
|
||||
//Matches is an alies for []Match used for sorting
|
||||
// Matches is an alies for []Match used for sorting
|
||||
type Matches []Match
|
||||
|
||||
func (s Matches) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s Matches) Swap(i, j int) {
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
func (s Matches) Less(i, j int) bool {
|
||||
if s[i].I < s[j].I {
|
||||
return true
|
||||
@@ -28,7 +30,7 @@ type Match struct {
|
||||
Entropy float64
|
||||
}
|
||||
|
||||
//DateMatch is specifilly a match for type date
|
||||
// DateMatch is specifilly a match for type date
|
||||
type DateMatch struct {
|
||||
Pattern string
|
||||
I, J int
|
||||
@@ -37,7 +39,7 @@ type DateMatch struct {
|
||||
Day, Month, Year int64
|
||||
}
|
||||
|
||||
//Matcher are a func and ID that can be used to match different passwords
|
||||
// Matcher are a func and ID that can be used to match different passwords
|
||||
type Matcher struct {
|
||||
MatchingFunc func(password string) []Match
|
||||
ID string
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -20,12 +20,12 @@ var (
|
||||
dateWithOutSepMatch = regexp.MustCompile(`\d{4,8}`)
|
||||
)
|
||||
|
||||
//FilterDateSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
// FilterDateSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
func FilterDateSepMatcher(m match.Matcher) bool {
|
||||
return m.ID == dateSepMatcherName
|
||||
}
|
||||
|
||||
//FilterDateWithoutSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
// FilterDateWithoutSepMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
func FilterDateWithoutSepMatcher(m match.Matcher) bool {
|
||||
return m.ID == dateWithOutSepMatcherName
|
||||
}
|
||||
@@ -64,8 +64,8 @@ func dateSepMatcher(password string) []match.Match {
|
||||
|
||||
return matches
|
||||
}
|
||||
func dateSepMatchHelper(password string) []match.DateMatch {
|
||||
|
||||
func dateSepMatchHelper(password string) []match.DateMatch {
|
||||
var matches []match.DateMatch
|
||||
|
||||
for _, v := range dateRxYearSuffix.FindAllString(password, len(password)) {
|
||||
@@ -101,7 +101,6 @@ func dateSepMatchHelper(password string) []match.DateMatch {
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
}
|
||||
|
||||
type dateMatchCandidate struct {
|
||||
@@ -136,7 +135,7 @@ func dateWithoutSepMatch(password string) []match.Match {
|
||||
return matches
|
||||
}
|
||||
|
||||
//TODO Has issues with 6 digit dates
|
||||
// TODO Has issues with 6 digit dates
|
||||
func dateWithoutSepMatchHelper(password string) (matches []match.DateMatch) {
|
||||
for _, v := range dateWithOutSepMatch.FindAllString(password, len(password)) {
|
||||
i := strings.Index(password, v)
|
||||
@@ -146,17 +145,17 @@ func dateWithoutSepMatchHelper(password string) (matches []match.DateMatch) {
|
||||
var candidatesRoundOne []dateMatchCandidate
|
||||
|
||||
if length <= 6 {
|
||||
//2-digit year prefix
|
||||
// 2-digit year prefix
|
||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[2:], v[0:2], i, j))
|
||||
|
||||
//2-digityear suffix
|
||||
// 2-digityear suffix
|
||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-2], v[lastIndex-2:], i, j))
|
||||
}
|
||||
if length >= 6 {
|
||||
//4-digit year prefix
|
||||
// 4-digit year prefix
|
||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[4:], v[0:4], i, j))
|
||||
|
||||
//4-digit year sufix
|
||||
// 4-digit year sufix
|
||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-3], v[lastIndex-3:], i, j))
|
||||
}
|
||||
|
||||
@@ -179,7 +178,6 @@ func dateWithoutSepMatchHelper(password string) (matches []match.DateMatch) {
|
||||
}
|
||||
|
||||
intMonth, err := strconv.ParseInt(candidate.Month, 10, 16)
|
||||
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -204,6 +202,5 @@ func buildDateMatchCandidate(dayMonth, year string, i, j int) dateMatchCandidate
|
||||
}
|
||||
|
||||
func buildDateMatchCandidateTwo(day, month string, year string, i, j int) dateMatchCandidateTwo {
|
||||
|
||||
return dateMatchCandidateTwo{Day: day, Month: month, Year: year, I: i, J: j}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package matching
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
func buildDictMatcher(dictName string, rankedDict map[string]int) func(password string) []match.Match {
|
||||
@@ -15,7 +15,6 @@ func buildDictMatcher(dictName string, rankedDict map[string]int) func(password
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func dictionaryMatch(password string, dictionaryName string, rankedDict map[string]int) []match.Match {
|
||||
@@ -29,7 +28,8 @@ func dictionaryMatch(password string, dictionaryName string, rankedDict map[stri
|
||||
for j := i; j < length; j++ {
|
||||
word := pwLowerRunes[i : j+1]
|
||||
if val, ok := rankedDict[string(word)]; ok {
|
||||
matchDic := match.Match{Pattern: "dictionary",
|
||||
matchDic := match.Match{
|
||||
Pattern: "dictionary",
|
||||
DictionaryName: dictionaryName,
|
||||
I: i,
|
||||
J: j,
|
||||
@@ -46,7 +46,6 @@ func dictionaryMatch(password string, dictionaryName string, rankedDict map[stri
|
||||
}
|
||||
|
||||
func buildRankedDict(unrankedList []string) map[string]int {
|
||||
|
||||
result := make(map[string]int)
|
||||
|
||||
for i, v := range unrankedList {
|
||||
@@ -3,14 +3,14 @@ package matching
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
// L33TMatcherName id
|
||||
const L33TMatcherName = "l33t"
|
||||
|
||||
//FilterL33tMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
// FilterL33tMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
func FilterL33tMatcher(m match.Matcher) bool {
|
||||
return m.ID == L33TMatcherName
|
||||
}
|
||||
@@ -105,7 +105,7 @@ func createListOfMapsWithoutConflicts(table map[string][]string) []map[string][]
|
||||
return result
|
||||
}
|
||||
|
||||
// This function retrieves the list of values that appear for one or more keys. This is usefull to
|
||||
// This function retrieves the list of values that appear for one or more keys. This is useful to
|
||||
// know which l33t chars can represent more than one letter.
|
||||
func retrieveConflictsListFromTable(table map[string][]string) []string {
|
||||
result := []string{}
|
||||
@@ -128,7 +128,7 @@ func retrieveConflictsListFromTable(table map[string][]string) []string {
|
||||
}
|
||||
|
||||
// This function aims to create different maps for a given char if this char represents a conflict.
|
||||
// If the specified char is not a conflit one, the same map will be returned. In scenarios which
|
||||
// If the specified char is not a conflict one, the same map will be returned. In scenarios which
|
||||
// the provided char can not be found on map, an empty list will be returned. This function was
|
||||
// designed to be used on conflicts situations.
|
||||
func createDifferentMapsForLeetChar(table map[string][]string, leetChar string) []map[string][]string {
|
||||
@@ -158,7 +158,7 @@ func retrieveListOfKeysWithSpecificValueFromTable(table map[string][]string, val
|
||||
return result
|
||||
}
|
||||
|
||||
// This function returns a lsit of substitution map from a given table. Each map in the result will
|
||||
// This function returns a list of substitution map from a given table. Each map in the result will
|
||||
// provide only one representation for each value. As an example, if the provided map contains the
|
||||
// values "@" and "4" in the possibilities to represent "a", two maps will be created where one
|
||||
// will contain "a" mapping to "@" and the other one will provide "a" mapping to "4".
|
||||
@@ -3,9 +3,9 @@ package matching
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/adjacency"
|
||||
"github.com/nbutton23/zxcvbn-go/frequency"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/adjacency"
|
||||
"github.com/ccojocar/zxcvbn-go/frequency"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -23,8 +23,7 @@ func init() {
|
||||
|
||||
// Omnimatch runs all matchers against the password
|
||||
func Omnimatch(password string, userInputs []string, filters ...func(match.Matcher) bool) (matches []match.Match) {
|
||||
|
||||
//Can I run into the issue where nil is not equal to nil?
|
||||
// Can I run into the issue where nil is not equal to nil?
|
||||
if dictionaryMatchers == nil || adjacencyGraphs == nil {
|
||||
loadFrequencyList()
|
||||
}
|
||||
@@ -51,7 +50,6 @@ func Omnimatch(password string, userInputs []string, filters ...func(match.Match
|
||||
}
|
||||
|
||||
func loadFrequencyList() {
|
||||
|
||||
for n, list := range frequency.Lists {
|
||||
dictionaryMatchers = append(dictionaryMatchers, match.Matcher{MatchingFunc: buildDictMatcher(n, buildRankedDict(list.List)), ID: n})
|
||||
}
|
||||
@@ -63,8 +61,8 @@ func loadFrequencyList() {
|
||||
adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["keypad"])
|
||||
adjacencyGraphs = append(adjacencyGraphs, adjacency.GraphMap["macKeypad"])
|
||||
|
||||
//l33tFilePath, _ := filepath.Abs("adjacency/L33t.json")
|
||||
//L33T_TABLE = adjacency.GetAdjancencyGraphFromFile(l33tFilePath, "l33t")
|
||||
// l33tFilePath, _ := filepath.Abs("adjacency/L33t.json")
|
||||
// L33T_TABLE = adjacency.GetAdjancencyGraphFromFile(l33tFilePath, "l33t")
|
||||
|
||||
sequences = make(map[string]string)
|
||||
sequences["lower"] = "abcdefghijklmnopqrstuvwxyz"
|
||||
@@ -78,5 +76,4 @@ func loadFrequencyList() {
|
||||
matchers = append(matchers, match.Matcher{MatchingFunc: l33tMatch, ID: L33TMatcherName})
|
||||
matchers = append(matchers, match.Matcher{MatchingFunc: dateSepMatcher, ID: dateSepMatcherName})
|
||||
matchers = append(matchers, match.Matcher{MatchingFunc: dateWithoutSepMatch, ID: dateWithOutSepMatcherName})
|
||||
|
||||
}
|
||||
@@ -3,13 +3,13 @@ package matching
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
const repeatMatcherName = "REPEAT"
|
||||
|
||||
//FilterRepeatMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
// FilterRepeatMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
func FilterRepeatMatcher(m match.Matcher) bool {
|
||||
return m.ID == repeatMatcherName
|
||||
}
|
||||
@@ -17,7 +17,7 @@ func FilterRepeatMatcher(m match.Matcher) bool {
|
||||
func repeatMatch(password string) []match.Match {
|
||||
var matches []match.Match
|
||||
|
||||
//Loop through password. if current == prev currentStreak++ else if currentStreak > 2 {buildMatch; currentStreak = 1} prev = current
|
||||
// Loop through password. if current == prev currentStreak++ else if currentStreak > 2 {buildMatch; currentStreak = 1} prev = current
|
||||
var current, prev string
|
||||
currentStreak := 1
|
||||
var i int
|
||||
@@ -29,9 +29,8 @@ func repeatMatch(password string) []match.Match {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.ToLower(current) == strings.ToLower(prev) {
|
||||
if strings.EqualFold(current, prev) {
|
||||
currentStreak++
|
||||
|
||||
} else if currentStreak > 2 {
|
||||
iPos := i - currentStreak
|
||||
jPos := i - 1
|
||||
@@ -40,7 +39,8 @@ func repeatMatch(password string) []match.Match {
|
||||
I: iPos,
|
||||
J: jPos,
|
||||
Token: password[iPos : jPos+1],
|
||||
DictionaryName: prev}
|
||||
DictionaryName: prev,
|
||||
}
|
||||
matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat)
|
||||
matches = append(matches, matchRepeat)
|
||||
currentStreak = 1
|
||||
@@ -59,7 +59,8 @@ func repeatMatch(password string) []match.Match {
|
||||
I: iPos,
|
||||
J: jPos,
|
||||
Token: password[iPos : jPos+1],
|
||||
DictionaryName: prev}
|
||||
DictionaryName: prev,
|
||||
}
|
||||
matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat)
|
||||
matches = append(matches, matchRepeat)
|
||||
}
|
||||
@@ -3,13 +3,13 @@ package matching
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
const sequenceMatcherName = "SEQ"
|
||||
|
||||
//FilterSequenceMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
// FilterSequenceMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
func FilterSequenceMatcher(m match.Matcher) bool {
|
||||
return m.ID == sequenceMatcherName
|
||||
}
|
||||
@@ -64,10 +64,8 @@ func sequenceMatch(password string) []match.Match {
|
||||
matches = append(matches, matchSequence)
|
||||
}
|
||||
break
|
||||
} else {
|
||||
j++
|
||||
}
|
||||
|
||||
j++
|
||||
}
|
||||
}
|
||||
i = j
|
||||
@@ -3,14 +3,14 @@ package matching
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/adjacency"
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/adjacency"
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
)
|
||||
|
||||
const spatialMatcherName = "SPATIAL"
|
||||
|
||||
//FilterSpatialMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
// FilterSpatialMatcher can be pass to zxcvbn-go.PasswordStrength to skip that matcher
|
||||
func FilterSpatialMatcher(m match.Matcher) bool {
|
||||
return m.ID == spatialMatcherName
|
||||
}
|
||||
@@ -25,39 +25,38 @@ func spatialMatch(password string) (matches []match.Match) {
|
||||
}
|
||||
|
||||
func spatialMatchHelper(password string, graph adjacency.Graph) (matches []match.Match) {
|
||||
|
||||
for i := 0; i < len(password)-1; {
|
||||
j := i + 1
|
||||
lastDirection := -99 //an int that it should never be!
|
||||
lastDirection := -99 // an int that it should never be!
|
||||
turns := 0
|
||||
shiftedCount := 0
|
||||
|
||||
for {
|
||||
prevChar := password[j-1]
|
||||
found := false
|
||||
foundDirection := -1
|
||||
var foundDirection int
|
||||
curDirection := -1
|
||||
//My graphs seem to be wrong. . . and where the hell is qwerty
|
||||
// My graphs seem to be wrong. . . and where the hell is qwerty
|
||||
adjacents := graph.Graph[string(prevChar)]
|
||||
//Consider growing pattern by one character if j hasn't gone over the edge
|
||||
// Consider growing pattern by one character if j hasn't gone over the edge
|
||||
if j < len(password) {
|
||||
curChar := password[j]
|
||||
for _, adj := range adjacents {
|
||||
curDirection++
|
||||
|
||||
if strings.Index(adj, string(curChar)) != -1 {
|
||||
if strings.Contains(adj, string(curChar)) {
|
||||
found = true
|
||||
foundDirection = curDirection
|
||||
|
||||
if strings.Index(adj, string(curChar)) == 1 {
|
||||
//index 1 in the adjacency means the key is shifted, 0 means unshifted: A vs a, % vs 5, etc.
|
||||
//for example, 'q' is adjacent to the entry '2@'. @ is shifted w/ index 1, 2 is unshifted.
|
||||
// index 1 in the adjacency means the key is shifted, 0 means unshifted: A vs a, % vs 5, etc.
|
||||
// for example, 'q' is adjacent to the entry '2@'. @ is shifted w/ index 1, 2 is unshifted.
|
||||
shiftedCount++
|
||||
}
|
||||
|
||||
if lastDirection != foundDirection {
|
||||
//adding a turn is correct even in the initial case when last_direction is null:
|
||||
//every spatial pattern starts with a turn.
|
||||
// adding a turn is correct even in the initial case when last_direction is null:
|
||||
// every spatial pattern starts with a turn.
|
||||
turns++
|
||||
lastDirection = foundDirection
|
||||
}
|
||||
@@ -66,12 +65,12 @@ func spatialMatchHelper(password string, graph adjacency.Graph) (matches []match
|
||||
}
|
||||
}
|
||||
|
||||
//if the current pattern continued, extend j and try to grow again
|
||||
// if the current pattern continued, extend j and try to grow again
|
||||
if found {
|
||||
j++
|
||||
} else {
|
||||
//otherwise push the pattern discovered so far, if any...
|
||||
//don't consider length 1 or 2 chains.
|
||||
// otherwise push the pattern discovered so far, if any...
|
||||
// don't consider length 1 or 2 chains.
|
||||
if j-i > 2 {
|
||||
matchSpc := match.Match{Pattern: "spatial", I: i, J: j - 1, Token: password[i:j], DictionaryName: graph.Name}
|
||||
matchSpc.Entropy = entropy.SpatialEntropy(matchSpc, turns, shiftedCount)
|
||||
@@ -2,11 +2,12 @@ package scoring
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/nbutton23/zxcvbn-go/entropy"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/nbutton23/zxcvbn-go/utils/math"
|
||||
"math"
|
||||
"sort"
|
||||
|
||||
"github.com/ccojocar/zxcvbn-go/entropy"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
zxcvbnmath "github.com/ccojocar/zxcvbn-go/utils/math"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -15,7 +16,7 @@ const (
|
||||
//adjust for your site accordingly if you use another hash function, possibly by
|
||||
//several orders of magnitude!
|
||||
singleGuess float64 = 0.010
|
||||
numAttackers float64 = 100 //Cores used to make guesses
|
||||
numAttackers float64 = 100 // Cores used to make guesses
|
||||
secondsPerGuess float64 = singleGuess / numAttackers
|
||||
)
|
||||
|
||||
@@ -33,11 +34,11 @@ type MinEntropyMatch struct {
|
||||
/*
|
||||
MinimumEntropyMatchSequence returns the minimum entropy
|
||||
|
||||
Takes a list of overlapping matches, returns the non-overlapping sublist with
|
||||
minimum entropy. O(nm) dp alg for length-n password with m candidate matches.
|
||||
Takes a list of overlapping matches, returns the non-overlapping sublist with
|
||||
minimum entropy. O(nm) dp alg for length-n password with m candidate matches.
|
||||
*/
|
||||
func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntropyMatch {
|
||||
bruteforceCardinality := float64(entropy.CalcBruteForceCardinality(password))
|
||||
bruteforceCardinality := entropy.CalcBruteForceCardinality(password)
|
||||
upToK := make([]float64, len(password))
|
||||
backPointers := make([]match.Match, len(password))
|
||||
|
||||
@@ -50,7 +51,7 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||
}
|
||||
|
||||
i, j := match.I, match.J
|
||||
//see if best entropy up to i-1 + entropy of match is less that current min at j
|
||||
// see if best entropy up to i-1 + entropy of match is less that current min at j
|
||||
upTo := get(upToK, i-1)
|
||||
candidateEntropy := upTo + match.Entropy
|
||||
|
||||
@@ -62,7 +63,7 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||
}
|
||||
}
|
||||
|
||||
//walk backwards and decode the best sequence
|
||||
// walk backwards and decode the best sequence
|
||||
var matchSequence []match.Match
|
||||
passwordLen := len(password)
|
||||
passwordLen--
|
||||
@@ -80,12 +81,13 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||
sort.Sort(match.Matches(matchSequence))
|
||||
|
||||
makeBruteForceMatch := func(i, j int) match.Match {
|
||||
return match.Match{Pattern: "bruteforce",
|
||||
return match.Match{
|
||||
Pattern: "bruteforce",
|
||||
I: i,
|
||||
J: j,
|
||||
Token: password[i : j+1],
|
||||
Entropy: math.Log2(math.Pow(bruteforceCardinality, float64(j-i)))}
|
||||
|
||||
Entropy: math.Log2(math.Pow(bruteforceCardinality, float64(j-i))),
|
||||
}
|
||||
}
|
||||
|
||||
k := 0
|
||||
@@ -110,14 +112,16 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||
}
|
||||
|
||||
crackTime := roundToXDigits(entropyToCrackTime(minEntropy), 3)
|
||||
return MinEntropyMatch{Password: password,
|
||||
return MinEntropyMatch{
|
||||
Password: password,
|
||||
Entropy: roundToXDigits(minEntropy, 3),
|
||||
MatchSequence: matchSequenceCopy,
|
||||
CrackTime: crackTime,
|
||||
CrackTimeDisplay: displayTime(crackTime),
|
||||
Score: crackTimeToScore(crackTime)}
|
||||
|
||||
Score: crackTimeToScore(crackTime),
|
||||
}
|
||||
}
|
||||
|
||||
func get(a []float64, i int) float64 {
|
||||
if i < 0 || i >= len(a) {
|
||||
return float64(0)
|
||||
@@ -3,10 +3,10 @@ package zxcvbn
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"github.com/nbutton23/zxcvbn-go/matching"
|
||||
"github.com/nbutton23/zxcvbn-go/scoring"
|
||||
"github.com/nbutton23/zxcvbn-go/utils/math"
|
||||
"github.com/ccojocar/zxcvbn-go/match"
|
||||
"github.com/ccojocar/zxcvbn-go/matching"
|
||||
"github.com/ccojocar/zxcvbn-go/scoring"
|
||||
zxcvbnmath "github.com/ccojocar/zxcvbn-go/utils/math"
|
||||
)
|
||||
|
||||
// PasswordStrength takes a password, userInputs and optional filters and returns a MinEntropyMatch
|
||||
1
vendor/github.com/gookit/color/README.md
generated
vendored
1
vendor/github.com/gookit/color/README.md
generated
vendored
@@ -570,6 +570,7 @@ Check out these projects, which use https://github.com/gookit/color :
|
||||
- [xo/terminfo](https://github.com/xo/terminfo)
|
||||
- [beego/bee](https://github.com/beego/bee)
|
||||
- [issue9/term](https://github.com/issue9/term)
|
||||
- [muesli/termenv](https://github.com/muesli/termenv)
|
||||
- [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code)
|
||||
- [Standard ANSI color map](https://conemu.github.io/en/AnsiEscapeCodes.html#Standard_ANSI_color_map)
|
||||
- [Terminal Colors](https://gist.github.com/XVilka/8346728)
|
||||
|
||||
1
vendor/github.com/gookit/color/README.zh-CN.md
generated
vendored
1
vendor/github.com/gookit/color/README.zh-CN.md
generated
vendored
@@ -578,6 +578,7 @@ const (
|
||||
## 参考项目
|
||||
|
||||
- [inhere/console](https://github.com/inhere/php-console)
|
||||
- [muesli/termenv](https://github.com/muesli/termenv)
|
||||
- [xo/terminfo](https://github.com/xo/terminfo)
|
||||
- [beego/bee](https://github.com/beego/bee)
|
||||
- [issue9/term](https://github.com/issue9/term)
|
||||
|
||||
6
vendor/github.com/gookit/color/any.go
generated
vendored
Normal file
6
vendor/github.com/gookit/color/any.go
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package color
|
||||
|
||||
type any = interface{}
|
||||
4
vendor/github.com/gookit/color/color.go
generated
vendored
4
vendor/github.com/gookit/color/color.go
generated
vendored
@@ -183,7 +183,7 @@ func InnerErrs() []error {
|
||||
// Usage:
|
||||
//
|
||||
// msg := RenderCode("3;32;45", "some", "message")
|
||||
func RenderCode(code string, args ...interface{}) string {
|
||||
func RenderCode(code string, args ...any) string {
|
||||
var message string
|
||||
if ln := len(args); ln == 0 {
|
||||
return ""
|
||||
@@ -205,7 +205,7 @@ func RenderCode(code string, args ...interface{}) string {
|
||||
|
||||
// RenderWithSpaces Render code with spaces.
|
||||
// If the number of args is > 1, a space will be added between the args
|
||||
func RenderWithSpaces(code string, args ...interface{}) string {
|
||||
func RenderWithSpaces(code string, args ...any) string {
|
||||
msg := formatArgsForPrintln(args)
|
||||
if len(code) == 0 {
|
||||
return msg
|
||||
|
||||
104
vendor/github.com/gookit/color/color_16.go
generated
vendored
104
vendor/github.com/gookit/color/color_16.go
generated
vendored
@@ -41,15 +41,27 @@ func (o Opts) String() string {
|
||||
* Basic 16 color definition
|
||||
*************************************************************/
|
||||
|
||||
// Base value for foreground/background color
|
||||
// base: fg 30~37, bg 40~47
|
||||
// light: fg 90~97, bg 100~107
|
||||
const (
|
||||
// OptMax max option value. range: 0 - 9
|
||||
OptMax = 10
|
||||
// DiffFgBg diff foreground and background color
|
||||
DiffFgBg = 10
|
||||
)
|
||||
|
||||
// Boundary value for foreground/background color 16
|
||||
//
|
||||
// - base: fg 30~37, bg 40~47
|
||||
// - light: fg 90~97, bg 100~107
|
||||
const (
|
||||
FgBase uint8 = 30
|
||||
FgMax uint8 = 37
|
||||
BgBase uint8 = 40
|
||||
BgMax uint8 = 47
|
||||
|
||||
HiFgBase uint8 = 90
|
||||
HiFgMax uint8 = 97
|
||||
HiBgBase uint8 = 100
|
||||
HiBgMax uint8 = 107
|
||||
)
|
||||
|
||||
// Foreground colors. basic foreground colors 30 - 37
|
||||
@@ -94,7 +106,7 @@ const (
|
||||
BgDefault Color = 49
|
||||
)
|
||||
|
||||
// Extra background color 100 - 107(非标准)
|
||||
// Extra background color 100 - 107 (non-standard)
|
||||
const (
|
||||
BgDarkGray Color = iota + 100
|
||||
BgLightRed
|
||||
@@ -108,7 +120,7 @@ const (
|
||||
BgGray Color = 100
|
||||
)
|
||||
|
||||
// Option settings
|
||||
// Option settings. range: 0 - 9
|
||||
const (
|
||||
OpReset Color = iota // 0 重置所有设置
|
||||
OpBold // 1 加粗
|
||||
@@ -188,61 +200,69 @@ func (c Color) Text(message string) string { return RenderString(c.String(), mes
|
||||
// Render messages by color setting
|
||||
//
|
||||
// Usage:
|
||||
// green := color.FgGreen.Render
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Render(a ...interface{}) string { return RenderCode(c.String(), a...) }
|
||||
//
|
||||
// green := color.FgGreen.Render
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Render(a ...any) string { return RenderCode(c.String(), a...) }
|
||||
|
||||
// Renderln messages by color setting.
|
||||
// like Println, will add spaces for each argument
|
||||
//
|
||||
// Usage:
|
||||
// green := color.FgGreen.Renderln
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Renderln(a ...interface{}) string { return RenderWithSpaces(c.String(), a...) }
|
||||
//
|
||||
// green := color.FgGreen.Renderln
|
||||
// fmt.Println(green("message"))
|
||||
func (c Color) Renderln(a ...any) string { return RenderWithSpaces(c.String(), a...) }
|
||||
|
||||
// Sprint render messages by color setting. is alias of the Render()
|
||||
func (c Color) Sprint(a ...interface{}) string { return RenderCode(c.String(), a...) }
|
||||
func (c Color) Sprint(a ...any) string { return RenderCode(c.String(), a...) }
|
||||
|
||||
// Sprintf format and render message.
|
||||
//
|
||||
// Usage:
|
||||
// green := color.Green.Sprintf
|
||||
// colored := green("message")
|
||||
func (c Color) Sprintf(format string, args ...interface{}) string {
|
||||
//
|
||||
// green := color.Green.Sprintf
|
||||
// colored := green("message")
|
||||
func (c Color) Sprintf(format string, args ...any) string {
|
||||
return RenderString(c.String(), fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
// Print messages.
|
||||
//
|
||||
// Usage:
|
||||
// color.Green.Print("message")
|
||||
//
|
||||
// color.Green.Print("message")
|
||||
//
|
||||
// OR:
|
||||
// green := color.FgGreen.Print
|
||||
// green("message")
|
||||
func (c Color) Print(args ...interface{}) {
|
||||
//
|
||||
// green := color.FgGreen.Print
|
||||
// green("message")
|
||||
func (c Color) Print(args ...any) {
|
||||
doPrintV2(c.Code(), fmt.Sprint(args...))
|
||||
}
|
||||
|
||||
// Printf format and print messages.
|
||||
//
|
||||
// Usage:
|
||||
// color.Cyan.Printf("string %s", "arg0")
|
||||
func (c Color) Printf(format string, a ...interface{}) {
|
||||
//
|
||||
// color.Cyan.Printf("string %s", "arg0")
|
||||
func (c Color) Printf(format string, a ...any) {
|
||||
doPrintV2(c.Code(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println messages with new line
|
||||
func (c Color) Println(a ...interface{}) { doPrintlnV2(c.String(), a) }
|
||||
func (c Color) Println(a ...any) { doPrintlnV2(c.String(), a) }
|
||||
|
||||
// Light current color. eg: 36(FgCyan) -> 96(FgLightCyan).
|
||||
//
|
||||
// Usage:
|
||||
// lightCyan := Cyan.Light()
|
||||
// lightCyan.Print("message")
|
||||
//
|
||||
// lightCyan := Cyan.Light()
|
||||
// lightCyan.Print("message")
|
||||
func (c Color) Light() Color {
|
||||
val := int(c)
|
||||
val := uint8(c)
|
||||
if val >= 30 && val <= 47 {
|
||||
return Color(uint8(c) + 60)
|
||||
return Color(val + 60)
|
||||
}
|
||||
|
||||
// don't change
|
||||
@@ -252,12 +272,13 @@ func (c Color) Light() Color {
|
||||
// Darken current color. eg. 96(FgLightCyan) -> 36(FgCyan)
|
||||
//
|
||||
// Usage:
|
||||
// cyan := LightCyan.Darken()
|
||||
// cyan.Print("message")
|
||||
//
|
||||
// cyan := LightCyan.Darken()
|
||||
// cyan.Print("message")
|
||||
func (c Color) Darken() Color {
|
||||
val := int(c)
|
||||
val := uint8(c)
|
||||
if val >= 90 && val <= 107 {
|
||||
return Color(uint8(c) - 60)
|
||||
return Color(val - 60)
|
||||
}
|
||||
|
||||
// don't change
|
||||
@@ -315,7 +336,7 @@ func (c Color) RGB() RGBColor {
|
||||
return emptyRGBColor
|
||||
}
|
||||
|
||||
return HEX(Basic2hex(val))
|
||||
return HEX(Basic2hex(val), c.IsBg())
|
||||
}
|
||||
|
||||
// Code convert to code string. eg "35"
|
||||
@@ -328,8 +349,23 @@ func (c Color) String() string {
|
||||
return strconv.FormatInt(int64(c), 10)
|
||||
}
|
||||
|
||||
// IsBg check is background color
|
||||
func (c Color) IsBg() bool {
|
||||
val := uint8(c)
|
||||
return val >= BgBase && val <= BgMax || val >= HiBgBase && val <= HiBgMax
|
||||
}
|
||||
|
||||
// IsFg check is foreground color
|
||||
func (c Color) IsFg() bool {
|
||||
val := uint8(c)
|
||||
return val >= FgBase && val <= FgMax || val >= HiFgBase && val <= HiFgMax
|
||||
}
|
||||
|
||||
// IsOption check is option code: 0-9
|
||||
func (c Color) IsOption() bool { return uint8(c) < OptMax }
|
||||
|
||||
// IsValid color value
|
||||
func (c Color) IsValid() bool { return c < 107 }
|
||||
func (c Color) IsValid() bool { return uint8(c) < HiBgMax }
|
||||
|
||||
/*************************************************************
|
||||
* basic color maps
|
||||
@@ -461,9 +497,7 @@ func Fg2Bg(val uint8) uint8 {
|
||||
}
|
||||
|
||||
// Basic2nameMap data
|
||||
func Basic2nameMap() map[uint8]string {
|
||||
return basic2nameMap
|
||||
}
|
||||
func Basic2nameMap() map[uint8]string { return basic2nameMap }
|
||||
|
||||
// func initName2basicMap() map[string]uint8 {
|
||||
// n2b := make(map[string]uint8, len(basic2nameMap))
|
||||
|
||||
68
vendor/github.com/gookit/color/color_256.go
generated
vendored
68
vendor/github.com/gookit/color/color_256.go
generated
vendored
@@ -19,16 +19,19 @@ from wikipedia, 256 color:
|
||||
// tpl for 8 bit 256 color(`2^8`)
|
||||
//
|
||||
// format:
|
||||
// ESC[ … 38;5;<n> … m // 选择前景色
|
||||
// ESC[ … 48;5;<n> … m // 选择背景色
|
||||
//
|
||||
// ESC[ … 38;5;<n> … m // 选择前景色
|
||||
// ESC[ … 48;5;<n> … m // 选择背景色
|
||||
//
|
||||
// example:
|
||||
// fg "\x1b[38;5;242m"
|
||||
// bg "\x1b[48;5;208m"
|
||||
// both "\x1b[38;5;242;48;5;208m"
|
||||
//
|
||||
// fg "\x1b[38;5;242m"
|
||||
// bg "\x1b[48;5;208m"
|
||||
// both "\x1b[38;5;242;48;5;208m"
|
||||
//
|
||||
// links:
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位
|
||||
//
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#8位
|
||||
const (
|
||||
TplFg256 = "38;5;%d"
|
||||
TplBg256 = "48;5;%d"
|
||||
@@ -40,19 +43,21 @@ const (
|
||||
* 8bit(256) Color: Bit8Color Color256
|
||||
*************************************************************/
|
||||
|
||||
// Color256 256 color (8 bit), uint8 range at 0 - 255
|
||||
// Color256 256 color (8 bit), uint8 range at 0 - 255.
|
||||
// Support 256 color on windows CMD, PowerShell
|
||||
//
|
||||
// 颜色值使用10进制和16进制都可 0x98 = 152
|
||||
//
|
||||
// The color consists of two uint8:
|
||||
// 0: color value
|
||||
// 1: color type; Fg=0, Bg=1, >1: unset value
|
||||
//
|
||||
// 0: color value
|
||||
// 1: color type; Fg=0, Bg=1, >1: unset value
|
||||
//
|
||||
// example:
|
||||
// fg color: [152, 0]
|
||||
// bg color: [152, 1]
|
||||
//
|
||||
// NOTICE: now support 256 color on windows CMD, PowerShell
|
||||
// fg color: [152, 0]
|
||||
// bg color: [152, 1]
|
||||
//
|
||||
// lint warn - Name starts with package name
|
||||
type Color256 [2]uint8
|
||||
type Bit8Color = Color256 // alias
|
||||
@@ -87,27 +92,27 @@ func (c Color256) Reset() error {
|
||||
}
|
||||
|
||||
// Print print message
|
||||
func (c Color256) Print(a ...interface{}) {
|
||||
func (c Color256) Print(a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (c Color256) Printf(format string, a ...interface{}) {
|
||||
func (c Color256) Printf(format string, a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (c Color256) Println(a ...interface{}) {
|
||||
func (c Color256) Println(a ...any) {
|
||||
doPrintlnV2(c.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (c Color256) Sprint(a ...interface{}) string {
|
||||
func (c Color256) Sprint(a ...any) string {
|
||||
return RenderCode(c.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (c Color256) Sprintf(format string, a ...interface{}) string {
|
||||
func (c Color256) Sprintf(format string, a ...any) string {
|
||||
return RenderString(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
@@ -159,9 +164,7 @@ func (c Color256) String() string {
|
||||
}
|
||||
|
||||
// IsFg color
|
||||
func (c Color256) IsFg() bool {
|
||||
return c[1] == AsFg
|
||||
}
|
||||
func (c Color256) IsFg() bool { return c[1] == AsFg }
|
||||
|
||||
// ToFg 256 color
|
||||
func (c Color256) ToFg() Color256 {
|
||||
@@ -170,9 +173,7 @@ func (c Color256) ToFg() Color256 {
|
||||
}
|
||||
|
||||
// IsBg color
|
||||
func (c Color256) IsBg() bool {
|
||||
return c[1] == AsBg
|
||||
}
|
||||
func (c Color256) IsBg() bool { return c[1] == AsBg }
|
||||
|
||||
// ToBg 256 color
|
||||
func (c Color256) ToBg() Color256 {
|
||||
@@ -181,9 +182,7 @@ func (c Color256) ToBg() Color256 {
|
||||
}
|
||||
|
||||
// IsEmpty value
|
||||
func (c Color256) IsEmpty() bool {
|
||||
return c[1] > 1
|
||||
}
|
||||
func (c Color256) IsEmpty() bool { return c[1] > 1 }
|
||||
|
||||
/*************************************************************
|
||||
* 8bit(256) Style
|
||||
@@ -206,9 +205,10 @@ type Style256 struct {
|
||||
// S256 create a color256 style
|
||||
//
|
||||
// Usage:
|
||||
// s := color.S256()
|
||||
// s := color.S256(132) // fg
|
||||
// s := color.S256(132, 203) // fg and bg
|
||||
//
|
||||
// s := color.S256()
|
||||
// s := color.S256(132) // fg
|
||||
// s := color.S256(132, 203) // fg and bg
|
||||
func S256(fgAndBg ...uint8) *Style256 {
|
||||
s := &Style256{}
|
||||
vl := len(fgAndBg)
|
||||
@@ -256,27 +256,27 @@ func (s *Style256) AddOpts(opts ...Color) *Style256 {
|
||||
}
|
||||
|
||||
// Print message
|
||||
func (s *Style256) Print(a ...interface{}) {
|
||||
func (s *Style256) Print(a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (s *Style256) Printf(format string, a ...interface{}) {
|
||||
func (s *Style256) Printf(format string, a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (s *Style256) Println(a ...interface{}) {
|
||||
func (s *Style256) Println(a ...any) {
|
||||
doPrintlnV2(s.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (s *Style256) Sprint(a ...interface{}) string {
|
||||
func (s *Style256) Sprint(a ...any) string {
|
||||
return RenderCode(s.Code(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (s *Style256) Sprintf(format string, a ...interface{}) string {
|
||||
func (s *Style256) Sprintf(format string, a ...any) string {
|
||||
return RenderString(s.Code(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
|
||||
103
vendor/github.com/gookit/color/color_rgb.go
generated
vendored
103
vendor/github.com/gookit/color/color_rgb.go
generated
vendored
@@ -8,20 +8,24 @@ import (
|
||||
|
||||
// 24 bit RGB color
|
||||
// RGB:
|
||||
// R 0-255 G 0-255 B 0-255
|
||||
// R 00-FF G 00-FF B 00-FF (16进制)
|
||||
//
|
||||
// R 0-255 G 0-255 B 0-255
|
||||
// R 00-FF G 00-FF B 00-FF (16进制)
|
||||
//
|
||||
// Format:
|
||||
// ESC[ … 38;2;<r>;<g>;<b> … m // Select RGB foreground color
|
||||
// ESC[ … 48;2;<r>;<g>;<b> … m // Choose RGB background color
|
||||
//
|
||||
// ESC[ … 38;2;<r>;<g>;<b> … m // Select RGB foreground color
|
||||
// ESC[ … 48;2;<r>;<g>;<b> … m // Choose RGB background color
|
||||
//
|
||||
// links:
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位
|
||||
//
|
||||
// https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位
|
||||
//
|
||||
// example:
|
||||
// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m
|
||||
// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m
|
||||
// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m
|
||||
//
|
||||
// fg: \x1b[38;2;30;144;255mMESSAGE\x1b[0m
|
||||
// bg: \x1b[48;2;30;144;255mMESSAGE\x1b[0m
|
||||
// both: \x1b[38;2;233;90;203;48;2;30;144;255mMESSAGE\x1b[0m
|
||||
const (
|
||||
TplFgRGB = "38;2;%d;%d;%d"
|
||||
TplBgRGB = "48;2;%d;%d;%d"
|
||||
@@ -40,17 +44,17 @@ const (
|
||||
*************************************************************/
|
||||
|
||||
// RGBColor definition.
|
||||
// Support RGB color on Windows CMD, PowerShell
|
||||
//
|
||||
// The first to third digits represent the color value.
|
||||
// The last digit represents the foreground(0), background(1), >1 is unset value
|
||||
//
|
||||
// Usage:
|
||||
// // 0, 1, 2 is R,G,B.
|
||||
// // 3rd: Fg=0, Bg=1, >1: unset value
|
||||
// RGBColor{30,144,255, 0}
|
||||
// RGBColor{30,144,255, 1}
|
||||
//
|
||||
// NOTICE: now support RGB color on Windows CMD, PowerShell
|
||||
// // 0, 1, 2 is R,G,B.
|
||||
// // 3rd: Fg=0, Bg=1, >1: unset value
|
||||
// RGBColor{30,144,255, 0}
|
||||
// RGBColor{30,144,255, 1}
|
||||
type RGBColor [4]uint8
|
||||
|
||||
// create an empty RGBColor
|
||||
@@ -59,9 +63,10 @@ var emptyRGBColor = RGBColor{3: 99}
|
||||
// RGB color create.
|
||||
//
|
||||
// Usage:
|
||||
// c := RGB(30,144,255)
|
||||
// c := RGB(30,144,255, true)
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := RGB(30,144,255)
|
||||
// c := RGB(30,144,255, true)
|
||||
// c.Print("message")
|
||||
func RGB(r, g, b uint8, isBg ...bool) RGBColor {
|
||||
rgb := RGBColor{r, g, b}
|
||||
if len(isBg) > 0 && isBg[0] {
|
||||
@@ -90,11 +95,12 @@ func RgbFromInts(rgb []int, isBg ...bool) RGBColor {
|
||||
// HEX create RGB color from a HEX color string.
|
||||
//
|
||||
// Usage:
|
||||
// c := HEX("ccc") // rgb: [204 204 204]
|
||||
// c := HEX("aabbcc") // rgb: [170 187 204]
|
||||
// c := HEX("#aabbcc")
|
||||
// c := HEX("0xaabbcc")
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := HEX("ccc") // rgb: [204 204 204]
|
||||
// c := HEX("aabbcc") // rgb: [170 187 204]
|
||||
// c := HEX("#aabbcc")
|
||||
// c := HEX("0xaabbcc")
|
||||
// c.Print("message")
|
||||
func HEX(hex string, isBg ...bool) RGBColor {
|
||||
if rgb := HexToRgb(hex); len(rgb) > 0 {
|
||||
return RGB(uint8(rgb[0]), uint8(rgb[1]), uint8(rgb[2]), isBg...)
|
||||
@@ -139,11 +145,12 @@ func RGBFromSlice(rgb []uint8, isBg ...bool) RGBColor {
|
||||
// Support use color name in the {namedRgbMap}
|
||||
//
|
||||
// Usage:
|
||||
// c := RGBFromString("170,187,204")
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := RGBFromString("brown")
|
||||
// c.Print("message with color brown")
|
||||
// c := RGBFromString("170,187,204")
|
||||
// c.Print("message")
|
||||
//
|
||||
// c := RGBFromString("brown")
|
||||
// c.Print("message with color brown")
|
||||
func RGBFromString(rgb string, isBg ...bool) RGBColor {
|
||||
// use color name in the {namedRgbMap}
|
||||
if rgbVal, ok := namedRgbMap[rgb]; ok {
|
||||
@@ -180,27 +187,27 @@ func (c RGBColor) Reset() error {
|
||||
}
|
||||
|
||||
// Print print message
|
||||
func (c RGBColor) Print(a ...interface{}) {
|
||||
func (c RGBColor) Print(a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (c RGBColor) Printf(format string, a ...interface{}) {
|
||||
func (c RGBColor) Printf(format string, a ...any) {
|
||||
doPrintV2(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (c RGBColor) Println(a ...interface{}) {
|
||||
func (c RGBColor) Println(a ...any) {
|
||||
doPrintlnV2(c.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (c RGBColor) Sprint(a ...interface{}) string {
|
||||
func (c RGBColor) Sprint(a ...any) string {
|
||||
return RenderCode(c.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (c RGBColor) Sprintf(format string, a ...interface{}) string {
|
||||
func (c RGBColor) Sprintf(format string, a ...any) string {
|
||||
return RenderString(c.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
@@ -243,6 +250,18 @@ func (c RGBColor) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ToBg convert to background color
|
||||
func (c RGBColor) ToBg() RGBColor {
|
||||
c[3] = AsBg
|
||||
return c
|
||||
}
|
||||
|
||||
// ToFg convert to foreground color
|
||||
func (c RGBColor) ToFg() RGBColor {
|
||||
c[3] = AsFg
|
||||
return c
|
||||
}
|
||||
|
||||
// IsEmpty value
|
||||
func (c RGBColor) IsEmpty() bool {
|
||||
return c[3] > AsBg
|
||||
@@ -279,8 +298,8 @@ func (c RGBColor) C16() Color { return c.Basic() }
|
||||
// All are composed of 4 digits uint8, the first three digits are the color value;
|
||||
// The last bit is different from RGBColor, here it indicates whether the value is set.
|
||||
//
|
||||
// 1 Has been set
|
||||
// ^1 Not set
|
||||
// 1 Has been set
|
||||
// ^1 Not set
|
||||
type RGBStyle struct {
|
||||
// Name of the style
|
||||
Name string
|
||||
@@ -303,8 +322,9 @@ func NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle {
|
||||
// HEXStyle create a RGBStyle from HEX color string.
|
||||
//
|
||||
// Usage:
|
||||
// s := HEXStyle("aabbcc", "eee")
|
||||
// s.Print("message")
|
||||
//
|
||||
// s := HEXStyle("aabbcc", "eee")
|
||||
// s.Print("message")
|
||||
func HEXStyle(fg string, bg ...string) *RGBStyle {
|
||||
s := &RGBStyle{}
|
||||
if len(bg) > 0 {
|
||||
@@ -320,8 +340,9 @@ func HEXStyle(fg string, bg ...string) *RGBStyle {
|
||||
// RGBStyleFromString create a RGBStyle from color value string.
|
||||
//
|
||||
// Usage:
|
||||
// s := RGBStyleFromString("170,187,204", "70,87,4")
|
||||
// s.Print("message")
|
||||
//
|
||||
// s := RGBStyleFromString("170,187,204", "70,87,4")
|
||||
// s.Print("message")
|
||||
func RGBStyleFromString(fg string, bg ...string) *RGBStyle {
|
||||
s := &RGBStyle{}
|
||||
if len(bg) > 0 {
|
||||
@@ -363,27 +384,27 @@ func (s *RGBStyle) AddOpts(opts ...Color) *RGBStyle {
|
||||
}
|
||||
|
||||
// Print print message
|
||||
func (s *RGBStyle) Print(a ...interface{}) {
|
||||
func (s *RGBStyle) Print(a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and print message
|
||||
func (s *RGBStyle) Printf(format string, a ...interface{}) {
|
||||
func (s *RGBStyle) Printf(format string, a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println print message with newline
|
||||
func (s *RGBStyle) Println(a ...interface{}) {
|
||||
func (s *RGBStyle) Println(a ...any) {
|
||||
doPrintlnV2(s.String(), a)
|
||||
}
|
||||
|
||||
// Sprint returns rendered message
|
||||
func (s *RGBStyle) Sprint(a ...interface{}) string {
|
||||
func (s *RGBStyle) Sprint(a ...any) string {
|
||||
return RenderCode(s.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendered message
|
||||
func (s *RGBStyle) Sprintf(format string, a ...interface{}) string {
|
||||
func (s *RGBStyle) Sprintf(format string, a ...any) string {
|
||||
return RenderString(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
|
||||
56
vendor/github.com/gookit/color/color_tag.go
generated
vendored
56
vendor/github.com/gookit/color/color_tag.go
generated
vendored
@@ -41,7 +41,8 @@ var (
|
||||
// There are internal defined fg color tags
|
||||
//
|
||||
// Usage:
|
||||
// <tag>content text</>
|
||||
//
|
||||
// <tag>content text</>
|
||||
//
|
||||
// @notice 加 0 在前面是为了防止之前的影响到现在的设置
|
||||
var colorTags = map[string]string{
|
||||
@@ -324,15 +325,17 @@ func (tp *TagParser) ParseByEnv(str string) string {
|
||||
return tp.Parse(str)
|
||||
}
|
||||
|
||||
// Parse parse given string, replace color tag and return rendered string
|
||||
// Parse given string, replace color tag and return rendered string
|
||||
//
|
||||
// Use built in tags:
|
||||
// <TAG_NAME>CONTENT</>
|
||||
// // e.g: `<info>message</>`
|
||||
//
|
||||
// <TAG_NAME>CONTENT</>
|
||||
// // e.g: `<info>message</>`
|
||||
//
|
||||
// Custom tag attributes:
|
||||
// `<fg=VALUE;bg=VALUE;op=VALUES>CONTENT</>`
|
||||
// // e.g: `<fg=167;bg=232>wel</>`
|
||||
//
|
||||
// `<fg=VALUE;bg=VALUE;op=VALUES>CONTENT</>`
|
||||
// // e.g: `<fg=167;bg=232>wel</>`
|
||||
func (tp *TagParser) Parse(str string) string {
|
||||
// not contains color tag
|
||||
if !strings.Contains(str, "</>") {
|
||||
@@ -376,26 +379,30 @@ func ReplaceTag(str string) string {
|
||||
// ParseCodeFromAttr parse color attributes.
|
||||
//
|
||||
// attr format:
|
||||
// // VALUE please see var: FgColors, BgColors, AllOptions
|
||||
// "fg=VALUE;bg=VALUE;op=VALUE"
|
||||
//
|
||||
// // VALUE please see var: FgColors, BgColors, AllOptions
|
||||
// "fg=VALUE;bg=VALUE;op=VALUE"
|
||||
//
|
||||
// 16 color:
|
||||
// "fg=yellow"
|
||||
// "bg=red"
|
||||
// "op=bold,underscore" // option is allow multi value
|
||||
// "fg=white;bg=blue;op=bold"
|
||||
// "fg=white;op=bold,underscore"
|
||||
//
|
||||
// "fg=yellow"
|
||||
// "bg=red"
|
||||
// "op=bold,underscore" // option is allow multi value
|
||||
// "fg=white;bg=blue;op=bold"
|
||||
// "fg=white;op=bold,underscore"
|
||||
//
|
||||
// 256 color:
|
||||
//
|
||||
// "fg=167"
|
||||
// "fg=167;bg=23"
|
||||
// "fg=167;bg=23;op=bold"
|
||||
//
|
||||
// True color:
|
||||
// // hex
|
||||
//
|
||||
// // hex
|
||||
// "fg=fc1cac"
|
||||
// "fg=fc1cac;bg=c2c3c4"
|
||||
// // r,g,b
|
||||
// // r,g,b
|
||||
// "fg=23,45,214"
|
||||
// "fg=23,45,214;bg=109,99,88"
|
||||
func ParseCodeFromAttr(attr string) (code string) {
|
||||
@@ -476,12 +483,10 @@ func ClearTag(s string) string {
|
||||
*************************************************************/
|
||||
|
||||
// GetTagCode get color code by tag name
|
||||
func GetTagCode(name string) string {
|
||||
return colorTags[name]
|
||||
}
|
||||
func GetTagCode(name string) string { return colorTags[name] }
|
||||
|
||||
// ApplyTag for messages
|
||||
func ApplyTag(tag string, a ...interface{}) string {
|
||||
func ApplyTag(tag string, a ...any) string {
|
||||
return RenderCode(GetTagCode(tag), a...)
|
||||
}
|
||||
|
||||
@@ -510,11 +515,12 @@ func IsDefinedTag(name string) bool {
|
||||
|
||||
// Tag value is a defined style name
|
||||
// Usage:
|
||||
// Tag("info").Println("message")
|
||||
//
|
||||
// Tag("info").Println("message")
|
||||
type Tag string
|
||||
|
||||
// Print messages
|
||||
func (tg Tag) Print(a ...interface{}) {
|
||||
func (tg Tag) Print(a ...any) {
|
||||
name := string(tg)
|
||||
str := fmt.Sprint(a...)
|
||||
|
||||
@@ -526,7 +532,7 @@ func (tg Tag) Print(a ...interface{}) {
|
||||
}
|
||||
|
||||
// Printf format and print messages
|
||||
func (tg Tag) Printf(format string, a ...interface{}) {
|
||||
func (tg Tag) Printf(format string, a ...any) {
|
||||
name := string(tg)
|
||||
str := fmt.Sprintf(format, a...)
|
||||
|
||||
@@ -538,7 +544,7 @@ func (tg Tag) Printf(format string, a ...interface{}) {
|
||||
}
|
||||
|
||||
// Println messages line
|
||||
func (tg Tag) Println(a ...interface{}) {
|
||||
func (tg Tag) Println(a ...any) {
|
||||
name := string(tg)
|
||||
if stl := GetStyle(name); !stl.IsEmpty() {
|
||||
stl.Println(a...)
|
||||
@@ -548,12 +554,12 @@ func (tg Tag) Println(a ...interface{}) {
|
||||
}
|
||||
|
||||
// Sprint render messages
|
||||
func (tg Tag) Sprint(a ...interface{}) string {
|
||||
func (tg Tag) Sprint(a ...any) string {
|
||||
return RenderCode(GetTagCode(string(tg)), a...)
|
||||
}
|
||||
|
||||
// Sprintf format and render messages
|
||||
func (tg Tag) Sprintf(format string, a ...interface{}) string {
|
||||
func (tg Tag) Sprintf(format string, a ...any) string {
|
||||
tag := string(tg)
|
||||
str := fmt.Sprintf(format, a...)
|
||||
|
||||
|
||||
24
vendor/github.com/gookit/color/convert.go
generated
vendored
24
vendor/github.com/gookit/color/convert.go
generated
vendored
@@ -52,6 +52,7 @@ var (
|
||||
|
||||
// ---------- basic(16) <=> RGB color convert ----------
|
||||
// refer from Hyper app
|
||||
// Tip: only keep foreground color, background color need convert to foreground color for convert to RGB
|
||||
basic2hexMap = map[uint8]string{
|
||||
30: "000000", // black
|
||||
31: "c51e14", // red
|
||||
@@ -61,7 +62,7 @@ var (
|
||||
35: "c839c5", // magenta
|
||||
36: "20c5c6", // cyan
|
||||
37: "c7c7c7", // white
|
||||
// - don't add bg color
|
||||
// - don't add bg color, convert to fg color for convert to RGB
|
||||
// 40: "000000", // black
|
||||
// 41: "c51e14", // red
|
||||
// 42: "1dc121", // green
|
||||
@@ -428,10 +429,11 @@ func HexToRGB(hex string) []int { return HexToRgb(hex) }
|
||||
// HexToRgb convert hex color string to RGB numbers
|
||||
//
|
||||
// Usage:
|
||||
// rgb := HexToRgb("ccc") // rgb: [204 204 204]
|
||||
// rgb := HexToRgb("aabbcc") // rgb: [170 187 204]
|
||||
// rgb := HexToRgb("#aabbcc") // rgb: [170 187 204]
|
||||
// rgb := HexToRgb("0xad99c0") // rgb: [170 187 204]
|
||||
//
|
||||
// rgb := HexToRgb("ccc") // rgb: [204 204 204]
|
||||
// rgb := HexToRgb("aabbcc") // rgb: [170 187 204]
|
||||
// rgb := HexToRgb("#aabbcc") // rgb: [170 187 204]
|
||||
// rgb := HexToRgb("0xad99c0") // rgb: [170 187 204]
|
||||
func HexToRgb(hex string) (rgb []int) {
|
||||
hex = strings.TrimSpace(hex)
|
||||
if hex == "" {
|
||||
@@ -474,6 +476,7 @@ func Rgb2hex(rgb []int) string { return RgbToHex(rgb) }
|
||||
// RgbToHex convert RGB-code to hex-code
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// hex := RgbToHex([]int{170, 187, 204}) // hex: "aabbcc"
|
||||
func RgbToHex(rgb []int) string {
|
||||
hexNodes := make([]string, len(rgb))
|
||||
@@ -488,10 +491,15 @@ func RgbToHex(rgb []int) string {
|
||||
* 4bit(16) color <=> RGB/True color
|
||||
*************************************************************/
|
||||
|
||||
// BasicToHex convert basic color to hex string.
|
||||
func BasicToHex(val uint8) string {
|
||||
val = Bg2Fg(val)
|
||||
return basic2hexMap[val]
|
||||
}
|
||||
|
||||
// Basic2hex convert basic color to hex string.
|
||||
func Basic2hex(val uint8) string {
|
||||
val = Fg2Bg(val)
|
||||
return basic2hexMap[val]
|
||||
return BasicToHex(val)
|
||||
}
|
||||
|
||||
// Hex2basic convert hex string to basic color code.
|
||||
@@ -663,6 +671,7 @@ func C256ToRgbV1(val uint8) (rgb []uint8) {
|
||||
// returns r, g, and b in the set [0, 255].
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// HslIntToRgb(0, 100, 50) // red
|
||||
// HslIntToRgb(120, 100, 50) // lime
|
||||
// HslIntToRgb(120, 100, 25) // dark green
|
||||
@@ -677,6 +686,7 @@ func HslIntToRgb(h, s, l int) (rgb []uint8) {
|
||||
// returns r, g, and b in the set [0, 255].
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// rgbVals := HslToRgb(0, 1, 0.5) // red
|
||||
func HslToRgb(h, s, l float64) (rgb []uint8) {
|
||||
var r, g, b float64
|
||||
|
||||
53
vendor/github.com/gookit/color/printer.go
generated
vendored
53
vendor/github.com/gookit/color/printer.go
generated
vendored
@@ -9,18 +9,19 @@ import "fmt"
|
||||
// PrinterFace interface
|
||||
type PrinterFace interface {
|
||||
fmt.Stringer
|
||||
Sprint(a ...interface{}) string
|
||||
Sprintf(format string, a ...interface{}) string
|
||||
Print(a ...interface{})
|
||||
Printf(format string, a ...interface{})
|
||||
Println(a ...interface{})
|
||||
Sprint(a ...any) string
|
||||
Sprintf(format string, a ...any) string
|
||||
Print(a ...any)
|
||||
Printf(format string, a ...any)
|
||||
Println(a ...any)
|
||||
}
|
||||
|
||||
// Printer a generic color message printer.
|
||||
//
|
||||
// Usage:
|
||||
// p := &Printer{Code: "32;45;3"}
|
||||
// p.Print("message")
|
||||
//
|
||||
// p := &Printer{Code: "32;45;3"}
|
||||
// p.Print("message")
|
||||
type Printer struct {
|
||||
// NoColor disable color.
|
||||
NoColor bool
|
||||
@@ -40,27 +41,27 @@ func (p *Printer) String() string {
|
||||
}
|
||||
|
||||
// Sprint returns rendering colored messages
|
||||
func (p *Printer) Sprint(a ...interface{}) string {
|
||||
func (p *Printer) Sprint(a ...any) string {
|
||||
return RenderCode(p.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf returns format and rendering colored messages
|
||||
func (p *Printer) Sprintf(format string, a ...interface{}) string {
|
||||
func (p *Printer) Sprintf(format string, a ...any) string {
|
||||
return RenderString(p.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Print rendering colored messages
|
||||
func (p *Printer) Print(a ...interface{}) {
|
||||
func (p *Printer) Print(a ...any) {
|
||||
doPrintV2(p.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf format and rendering colored messages
|
||||
func (p *Printer) Printf(format string, a ...interface{}) {
|
||||
func (p *Printer) Printf(format string, a ...any) {
|
||||
doPrintV2(p.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println rendering colored messages with newline
|
||||
func (p *Printer) Println(a ...interface{}) {
|
||||
func (p *Printer) Println(a ...any) {
|
||||
doPrintlnV2(p.Code, a)
|
||||
}
|
||||
|
||||
@@ -77,46 +78,56 @@ func (p *Printer) IsEmpty() bool {
|
||||
type SimplePrinter struct{}
|
||||
|
||||
// Print message
|
||||
func (s *SimplePrinter) Print(v ...interface{}) {
|
||||
func (s *SimplePrinter) Print(v ...any) {
|
||||
Print(v...)
|
||||
}
|
||||
|
||||
// Printf message
|
||||
func (s *SimplePrinter) Printf(format string, v ...interface{}) {
|
||||
func (s *SimplePrinter) Printf(format string, v ...any) {
|
||||
Printf(format, v...)
|
||||
}
|
||||
|
||||
// Println message
|
||||
func (s *SimplePrinter) Println(v ...interface{}) {
|
||||
func (s *SimplePrinter) Println(v ...any) {
|
||||
Println(v...)
|
||||
}
|
||||
|
||||
// Successf message
|
||||
func (s *SimplePrinter) Successf(format string, a ...any) {
|
||||
Success.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Successln message
|
||||
func (s *SimplePrinter) Successln(a ...any) {
|
||||
Success.Println(a...)
|
||||
}
|
||||
|
||||
// Infof message
|
||||
func (s *SimplePrinter) Infof(format string, a ...interface{}) {
|
||||
func (s *SimplePrinter) Infof(format string, a ...any) {
|
||||
Info.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Infoln message
|
||||
func (s *SimplePrinter) Infoln(a ...interface{}) {
|
||||
func (s *SimplePrinter) Infoln(a ...any) {
|
||||
Info.Println(a...)
|
||||
}
|
||||
|
||||
// Warnf message
|
||||
func (s *SimplePrinter) Warnf(format string, a ...interface{}) {
|
||||
func (s *SimplePrinter) Warnf(format string, a ...any) {
|
||||
Warn.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Warnln message
|
||||
func (s *SimplePrinter) Warnln(a ...interface{}) {
|
||||
func (s *SimplePrinter) Warnln(a ...any) {
|
||||
Warn.Println(a...)
|
||||
}
|
||||
|
||||
// Errorf message
|
||||
func (s *SimplePrinter) Errorf(format string, a ...interface{}) {
|
||||
func (s *SimplePrinter) Errorf(format string, a ...any) {
|
||||
Error.Printf(format, a...)
|
||||
}
|
||||
|
||||
// Errorln message
|
||||
func (s *SimplePrinter) Errorln(a ...interface{}) {
|
||||
func (s *SimplePrinter) Errorln(a ...any) {
|
||||
Error.Println(a...)
|
||||
}
|
||||
|
||||
66
vendor/github.com/gookit/color/quickstart.go
generated
vendored
66
vendor/github.com/gookit/color/quickstart.go
generated
vendored
@@ -5,104 +5,104 @@ package color
|
||||
*************************************************************/
|
||||
|
||||
// Redp print message with Red color
|
||||
func Redp(a ...interface{}) { Red.Print(a...) }
|
||||
func Redp(a ...any) { Red.Print(a...) }
|
||||
|
||||
// Redf print message with Red color
|
||||
func Redf(format string, a ...interface{}) { Red.Printf(format, a...) }
|
||||
func Redf(format string, a ...any) { Red.Printf(format, a...) }
|
||||
|
||||
// Redln print message line with Red color
|
||||
func Redln(a ...interface{}) { Red.Println(a...) }
|
||||
func Redln(a ...any) { Red.Println(a...) }
|
||||
|
||||
// Bluep print message with Blue color
|
||||
func Bluep(a ...interface{}) { Blue.Print(a...) }
|
||||
func Bluep(a ...any) { Blue.Print(a...) }
|
||||
|
||||
// Bluef print message with Blue color
|
||||
func Bluef(format string, a ...interface{}) { Blue.Printf(format, a...) }
|
||||
func Bluef(format string, a ...any) { Blue.Printf(format, a...) }
|
||||
|
||||
// Blueln print message line with Blue color
|
||||
func Blueln(a ...interface{}) { Blue.Println(a...) }
|
||||
func Blueln(a ...any) { Blue.Println(a...) }
|
||||
|
||||
// Cyanp print message with Cyan color
|
||||
func Cyanp(a ...interface{}) { Cyan.Print(a...) }
|
||||
func Cyanp(a ...any) { Cyan.Print(a...) }
|
||||
|
||||
// Cyanf print message with Cyan color
|
||||
func Cyanf(format string, a ...interface{}) { Cyan.Printf(format, a...) }
|
||||
func Cyanf(format string, a ...any) { Cyan.Printf(format, a...) }
|
||||
|
||||
// Cyanln print message line with Cyan color
|
||||
func Cyanln(a ...interface{}) { Cyan.Println(a...) }
|
||||
func Cyanln(a ...any) { Cyan.Println(a...) }
|
||||
|
||||
// Grayp print message with Gray color
|
||||
func Grayp(a ...interface{}) { Gray.Print(a...) }
|
||||
func Grayp(a ...any) { Gray.Print(a...) }
|
||||
|
||||
// Grayf print message with Gray color
|
||||
func Grayf(format string, a ...interface{}) { Gray.Printf(format, a...) }
|
||||
func Grayf(format string, a ...any) { Gray.Printf(format, a...) }
|
||||
|
||||
// Grayln print message line with Gray color
|
||||
func Grayln(a ...interface{}) { Gray.Println(a...) }
|
||||
func Grayln(a ...any) { Gray.Println(a...) }
|
||||
|
||||
// Greenp print message with Green color
|
||||
func Greenp(a ...interface{}) { Green.Print(a...) }
|
||||
func Greenp(a ...any) { Green.Print(a...) }
|
||||
|
||||
// Greenf print message with Green color
|
||||
func Greenf(format string, a ...interface{}) { Green.Printf(format, a...) }
|
||||
func Greenf(format string, a ...any) { Green.Printf(format, a...) }
|
||||
|
||||
// Greenln print message line with Green color
|
||||
func Greenln(a ...interface{}) { Green.Println(a...) }
|
||||
func Greenln(a ...any) { Green.Println(a...) }
|
||||
|
||||
// Yellowp print message with Yellow color
|
||||
func Yellowp(a ...interface{}) { Yellow.Print(a...) }
|
||||
func Yellowp(a ...any) { Yellow.Print(a...) }
|
||||
|
||||
// Yellowf print message with Yellow color
|
||||
func Yellowf(format string, a ...interface{}) { Yellow.Printf(format, a...) }
|
||||
func Yellowf(format string, a ...any) { Yellow.Printf(format, a...) }
|
||||
|
||||
// Yellowln print message line with Yellow color
|
||||
func Yellowln(a ...interface{}) { Yellow.Println(a...) }
|
||||
func Yellowln(a ...any) { Yellow.Println(a...) }
|
||||
|
||||
// Magentap print message with Magenta color
|
||||
func Magentap(a ...interface{}) { Magenta.Print(a...) }
|
||||
func Magentap(a ...any) { Magenta.Print(a...) }
|
||||
|
||||
// Magentaf print message with Magenta color
|
||||
func Magentaf(format string, a ...interface{}) { Magenta.Printf(format, a...) }
|
||||
func Magentaf(format string, a ...any) { Magenta.Printf(format, a...) }
|
||||
|
||||
// Magentaln print message line with Magenta color
|
||||
func Magentaln(a ...interface{}) { Magenta.Println(a...) }
|
||||
func Magentaln(a ...any) { Magenta.Println(a...) }
|
||||
|
||||
/*************************************************************
|
||||
* quick use style print message
|
||||
*************************************************************/
|
||||
|
||||
// Infop print message with Info color
|
||||
func Infop(a ...interface{}) { Info.Print(a...) }
|
||||
func Infop(a ...any) { Info.Print(a...) }
|
||||
|
||||
// Infof print message with Info style
|
||||
func Infof(format string, a ...interface{}) { Info.Printf(format, a...) }
|
||||
func Infof(format string, a ...any) { Info.Printf(format, a...) }
|
||||
|
||||
// Infoln print message with Info style
|
||||
func Infoln(a ...interface{}) { Info.Println(a...) }
|
||||
func Infoln(a ...any) { Info.Println(a...) }
|
||||
|
||||
// Successp print message with success color
|
||||
func Successp(a ...interface{}) { Success.Print(a...) }
|
||||
func Successp(a ...any) { Success.Print(a...) }
|
||||
|
||||
// Successf print message with success style
|
||||
func Successf(format string, a ...interface{}) { Success.Printf(format, a...) }
|
||||
func Successf(format string, a ...any) { Success.Printf(format, a...) }
|
||||
|
||||
// Successln print message with success style
|
||||
func Successln(a ...interface{}) { Success.Println(a...) }
|
||||
func Successln(a ...any) { Success.Println(a...) }
|
||||
|
||||
// Errorp print message with Error color
|
||||
func Errorp(a ...interface{}) { Error.Print(a...) }
|
||||
func Errorp(a ...any) { Error.Print(a...) }
|
||||
|
||||
// Errorf print message with Error style
|
||||
func Errorf(format string, a ...interface{}) { Error.Printf(format, a...) }
|
||||
func Errorf(format string, a ...any) { Error.Printf(format, a...) }
|
||||
|
||||
// Errorln print message with Error style
|
||||
func Errorln(a ...interface{}) { Error.Println(a...) }
|
||||
func Errorln(a ...any) { Error.Println(a...) }
|
||||
|
||||
// Warnp print message with Warn color
|
||||
func Warnp(a ...interface{}) { Warn.Print(a...) }
|
||||
func Warnp(a ...any) { Warn.Print(a...) }
|
||||
|
||||
// Warnf print message with Warn style
|
||||
func Warnf(format string, a ...interface{}) { Warn.Printf(format, a...) }
|
||||
func Warnf(format string, a ...any) { Warn.Printf(format, a...) }
|
||||
|
||||
// Warnln print message with Warn style
|
||||
func Warnln(a ...interface{}) { Warn.Println(a...) }
|
||||
func Warnln(a ...any) { Warn.Println(a...) }
|
||||
|
||||
67
vendor/github.com/gookit/color/style.go
generated
vendored
67
vendor/github.com/gookit/color/style.go
generated
vendored
@@ -12,12 +12,14 @@ import (
|
||||
// Style a 16 color style. can add: fg color, bg color, color options
|
||||
//
|
||||
// Example:
|
||||
// color.Style{color.FgGreen}.Print("message")
|
||||
//
|
||||
// color.Style{color.FgGreen}.Print("message")
|
||||
type Style []Color
|
||||
|
||||
// New create a custom style
|
||||
//
|
||||
// Usage:
|
||||
//
|
||||
// color.New(color.FgGreen).Print("message")
|
||||
// equals to:
|
||||
// color.Style{color.FgGreen}.Print("message")
|
||||
@@ -35,45 +37,49 @@ func (s *Style) Add(cs ...Color) {
|
||||
*s = append(*s, cs...)
|
||||
}
|
||||
|
||||
// Render render text
|
||||
// Render colored text
|
||||
//
|
||||
// Usage:
|
||||
// color.New(color.FgGreen).Render("text")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text")
|
||||
func (s Style) Render(a ...interface{}) string {
|
||||
//
|
||||
// color.New(color.FgGreen).Render("text")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text")
|
||||
func (s Style) Render(a ...any) string {
|
||||
return RenderCode(s.String(), a...)
|
||||
}
|
||||
|
||||
// Renderln render text line.
|
||||
// Renderln render text with newline.
|
||||
// like Println, will add spaces for each argument
|
||||
//
|
||||
// Usage:
|
||||
// color.New(color.FgGreen).Renderln("text", "more")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more")
|
||||
func (s Style) Renderln(a ...interface{}) string {
|
||||
//
|
||||
// color.New(color.FgGreen).Renderln("text", "more")
|
||||
// color.New(color.FgGreen, color.BgBlack, color.OpBold).Render("text", "more")
|
||||
func (s Style) Renderln(a ...any) string {
|
||||
return RenderWithSpaces(s.String(), a...)
|
||||
}
|
||||
|
||||
// Sprint is alias of the 'Render'
|
||||
func (s Style) Sprint(a ...interface{}) string {
|
||||
func (s Style) Sprint(a ...any) string {
|
||||
return RenderCode(s.String(), a...)
|
||||
}
|
||||
|
||||
// Sprintf format and render message.
|
||||
func (s Style) Sprintf(format string, a ...interface{}) string {
|
||||
func (s Style) Sprintf(format string, a ...any) string {
|
||||
return RenderString(s.String(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Print render and Print text
|
||||
func (s Style) Print(a ...interface{}) {
|
||||
func (s Style) Print(a ...any) {
|
||||
doPrintV2(s.String(), fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Printf render and print text
|
||||
func (s Style) Printf(format string, a ...interface{}) {
|
||||
func (s Style) Printf(format string, a ...any) {
|
||||
doPrintV2(s.Code(), fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Println render and print text line
|
||||
func (s Style) Println(a ...interface{}) {
|
||||
func (s Style) Println(a ...any) {
|
||||
doPrintlnV2(s.String(), a)
|
||||
}
|
||||
|
||||
@@ -115,20 +121,20 @@ func (t *Theme) Save() {
|
||||
}
|
||||
|
||||
// Tips use name as title, only apply style for name
|
||||
func (t *Theme) Tips(format string, a ...interface{}) {
|
||||
func (t *Theme) Tips(format string, a ...any) {
|
||||
// only apply style for name
|
||||
t.Print(strings.ToUpper(t.Name) + ": ")
|
||||
Printf(format+"\n", a...)
|
||||
}
|
||||
|
||||
// Prompt use name as title, and apply style for message
|
||||
func (t *Theme) Prompt(format string, a ...interface{}) {
|
||||
func (t *Theme) Prompt(format string, a ...any) {
|
||||
title := strings.ToUpper(t.Name) + ":"
|
||||
t.Println(title, fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// Block like Prompt, but will wrap a empty line
|
||||
func (t *Theme) Block(format string, a ...interface{}) {
|
||||
func (t *Theme) Block(format string, a ...any) {
|
||||
title := strings.ToUpper(t.Name) + ":\n"
|
||||
|
||||
t.Println(title, fmt.Sprintf(format, a...))
|
||||
@@ -140,10 +146,11 @@ func (t *Theme) Block(format string, a ...interface{}) {
|
||||
|
||||
// internal themes(like bootstrap style)
|
||||
// Usage:
|
||||
// color.Info.Print("message")
|
||||
// color.Info.Printf("a %s message", "test")
|
||||
// color.Warn.Println("message")
|
||||
// color.Error.Println("message")
|
||||
//
|
||||
// color.Info.Print("message")
|
||||
// color.Info.Printf("a %s message", "test")
|
||||
// color.Warn.Println("message")
|
||||
// color.Error.Println("message")
|
||||
var (
|
||||
// Info color style
|
||||
Info = &Theme{"info", Style{OpReset, FgGreen}}
|
||||
@@ -175,7 +182,8 @@ var (
|
||||
|
||||
// Themes internal defined themes.
|
||||
// Usage:
|
||||
// color.Themes["info"].Println("message")
|
||||
//
|
||||
// color.Themes["info"].Println("message")
|
||||
var Themes = map[string]*Theme{
|
||||
"info": Info,
|
||||
"note": Note,
|
||||
@@ -211,7 +219,8 @@ func GetTheme(name string) *Theme {
|
||||
|
||||
// Styles internal defined styles, like bootstrap styles.
|
||||
// Usage:
|
||||
// color.Styles["info"].Println("message")
|
||||
//
|
||||
// color.Styles["info"].Println("message")
|
||||
var Styles = map[string]Style{
|
||||
"info": {OpReset, FgGreen},
|
||||
"note": {OpBold, FgLightCyan},
|
||||
@@ -285,31 +294,31 @@ func (s *Scheme) Style(name string) Style {
|
||||
}
|
||||
|
||||
// Infof message print
|
||||
func (s *Scheme) Infof(format string, a ...interface{}) {
|
||||
func (s *Scheme) Infof(format string, a ...any) {
|
||||
s.Styles["info"].Printf(format, a...)
|
||||
}
|
||||
|
||||
// Infoln message print
|
||||
func (s *Scheme) Infoln(v ...interface{}) {
|
||||
func (s *Scheme) Infoln(v ...any) {
|
||||
s.Styles["info"].Println(v...)
|
||||
}
|
||||
|
||||
// Warnf message print
|
||||
func (s *Scheme) Warnf(format string, a ...interface{}) {
|
||||
func (s *Scheme) Warnf(format string, a ...any) {
|
||||
s.Styles["warn"].Printf(format, a...)
|
||||
}
|
||||
|
||||
// Warnln message print
|
||||
func (s *Scheme) Warnln(v ...interface{}) {
|
||||
func (s *Scheme) Warnln(v ...any) {
|
||||
s.Styles["warn"].Println(v...)
|
||||
}
|
||||
|
||||
// Errorf message print
|
||||
func (s *Scheme) Errorf(format string, a ...interface{}) {
|
||||
func (s *Scheme) Errorf(format string, a ...any) {
|
||||
s.Styles["error"].Printf(format, a...)
|
||||
}
|
||||
|
||||
// Errorln message print
|
||||
func (s *Scheme) Errorln(v ...interface{}) {
|
||||
func (s *Scheme) Errorln(v ...any) {
|
||||
s.Styles["error"].Println(v...)
|
||||
}
|
||||
|
||||
51
vendor/github.com/gookit/color/utils.go
generated
vendored
51
vendor/github.com/gookit/color/utils.go
generated
vendored
@@ -32,39 +32,31 @@ func ResetTerminal() error {
|
||||
*************************************************************/
|
||||
|
||||
// Print render color tag and print messages
|
||||
func Print(a ...interface{}) {
|
||||
func Print(a ...any) {
|
||||
Fprint(output, a...)
|
||||
}
|
||||
|
||||
// Printf format and print messages
|
||||
func Printf(format string, a ...interface{}) {
|
||||
func Printf(format string, a ...any) {
|
||||
Fprintf(output, format, a...)
|
||||
}
|
||||
|
||||
// Println messages with new line
|
||||
func Println(a ...interface{}) {
|
||||
func Println(a ...any) {
|
||||
Fprintln(output, a...)
|
||||
}
|
||||
|
||||
// Fprint print rendered messages to writer
|
||||
//
|
||||
// Notice: will ignore print error
|
||||
func Fprint(w io.Writer, a ...interface{}) {
|
||||
func Fprint(w io.Writer, a ...any) {
|
||||
_, err := fmt.Fprint(w, Render(a...))
|
||||
saveInternalError(err)
|
||||
|
||||
// if isLikeInCmd {
|
||||
// renderColorCodeOnCmd(func() {
|
||||
// _, _ = fmt.Fprint(w, Render(a...))
|
||||
// })
|
||||
// } else {
|
||||
// _, _ = fmt.Fprint(w, Render(a...))
|
||||
// }
|
||||
}
|
||||
|
||||
// Fprintf print format and rendered messages to writer.
|
||||
// Notice: will ignore print error
|
||||
func Fprintf(w io.Writer, format string, a ...interface{}) {
|
||||
func Fprintf(w io.Writer, format string, a ...any) {
|
||||
str := fmt.Sprintf(format, a...)
|
||||
_, err := fmt.Fprint(w, ReplaceTag(str))
|
||||
saveInternalError(err)
|
||||
@@ -72,7 +64,7 @@ func Fprintf(w io.Writer, format string, a ...interface{}) {
|
||||
|
||||
// Fprintln print rendered messages line to writer
|
||||
// Notice: will ignore print error
|
||||
func Fprintln(w io.Writer, a ...interface{}) {
|
||||
func Fprintln(w io.Writer, a ...any) {
|
||||
str := formatArgsForPrintln(a)
|
||||
_, err := fmt.Fprintln(w, ReplaceTag(str))
|
||||
saveInternalError(err)
|
||||
@@ -80,7 +72,7 @@ func Fprintln(w io.Writer, a ...interface{}) {
|
||||
|
||||
// Lprint passes colored messages to a log.Logger for printing.
|
||||
// Notice: should be goroutine safe
|
||||
func Lprint(l *log.Logger, a ...interface{}) {
|
||||
func Lprint(l *log.Logger, a ...any) {
|
||||
l.Print(Render(a...))
|
||||
}
|
||||
|
||||
@@ -90,7 +82,7 @@ func Lprint(l *log.Logger, a ...interface{}) {
|
||||
//
|
||||
// text := Render("<info>hello</> <cyan>world</>!")
|
||||
// fmt.Println(text)
|
||||
func Render(a ...interface{}) string {
|
||||
func Render(a ...any) string {
|
||||
if len(a) == 0 {
|
||||
return ""
|
||||
}
|
||||
@@ -98,28 +90,23 @@ func Render(a ...interface{}) string {
|
||||
}
|
||||
|
||||
// Sprint parse color tags, return rendered string
|
||||
func Sprint(a ...interface{}) string {
|
||||
func Sprint(a ...any) string {
|
||||
if len(a) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return ReplaceTag(fmt.Sprint(a...))
|
||||
}
|
||||
|
||||
// Sprintf format and return rendered string
|
||||
func Sprintf(format string, a ...interface{}) string {
|
||||
func Sprintf(format string, a ...any) string {
|
||||
return ReplaceTag(fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// String alias of the ReplaceTag
|
||||
func String(s string) string {
|
||||
return ReplaceTag(s)
|
||||
}
|
||||
func String(s string) string { return ReplaceTag(s) }
|
||||
|
||||
// Text alias of the ReplaceTag
|
||||
func Text(s string) string {
|
||||
return ReplaceTag(s)
|
||||
}
|
||||
func Text(s string) string { return ReplaceTag(s) }
|
||||
|
||||
// Uint8sToInts convert []uint8 to []int
|
||||
// func Uint8sToInts(u8s []uint8 ) []int {
|
||||
@@ -138,25 +125,17 @@ func Text(s string) string {
|
||||
func doPrintV2(code, str string) {
|
||||
_, err := fmt.Fprint(output, RenderString(code, str))
|
||||
saveInternalError(err)
|
||||
|
||||
// if isLikeInCmd {
|
||||
// renderColorCodeOnCmd(func() {
|
||||
// _, _ = fmt.Fprint(output, RenderString(code, str))
|
||||
// })
|
||||
// } else {
|
||||
// _, _ = fmt.Fprint(output, RenderString(code, str))
|
||||
// }
|
||||
}
|
||||
|
||||
// new implementation, support render full color code on pwsh.exe, cmd.exe
|
||||
func doPrintlnV2(code string, args []interface{}) {
|
||||
func doPrintlnV2(code string, args []any) {
|
||||
str := formatArgsForPrintln(args)
|
||||
_, err := fmt.Fprintln(output, RenderString(code, str))
|
||||
saveInternalError(err)
|
||||
}
|
||||
|
||||
// use Println, will add spaces for each arg
|
||||
func formatArgsForPrintln(args []interface{}) (message string) {
|
||||
func formatArgsForPrintln(args []any) (message string) {
|
||||
if ln := len(args); ln == 0 {
|
||||
message = ""
|
||||
} else if ln == 1 {
|
||||
@@ -178,7 +157,7 @@ func formatArgsForPrintln(args []interface{}) (message string) {
|
||||
// return debugMode == "on"
|
||||
// }
|
||||
|
||||
func debugf(f string, v ...interface{}) {
|
||||
func debugf(f string, v ...any) {
|
||||
if debugMode {
|
||||
fmt.Print("COLOR_DEBUG: ")
|
||||
fmt.Printf(f, v...)
|
||||
|
||||
2
vendor/github.com/nbutton23/zxcvbn-go/.gitignore
generated
vendored
2
vendor/github.com/nbutton23/zxcvbn-go/.gitignore
generated
vendored
@@ -1,2 +0,0 @@
|
||||
zxcvbn
|
||||
debug.test
|
||||
15
vendor/github.com/nbutton23/zxcvbn-go/Makefile
generated
vendored
15
vendor/github.com/nbutton23/zxcvbn-go/Makefile
generated
vendored
@@ -1,15 +0,0 @@
|
||||
PKG_LIST = $$( go list ./... | grep -v /vendor/ | grep -v "zxcvbn-go/data" )
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: help
|
||||
help:
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: test
|
||||
test: ## Run `go test {Package list}` on the packages
|
||||
go test $(PKG_LIST)
|
||||
|
||||
.PHONY: lint
|
||||
lint: ## Run `golint {Package list}`
|
||||
golint $(PKG_LIST)
|
||||
19
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
19
vendor/github.com/onsi/gomega/CHANGELOG.md
generated
vendored
@@ -1,3 +1,22 @@
|
||||
## 1.27.10
|
||||
|
||||
### Fixes
|
||||
- fix: go 1.21 adding goroutine ID to creator+location (#685) [bdc7803]
|
||||
|
||||
## 1.27.9
|
||||
|
||||
### Fixes
|
||||
- Prevent nil-dereference in format.Object for boxed nil error (#681) [3b31fc3]
|
||||
|
||||
### Maintenance
|
||||
- Bump golang.org/x/net from 0.11.0 to 0.12.0 (#679) [360849b]
|
||||
- chore: use String() instead of fmt.Sprintf (#678) [86f3659]
|
||||
- Bump golang.org/x/net from 0.10.0 to 0.11.0 (#674) [642ead0]
|
||||
- chore: unnecessary use of fmt.Sprintf (#677) [ceb9ca6]
|
||||
- Bump github.com/onsi/ginkgo/v2 from 2.10.0 to 2.11.0 (#675) [a2087d8]
|
||||
- docs: fix ContainSubstring references (#673) [fc9a89f]
|
||||
- Bump github.com/onsi/ginkgo/v2 from 2.9.7 to 2.10.0 (#671) [9076019]
|
||||
|
||||
## 1.27.8
|
||||
|
||||
### Fixes
|
||||
|
||||
4
vendor/github.com/onsi/gomega/format/format.go
generated
vendored
4
vendor/github.com/onsi/gomega/format/format.go
generated
vendored
@@ -259,7 +259,7 @@ func Object(object interface{}, indentation uint) string {
|
||||
indent := strings.Repeat(Indent, int(indentation))
|
||||
value := reflect.ValueOf(object)
|
||||
commonRepresentation := ""
|
||||
if err, ok := object.(error); ok {
|
||||
if err, ok := object.(error); ok && !isNilValue(value) { // isNilValue check needed here to avoid nil deref due to boxed nil
|
||||
commonRepresentation += "\n" + IndentString(err.Error(), indentation) + "\n" + indent
|
||||
}
|
||||
return fmt.Sprintf("%s<%s>: %s%s", indent, formatType(value), commonRepresentation, formatValue(value, indentation))
|
||||
@@ -302,7 +302,7 @@ func formatType(v reflect.Value) string {
|
||||
case reflect.Map:
|
||||
return fmt.Sprintf("%s | len:%d", v.Type(), v.Len())
|
||||
default:
|
||||
return fmt.Sprintf("%s", v.Type())
|
||||
return v.Type().String()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
2
vendor/github.com/onsi/gomega/gomega_dsl.go
generated
vendored
@@ -22,7 +22,7 @@ import (
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
const GOMEGA_VERSION = "1.27.8"
|
||||
const GOMEGA_VERSION = "1.27.10"
|
||||
|
||||
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
||||
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
||||
|
||||
6
vendor/github.com/onsi/gomega/matchers.go
generated
vendored
6
vendor/github.com/onsi/gomega/matchers.go
generated
vendored
@@ -92,9 +92,9 @@ func Succeed() types.GomegaMatcher {
|
||||
//
|
||||
// These are valid use-cases:
|
||||
//
|
||||
// Expect(err).Should(MatchError("an error")) //asserts that err.Error() == "an error"
|
||||
// Expect(err).Should(MatchError(SomeError)) //asserts that err == SomeError (via reflect.DeepEqual)
|
||||
// Expect(err).Should(MatchError(ContainsSubstring("sprocket not found"))) // asserts that edrr.Error() contains substring "sprocket not found"
|
||||
// Expect(err).Should(MatchError("an error")) //asserts that err.Error() == "an error"
|
||||
// Expect(err).Should(MatchError(SomeError)) //asserts that err == SomeError (via reflect.DeepEqual)
|
||||
// Expect(err).Should(MatchError(ContainSubstring("sprocket not found"))) // asserts that edrr.Error() contains substring "sprocket not found"
|
||||
//
|
||||
// It is an error for err to be nil or an object that does not implement the
|
||||
// Error interface
|
||||
|
||||
2
vendor/github.com/onsi/gomega/matchers/be_a_directory.go
generated
vendored
2
vendor/github.com/onsi/gomega/matchers/be_a_directory.go
generated
vendored
@@ -52,5 +52,5 @@ func (matcher *BeADirectoryMatcher) FailureMessage(actual interface{}) (message
|
||||
}
|
||||
|
||||
func (matcher *BeADirectoryMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not be a directory"))
|
||||
return format.Message(actual, "not be a directory")
|
||||
}
|
||||
|
||||
2
vendor/github.com/onsi/gomega/matchers/be_a_regular_file.go
generated
vendored
2
vendor/github.com/onsi/gomega/matchers/be_a_regular_file.go
generated
vendored
@@ -52,5 +52,5 @@ func (matcher *BeARegularFileMatcher) FailureMessage(actual interface{}) (messag
|
||||
}
|
||||
|
||||
func (matcher *BeARegularFileMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not be a regular file"))
|
||||
return format.Message(actual, "not be a regular file")
|
||||
}
|
||||
|
||||
4
vendor/github.com/onsi/gomega/matchers/be_an_existing_file.go
generated
vendored
4
vendor/github.com/onsi/gomega/matchers/be_an_existing_file.go
generated
vendored
@@ -32,9 +32,9 @@ func (matcher *BeAnExistingFileMatcher) Match(actual interface{}) (success bool,
|
||||
}
|
||||
|
||||
func (matcher *BeAnExistingFileMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("to exist"))
|
||||
return format.Message(actual, "to exist")
|
||||
}
|
||||
|
||||
func (matcher *BeAnExistingFileMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, fmt.Sprintf("not to exist"))
|
||||
return format.Message(actual, "not to exist")
|
||||
}
|
||||
|
||||
69
vendor/github.com/securego/gosec/v2/.golangci.yml
generated
vendored
69
vendor/github.com/securego/gosec/v2/.golangci.yml
generated
vendored
@@ -1,33 +1,40 @@
|
||||
linters:
|
||||
enable:
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- deadcode
|
||||
- depguard
|
||||
- dogsled
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errorlint
|
||||
- exportloopref
|
||||
- gci
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- importas
|
||||
- ineffassign
|
||||
- megacheck
|
||||
- misspell
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- structcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- varcheck
|
||||
- wastedassign
|
||||
- asciicheck
|
||||
- bodyclose
|
||||
- dogsled
|
||||
- durationcheck
|
||||
- errcheck
|
||||
- errorlint
|
||||
- exportloopref
|
||||
- gci
|
||||
- ginkgolinter
|
||||
- gofmt
|
||||
- gofumpt
|
||||
- goimports
|
||||
- gosec
|
||||
- gosimple
|
||||
- govet
|
||||
- importas
|
||||
- ineffassign
|
||||
- megacheck
|
||||
- misspell
|
||||
- nakedret
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
- unparam
|
||||
- unused
|
||||
- wastedassign
|
||||
|
||||
linters-settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- default
|
||||
- prefix(github.com/securego)
|
||||
|
||||
run:
|
||||
timeout: 5m
|
||||
|
||||
7
vendor/github.com/securego/gosec/v2/.goreleaser.yml
generated
vendored
7
vendor/github.com/securego/gosec/v2/.goreleaser.yml
generated
vendored
@@ -26,6 +26,11 @@ builds:
|
||||
signs:
|
||||
- cmd: cosign
|
||||
stdin: '{{ .Env.COSIGN_PASSWORD}}'
|
||||
args: ["sign-blob", "--key=/tmp/cosign.key", "--output=${signature}", "${artifact}"]
|
||||
args:
|
||||
- "sign-blob"
|
||||
- "--key=/tmp/cosign.key"
|
||||
- "--output=${signature}"
|
||||
- "${artifact}"
|
||||
- "--yes"
|
||||
artifacts: all
|
||||
|
||||
|
||||
8
vendor/github.com/securego/gosec/v2/Dockerfile
generated
vendored
8
vendor/github.com/securego/gosec/v2/Dockerfile
generated
vendored
@@ -1,11 +1,11 @@
|
||||
ARG GO_VERSION
|
||||
FROM golang:${GO_VERSION}-alpine AS builder
|
||||
RUN apk add --no-cache ca-certificates make git curl gcc libc-dev
|
||||
RUN mkdir -p /build
|
||||
RUN apk add --no-cache ca-certificates make git curl gcc libc-dev \
|
||||
&& mkdir -p /build
|
||||
WORKDIR /build
|
||||
COPY . /build/
|
||||
RUN go mod download
|
||||
RUN make build-linux
|
||||
RUN go mod download \
|
||||
&& make build-linux
|
||||
|
||||
FROM golang:${GO_VERSION}-alpine
|
||||
RUN apk add --no-cache ca-certificates bash git gcc libc-dev openssh
|
||||
|
||||
5
vendor/github.com/securego/gosec/v2/Makefile
generated
vendored
5
vendor/github.com/securego/gosec/v2/Makefile
generated
vendored
@@ -87,4 +87,7 @@ image-push: image
|
||||
docker push $(IMAGE_REPO)/$(BIN):$(GIT_TAG)
|
||||
docker push $(IMAGE_REPO)/$(BIN):latest
|
||||
|
||||
.PHONY: test build clean release image image-push
|
||||
tlsconfig:
|
||||
go generate ./...
|
||||
|
||||
.PHONY: test build clean release image image-push tlsconfig
|
||||
|
||||
9
vendor/github.com/securego/gosec/v2/README.md
generated
vendored
9
vendor/github.com/securego/gosec/v2/README.md
generated
vendored
@@ -68,7 +68,7 @@ jobs:
|
||||
GO111MODULE: on
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Run Gosec Security Scanner
|
||||
uses: securego/gosec@master
|
||||
with:
|
||||
@@ -98,7 +98,7 @@ jobs:
|
||||
GO111MODULE: on
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
- name: Run Gosec Security Scanner
|
||||
uses: securego/gosec@master
|
||||
with:
|
||||
@@ -157,7 +157,6 @@ directory you can supply `./...` as the input argument.
|
||||
- G304: File path provided as taint input
|
||||
- G305: File traversal when extracting zip/tar archive
|
||||
- G306: Poor file permissions used when writing to a new file
|
||||
- G307: Deferring a method which returns an error
|
||||
- G401: Detect the usage of DES, RC4, MD5 or SHA1
|
||||
- G402: Look for bad TLS connection settings
|
||||
- G403: Ensure minimum RSA key length of 2048 bits
|
||||
@@ -168,10 +167,12 @@ directory you can supply `./...` as the input argument.
|
||||
- G504: Import blocklist: net/http/cgi
|
||||
- G505: Import blocklist: crypto/sha1
|
||||
- G601: Implicit memory aliasing of items from a range statement
|
||||
- G602: Slice access out of bounds
|
||||
|
||||
### Retired rules
|
||||
|
||||
- G105: Audit the use of math/big.Int.Exp - [CVE is fixed](https://github.com/golang/go/issues/15184)
|
||||
- G307: Deferring a method which returns an error - causing more inconvenience than fixing a security issue, despite the details from this [blog post](https://www.joeshaw.org/dont-defer-close-on-writable-files/)
|
||||
|
||||
### Selecting rules
|
||||
|
||||
@@ -188,7 +189,7 @@ $ gosec -exclude=G303 ./...
|
||||
|
||||
### CWE Mapping
|
||||
|
||||
Every issue detected by `gosec` is mapped to a [CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html) which describes in more generic terms the vulnerability. The exact mapping can be found [here](https://github.com/securego/gosec/blob/master/issue.go#L50).
|
||||
Every issue detected by `gosec` is mapped to a [CWE (Common Weakness Enumeration)](http://cwe.mitre.org/data/index.html) which describes in more generic terms the vulnerability. The exact mapping can be found [here](https://github.com/securego/gosec/blob/master/issue/issue.go#L50).
|
||||
|
||||
### Configuration
|
||||
|
||||
|
||||
2
vendor/github.com/securego/gosec/v2/action.yml
generated
vendored
2
vendor/github.com/securego/gosec/v2/action.yml
generated
vendored
@@ -10,7 +10,7 @@ inputs:
|
||||
|
||||
runs:
|
||||
using: 'docker'
|
||||
image: 'docker://securego/gosec'
|
||||
image: 'docker://securego/gosec:2.16.0'
|
||||
args:
|
||||
- ${{ inputs.args }}
|
||||
|
||||
|
||||
232
vendor/github.com/securego/gosec/v2/analyzer.go
generated
vendored
232
vendor/github.com/securego/gosec/v2/analyzer.go
generated
vendored
@@ -31,6 +31,10 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/securego/gosec/v2/analyzers"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
@@ -42,7 +46,10 @@ const LoadMode = packages.NeedName |
|
||||
packages.NeedTypes |
|
||||
packages.NeedTypesSizes |
|
||||
packages.NeedTypesInfo |
|
||||
packages.NeedSyntax
|
||||
packages.NeedSyntax |
|
||||
packages.NeedModule |
|
||||
packages.NeedEmbedFiles |
|
||||
packages.NeedEmbedPatterns
|
||||
|
||||
const externalSuppressionJustification = "Globally suppressed."
|
||||
|
||||
@@ -52,7 +59,7 @@ var generatedCodePattern = regexp.MustCompile(`^// Code generated .* DO NOT EDIT
|
||||
|
||||
// The Context is populated with data parsed from the source code as it is scanned.
|
||||
// It is passed through to all rule functions as they are called. Rules may use
|
||||
// this data in conjunction withe the encountered AST node.
|
||||
// this data in conjunction with the encountered AST node.
|
||||
type Context struct {
|
||||
FileSet *token.FileSet
|
||||
Comments ast.CommentMap
|
||||
@@ -60,12 +67,24 @@ type Context struct {
|
||||
Pkg *types.Package
|
||||
PkgFiles []*ast.File
|
||||
Root *ast.File
|
||||
Config Config
|
||||
Imports *ImportTracker
|
||||
Ignores []map[string][]SuppressionInfo
|
||||
Config Config
|
||||
Ignores []map[string][]issue.SuppressionInfo
|
||||
PassedValues map[string]interface{}
|
||||
}
|
||||
|
||||
// GetFileAtNodePos returns the file at the node position in the file set available in the context.
|
||||
func (ctx *Context) GetFileAtNodePos(node ast.Node) *token.File {
|
||||
return ctx.FileSet.File(node.Pos())
|
||||
}
|
||||
|
||||
// NewIssue creates a new issue
|
||||
func (ctx *Context) NewIssue(node ast.Node, ruleID, desc string,
|
||||
severity, confidence issue.Score,
|
||||
) *issue.Issue {
|
||||
return issue.New(ctx.GetFileAtNodePos(node), node, ruleID, desc, severity, confidence)
|
||||
}
|
||||
|
||||
// Metrics used when reporting information about a scanning run.
|
||||
type Metrics struct {
|
||||
NumFiles int `json:"files"`
|
||||
@@ -82,7 +101,7 @@ type Analyzer struct {
|
||||
context *Context
|
||||
config Config
|
||||
logger *log.Logger
|
||||
issues []*Issue
|
||||
issues []*issue.Issue
|
||||
stats *Metrics
|
||||
errors map[string][]Error // keys are file paths; values are the golang errors in those files
|
||||
tests bool
|
||||
@@ -90,13 +109,7 @@ type Analyzer struct {
|
||||
showIgnored bool
|
||||
trackSuppressions bool
|
||||
concurrency int
|
||||
}
|
||||
|
||||
// SuppressionInfo object is to record the kind and the justification that used
|
||||
// to suppress violations.
|
||||
type SuppressionInfo struct {
|
||||
Kind string `json:"kind"`
|
||||
Justification string `json:"justification"`
|
||||
analyzerList []*analysis.Analyzer
|
||||
}
|
||||
|
||||
// NewAnalyzer builds a new analyzer.
|
||||
@@ -119,13 +132,14 @@ func NewAnalyzer(conf Config, tests bool, excludeGenerated bool, trackSuppressio
|
||||
context: &Context{},
|
||||
config: conf,
|
||||
logger: logger,
|
||||
issues: make([]*Issue, 0, 16),
|
||||
issues: make([]*issue.Issue, 0, 16),
|
||||
stats: &Metrics{},
|
||||
errors: make(map[string][]Error),
|
||||
tests: tests,
|
||||
concurrency: concurrency,
|
||||
excludeGenerated: excludeGenerated,
|
||||
trackSuppressions: trackSuppressions,
|
||||
analyzerList: analyzers.BuildDefaultAnalyzers(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +230,10 @@ func (gosec *Analyzer) Process(buildTags []string, packagePaths ...string) error
|
||||
wg.Wait() // wait for the goroutines to stop
|
||||
return fmt.Errorf("parsing errors in pkg %q: %w", pkg.Name, err)
|
||||
}
|
||||
gosec.Check(pkg)
|
||||
gosec.CheckRules(pkg)
|
||||
if on, err := gosec.config.IsGlobalEnabled(SSA); err == nil && on {
|
||||
gosec.CheckAnalyzers(pkg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,8 +284,8 @@ func (gosec *Analyzer) load(pkgPath string, conf *packages.Config) ([]*packages.
|
||||
return pkgs, nil
|
||||
}
|
||||
|
||||
// Check runs analysis on the given package
|
||||
func (gosec *Analyzer) Check(pkg *packages.Package) {
|
||||
// CheckRules runs analysis on the given package
|
||||
func (gosec *Analyzer) CheckRules(pkg *packages.Package) {
|
||||
gosec.logger.Println("Checking package:", pkg.Name)
|
||||
for _, file := range pkg.Syntax {
|
||||
fp := pkg.Fset.File(file.Pos())
|
||||
@@ -303,6 +320,70 @@ func (gosec *Analyzer) Check(pkg *packages.Package) {
|
||||
}
|
||||
}
|
||||
|
||||
// CheckAnalyzers runs analyzers on a given package
|
||||
func (gosec *Analyzer) CheckAnalyzers(pkg *packages.Package) {
|
||||
ssaPass := &analysis.Pass{
|
||||
Analyzer: buildssa.Analyzer,
|
||||
Fset: pkg.Fset,
|
||||
Files: pkg.Syntax,
|
||||
OtherFiles: pkg.OtherFiles,
|
||||
IgnoredFiles: pkg.IgnoredFiles,
|
||||
Pkg: pkg.Types,
|
||||
TypesInfo: pkg.TypesInfo,
|
||||
TypesSizes: pkg.TypesSizes,
|
||||
ResultOf: nil,
|
||||
Report: nil,
|
||||
ImportObjectFact: nil,
|
||||
ExportObjectFact: nil,
|
||||
ImportPackageFact: nil,
|
||||
ExportPackageFact: nil,
|
||||
AllObjectFacts: nil,
|
||||
AllPackageFacts: nil,
|
||||
}
|
||||
ssaResult, err := ssaPass.Analyzer.Run(ssaPass)
|
||||
if err != nil {
|
||||
gosec.logger.Printf("Error running SSA analyser on package %q: %s", pkg.Name, err)
|
||||
return
|
||||
}
|
||||
resultMap := map[*analysis.Analyzer]interface{}{
|
||||
buildssa.Analyzer: &analyzers.SSAAnalyzerResult{
|
||||
Config: gosec.Config(),
|
||||
Logger: gosec.logger,
|
||||
SSA: ssaResult.(*buildssa.SSA),
|
||||
},
|
||||
}
|
||||
for _, analyzer := range gosec.analyzerList {
|
||||
pass := &analysis.Pass{
|
||||
Analyzer: analyzer,
|
||||
Fset: pkg.Fset,
|
||||
Files: pkg.Syntax,
|
||||
OtherFiles: pkg.OtherFiles,
|
||||
IgnoredFiles: pkg.IgnoredFiles,
|
||||
Pkg: pkg.Types,
|
||||
TypesInfo: pkg.TypesInfo,
|
||||
TypesSizes: pkg.TypesSizes,
|
||||
ResultOf: resultMap,
|
||||
Report: func(d analysis.Diagnostic) {},
|
||||
ImportObjectFact: nil,
|
||||
ExportObjectFact: nil,
|
||||
ImportPackageFact: nil,
|
||||
ExportPackageFact: nil,
|
||||
AllObjectFacts: nil,
|
||||
AllPackageFacts: nil,
|
||||
}
|
||||
result, err := pass.Analyzer.Run(pass)
|
||||
if err != nil {
|
||||
gosec.logger.Printf("Error running analyzer %s: %s\n", analyzer.Name, err)
|
||||
continue
|
||||
}
|
||||
if result != nil {
|
||||
if aissue, ok := result.(*issue.Issue); ok {
|
||||
gosec.updateIssues(aissue, false, []issue.SuppressionInfo{})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isGeneratedFile(file *ast.File) bool {
|
||||
for _, comment := range file.Comments {
|
||||
for _, row := range comment.List {
|
||||
@@ -364,14 +445,16 @@ func (gosec *Analyzer) AppendError(file string, err error) {
|
||||
}
|
||||
|
||||
// ignore a node (and sub-tree) if it is tagged with a nosec tag comment
|
||||
func (gosec *Analyzer) ignore(n ast.Node) map[string]SuppressionInfo {
|
||||
func (gosec *Analyzer) ignore(n ast.Node) map[string]issue.SuppressionInfo {
|
||||
if groups, ok := gosec.context.Comments[n]; ok && !gosec.ignoreNosec {
|
||||
|
||||
// Checks if an alternative for #nosec is set and, if not, uses the default.
|
||||
noSecDefaultTag := "#nosec"
|
||||
noSecDefaultTag := NoSecTag(string(Nosec))
|
||||
noSecAlternativeTag, err := gosec.config.GetGlobal(NoSecAlternative)
|
||||
if err != nil {
|
||||
noSecAlternativeTag = noSecDefaultTag
|
||||
} else {
|
||||
noSecAlternativeTag = NoSecTag(noSecAlternativeTag)
|
||||
}
|
||||
|
||||
for _, group := range groups {
|
||||
@@ -401,13 +484,13 @@ func (gosec *Analyzer) ignore(n ast.Node) map[string]SuppressionInfo {
|
||||
re := regexp.MustCompile(`(G\d{3})`)
|
||||
matches := re.FindAllStringSubmatch(directive, -1)
|
||||
|
||||
suppression := SuppressionInfo{
|
||||
suppression := issue.SuppressionInfo{
|
||||
Kind: "inSource",
|
||||
Justification: justification,
|
||||
}
|
||||
|
||||
// Find the rule IDs to ignore.
|
||||
ignores := make(map[string]SuppressionInfo)
|
||||
ignores := make(map[string]issue.SuppressionInfo)
|
||||
for _, v := range matches {
|
||||
ignores[v[1]] = suppression
|
||||
}
|
||||
@@ -426,25 +509,42 @@ func (gosec *Analyzer) ignore(n ast.Node) map[string]SuppressionInfo {
|
||||
// Visit runs the gosec visitor logic over an AST created by parsing go code.
|
||||
// Rule methods added with AddRule will be invoked as necessary.
|
||||
func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor {
|
||||
// If we've reached the end of this branch, pop off the ignores stack.
|
||||
ignores, ok := gosec.updateIgnoredRules(n)
|
||||
if !ok {
|
||||
return gosec
|
||||
}
|
||||
|
||||
// Using ast.File instead of ast.ImportSpec, so that we can track all imports at once.
|
||||
switch i := n.(type) {
|
||||
case *ast.File:
|
||||
gosec.context.Imports.TrackFile(i)
|
||||
}
|
||||
|
||||
for _, rule := range gosec.ruleset.RegisteredFor(n) {
|
||||
suppressions, ignored := gosec.updateSuppressions(rule.ID(), ignores)
|
||||
issue, err := rule.Match(n, gosec.context)
|
||||
if err != nil {
|
||||
file, line := GetLocation(n, gosec.context)
|
||||
file = path.Base(file)
|
||||
gosec.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line)
|
||||
}
|
||||
gosec.updateIssues(issue, ignored, suppressions)
|
||||
}
|
||||
return gosec
|
||||
}
|
||||
|
||||
func (gosec *Analyzer) updateIgnoredRules(n ast.Node) (map[string][]issue.SuppressionInfo, bool) {
|
||||
if n == nil {
|
||||
if len(gosec.context.Ignores) > 0 {
|
||||
gosec.context.Ignores = gosec.context.Ignores[1:]
|
||||
}
|
||||
return gosec
|
||||
return nil, false
|
||||
}
|
||||
switch i := n.(type) {
|
||||
case *ast.File:
|
||||
// Using ast.File instead of ast.ImportSpec, so that we can track
|
||||
// all imports at once.
|
||||
gosec.context.Imports.TrackFile(i)
|
||||
}
|
||||
|
||||
// Get any new rule exclusions.
|
||||
ignoredRules := gosec.ignore(n)
|
||||
|
||||
// Now create the union of exclusions.
|
||||
ignores := map[string][]SuppressionInfo{}
|
||||
ignores := map[string][]issue.SuppressionInfo{}
|
||||
if len(gosec.context.Ignores) > 0 {
|
||||
for k, v := range gosec.context.Ignores[0] {
|
||||
ignores[k] = v
|
||||
@@ -456,59 +556,57 @@ func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor {
|
||||
}
|
||||
|
||||
// Push the new set onto the stack.
|
||||
gosec.context.Ignores = append([]map[string][]SuppressionInfo{ignores}, gosec.context.Ignores...)
|
||||
gosec.context.Ignores = append([]map[string][]issue.SuppressionInfo{ignores}, gosec.context.Ignores...)
|
||||
|
||||
for _, rule := range gosec.ruleset.RegisteredFor(n) {
|
||||
// Check if all rules are ignored.
|
||||
generalSuppressions, generalIgnored := ignores[aliasOfAllRules]
|
||||
// Check if the specific rule is ignored
|
||||
ruleSuppressions, ruleIgnored := ignores[rule.ID()]
|
||||
return ignores, true
|
||||
}
|
||||
|
||||
ignored := generalIgnored || ruleIgnored
|
||||
suppressions := append(generalSuppressions, ruleSuppressions...)
|
||||
func (gosec *Analyzer) updateSuppressions(id string, ignores map[string][]issue.SuppressionInfo) ([]issue.SuppressionInfo, bool) {
|
||||
// Check if all rules are ignored.
|
||||
generalSuppressions, generalIgnored := ignores[aliasOfAllRules]
|
||||
// Check if the specific rule is ignored
|
||||
ruleSuppressions, ruleIgnored := ignores[id]
|
||||
|
||||
// Track external suppressions.
|
||||
if gosec.ruleset.IsRuleSuppressed(rule.ID()) {
|
||||
ignored = true
|
||||
suppressions = append(suppressions, SuppressionInfo{
|
||||
Kind: "external",
|
||||
Justification: externalSuppressionJustification,
|
||||
})
|
||||
ignored := generalIgnored || ruleIgnored
|
||||
suppressions := append(generalSuppressions, ruleSuppressions...)
|
||||
|
||||
// Track external suppressions.
|
||||
if gosec.ruleset.IsRuleSuppressed(id) {
|
||||
ignored = true
|
||||
suppressions = append(suppressions, issue.SuppressionInfo{
|
||||
Kind: "external",
|
||||
Justification: externalSuppressionJustification,
|
||||
})
|
||||
}
|
||||
return suppressions, ignored
|
||||
}
|
||||
|
||||
func (gosec *Analyzer) updateIssues(issue *issue.Issue, ignored bool, suppressions []issue.SuppressionInfo) {
|
||||
if issue != nil {
|
||||
if gosec.showIgnored {
|
||||
issue.NoSec = ignored
|
||||
}
|
||||
|
||||
issue, err := rule.Match(n, gosec.context)
|
||||
if err != nil {
|
||||
file, line := GetLocation(n, gosec.context)
|
||||
file = path.Base(file)
|
||||
gosec.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line)
|
||||
if !ignored || !gosec.showIgnored {
|
||||
gosec.stats.NumFound++
|
||||
}
|
||||
if issue != nil {
|
||||
if gosec.showIgnored {
|
||||
issue.NoSec = ignored
|
||||
}
|
||||
if !ignored || !gosec.showIgnored {
|
||||
gosec.stats.NumFound++
|
||||
}
|
||||
if ignored && gosec.trackSuppressions {
|
||||
issue.WithSuppressions(suppressions)
|
||||
gosec.issues = append(gosec.issues, issue)
|
||||
} else if !ignored || gosec.showIgnored || gosec.ignoreNosec {
|
||||
gosec.issues = append(gosec.issues, issue)
|
||||
}
|
||||
if ignored && gosec.trackSuppressions {
|
||||
issue.WithSuppressions(suppressions)
|
||||
gosec.issues = append(gosec.issues, issue)
|
||||
} else if !ignored || gosec.showIgnored || gosec.ignoreNosec {
|
||||
gosec.issues = append(gosec.issues, issue)
|
||||
}
|
||||
}
|
||||
return gosec
|
||||
}
|
||||
|
||||
// Report returns the current issues discovered and the metrics about the scan
|
||||
func (gosec *Analyzer) Report() ([]*Issue, *Metrics, map[string][]Error) {
|
||||
func (gosec *Analyzer) Report() ([]*issue.Issue, *Metrics, map[string][]Error) {
|
||||
return gosec.issues, gosec.stats, gosec.errors
|
||||
}
|
||||
|
||||
// Reset clears state such as context, issues and metrics from the configured analyzer
|
||||
func (gosec *Analyzer) Reset() {
|
||||
gosec.context = &Context{}
|
||||
gosec.issues = make([]*Issue, 0, 16)
|
||||
gosec.issues = make([]*issue.Issue, 0, 16)
|
||||
gosec.stats = &Metrics{}
|
||||
gosec.ruleset = NewRuleSet()
|
||||
}
|
||||
|
||||
57
vendor/github.com/securego/gosec/v2/analyzers/ssrf.go
generated
vendored
Normal file
57
vendor/github.com/securego/gosec/v2/analyzers/ssrf.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
// (c) Copyright gosec's authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package analyzers
|
||||
|
||||
import (
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
"golang.org/x/tools/go/ssa"
|
||||
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
func newSSRFAnalyzer(id string, description string) *analysis.Analyzer {
|
||||
return &analysis.Analyzer{
|
||||
Name: id,
|
||||
Doc: description,
|
||||
Run: runSSRF,
|
||||
Requires: []*analysis.Analyzer{buildssa.Analyzer},
|
||||
}
|
||||
}
|
||||
|
||||
func runSSRF(pass *analysis.Pass) (interface{}, error) {
|
||||
ssaResult, err := getSSAResult(pass)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: implement the analysis
|
||||
for _, fn := range ssaResult.SSA.SrcFuncs {
|
||||
for _, block := range fn.DomPreorder() {
|
||||
for _, instr := range block.Instrs {
|
||||
switch instr := instr.(type) {
|
||||
case *ssa.Call:
|
||||
callee := instr.Call.StaticCallee()
|
||||
if callee != nil {
|
||||
ssaResult.Logger.Printf("callee: %s\n", callee)
|
||||
return newIssue(pass.Analyzer.Name,
|
||||
"not implemented",
|
||||
pass.Fset, instr.Call.Pos(), issue.Low, issue.High), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
98
vendor/github.com/securego/gosec/v2/analyzers/util.go
generated
vendored
Normal file
98
vendor/github.com/securego/gosec/v2/analyzers/util.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// (c) Copyright gosec's authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package analyzers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"golang.org/x/tools/go/analysis/passes/buildssa"
|
||||
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// SSAAnalyzerResult contains various information returned by the
|
||||
// SSA analysis along with some configuration
|
||||
type SSAAnalyzerResult struct {
|
||||
Config map[string]interface{}
|
||||
Logger *log.Logger
|
||||
SSA *buildssa.SSA
|
||||
}
|
||||
|
||||
// BuildDefaultAnalyzers returns the default list of analyzers
|
||||
func BuildDefaultAnalyzers() []*analysis.Analyzer {
|
||||
return []*analysis.Analyzer{
|
||||
newSSRFAnalyzer("G107", "URL provided to HTTP request as taint input"),
|
||||
}
|
||||
}
|
||||
|
||||
// getSSAResult retrieves the SSA result from analysis pass
|
||||
func getSSAResult(pass *analysis.Pass) (*SSAAnalyzerResult, error) {
|
||||
result, ok := pass.ResultOf[buildssa.Analyzer]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no SSA result found in the analysis pass")
|
||||
}
|
||||
ssaResult, ok := result.(*SSAAnalyzerResult)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("the analysis pass result is not of type SSA")
|
||||
}
|
||||
return ssaResult, nil
|
||||
}
|
||||
|
||||
// newIssue creates a new gosec issue
|
||||
func newIssue(analyzerID string, desc string, fileSet *token.FileSet,
|
||||
pos token.Pos, severity, confidence issue.Score,
|
||||
) *issue.Issue {
|
||||
file := fileSet.File(pos)
|
||||
line := file.Line(pos)
|
||||
col := file.Position(pos).Column
|
||||
|
||||
return &issue.Issue{
|
||||
RuleID: analyzerID,
|
||||
File: file.Name(),
|
||||
Line: strconv.Itoa(line),
|
||||
Col: strconv.Itoa(col),
|
||||
Severity: severity,
|
||||
Confidence: confidence,
|
||||
What: desc,
|
||||
Cwe: issue.GetCweByRule(analyzerID),
|
||||
Code: issueCodeSnippet(fileSet, pos),
|
||||
}
|
||||
}
|
||||
|
||||
func issueCodeSnippet(fileSet *token.FileSet, pos token.Pos) string {
|
||||
file := fileSet.File(pos)
|
||||
|
||||
start := (int64)(file.Line(pos))
|
||||
if start-issue.SnippetOffset > 0 {
|
||||
start = start - issue.SnippetOffset
|
||||
}
|
||||
end := (int64)(file.Line(pos))
|
||||
end = end + issue.SnippetOffset
|
||||
|
||||
var code string
|
||||
if file, err := os.Open(file.Name()); err == nil {
|
||||
defer file.Close() // #nosec
|
||||
code, err = issue.CodeSnippet(file, start, end)
|
||||
if err != nil {
|
||||
return err.Error()
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
24
vendor/github.com/securego/gosec/v2/cmd/gosec/main.go
generated
vendored
24
vendor/github.com/securego/gosec/v2/cmd/gosec/main.go
generated
vendored
@@ -26,6 +26,7 @@ import (
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/cmd/vflag"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
"github.com/securego/gosec/v2/report"
|
||||
"github.com/securego/gosec/v2/rules"
|
||||
)
|
||||
@@ -142,7 +143,10 @@ var (
|
||||
// output suppression information for auditing purposes
|
||||
flagTrackSuppressions = flag.Bool("track-suppressions", false, "Output suppression information, including its kind and justification")
|
||||
|
||||
// exlude the folders from scan
|
||||
// flagTerse shows only the summary of scan discarding all the logs
|
||||
flagTerse = flag.Bool("terse", false, "Shows only the results and summary")
|
||||
|
||||
// exclude the folders from scan
|
||||
flagDirsExclude arrayFlags
|
||||
|
||||
logger *log.Logger
|
||||
@@ -265,22 +269,22 @@ func saveReport(filename, format string, rootPaths []string, reportInfo *gosec.R
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertToScore(value string) (gosec.Score, error) {
|
||||
func convertToScore(value string) (issue.Score, error) {
|
||||
value = strings.ToLower(value)
|
||||
switch value {
|
||||
case "low":
|
||||
return gosec.Low, nil
|
||||
return issue.Low, nil
|
||||
case "medium":
|
||||
return gosec.Medium, nil
|
||||
return issue.Medium, nil
|
||||
case "high":
|
||||
return gosec.High, nil
|
||||
return issue.High, nil
|
||||
default:
|
||||
return gosec.Low, fmt.Errorf("provided value '%s' not valid. Valid options: low, medium, high", value)
|
||||
return issue.Low, fmt.Errorf("provided value '%s' not valid. Valid options: low, medium, high", value)
|
||||
}
|
||||
}
|
||||
|
||||
func filterIssues(issues []*gosec.Issue, severity gosec.Score, confidence gosec.Score) ([]*gosec.Issue, int) {
|
||||
result := make([]*gosec.Issue, 0)
|
||||
func filterIssues(issues []*issue.Issue, severity issue.Score, confidence issue.Score) ([]*issue.Issue, int) {
|
||||
result := make([]*issue.Issue, 0)
|
||||
trueIssues := 0
|
||||
for _, issue := range issues {
|
||||
if issue.Severity >= severity && issue.Confidence >= confidence {
|
||||
@@ -293,7 +297,7 @@ func filterIssues(issues []*gosec.Issue, severity gosec.Score, confidence gosec.
|
||||
return result, trueIssues
|
||||
}
|
||||
|
||||
func exit(issues []*gosec.Issue, errors map[string][]gosec.Error, noFail bool) {
|
||||
func exit(issues []*issue.Issue, errors map[string][]gosec.Error, noFail bool) {
|
||||
nsi := 0
|
||||
for _, issue := range issues {
|
||||
if len(issue.Suppressions) == 0 {
|
||||
@@ -353,7 +357,7 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
if *flagQuiet {
|
||||
if *flagQuiet || *flagTerse {
|
||||
logger = log.New(io.Discard, "", 0)
|
||||
} else {
|
||||
logger = log.New(logWriter, "[gosec] ", log.LstdFlags)
|
||||
|
||||
6
vendor/github.com/securego/gosec/v2/cmd/gosec/sort_issues.go
generated
vendored
6
vendor/github.com/securego/gosec/v2/cmd/gosec/sort_issues.go
generated
vendored
@@ -5,7 +5,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// handle ranges
|
||||
@@ -14,7 +14,7 @@ func extractLineNumber(s string) int {
|
||||
return lineNumber
|
||||
}
|
||||
|
||||
type sortBySeverity []*gosec.Issue
|
||||
type sortBySeverity []*issue.Issue
|
||||
|
||||
func (s sortBySeverity) Len() int { return len(s) }
|
||||
|
||||
@@ -34,6 +34,6 @@ func (s sortBySeverity) Less(i, j int) bool {
|
||||
func (s sortBySeverity) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// sortIssues sorts the issues by severity in descending order
|
||||
func sortIssues(issues []*gosec.Issue) {
|
||||
func sortIssues(issues []*issue.Issue) {
|
||||
sort.Sort(sortBySeverity(issues))
|
||||
}
|
||||
|
||||
7
vendor/github.com/securego/gosec/v2/config.go
generated
vendored
7
vendor/github.com/securego/gosec/v2/config.go
generated
vendored
@@ -29,8 +29,15 @@ const (
|
||||
ExcludeRules GlobalOption = "exclude"
|
||||
// IncludeRules global option for should be load
|
||||
IncludeRules GlobalOption = "include"
|
||||
// SSA global option to enable go analysis framework with SSA support
|
||||
SSA GlobalOption = "ssa"
|
||||
)
|
||||
|
||||
// NoSecTag returns the tag used to disable gosec for a line of code.
|
||||
func NoSecTag(tag string) string {
|
||||
return fmt.Sprintf("%s%s", "#", tag)
|
||||
}
|
||||
|
||||
// Config is used to provide configuration and customization to each of the rules.
|
||||
type Config map[string]interface{}
|
||||
|
||||
|
||||
58
vendor/github.com/securego/gosec/v2/helpers.go
generated
vendored
58
vendor/github.com/securego/gosec/v2/helpers.go
generated
vendored
@@ -96,11 +96,46 @@ func GetChar(n ast.Node) (byte, error) {
|
||||
return 0, fmt.Errorf("Unexpected AST node type: %T", n)
|
||||
}
|
||||
|
||||
// GetStringRecursive will recursively walk down a tree of *ast.BinaryExpr. It will then concat the results, and return.
|
||||
// Unlike the other getters, it does _not_ raise an error for unknown ast.Node types. At the base, the recursion will hit a non-BinaryExpr type,
|
||||
// either BasicLit or other, so it's not an error case. It will only error if `strconv.Unquote` errors. This matters, because there's
|
||||
// currently functionality that relies on error values being returned by GetString if and when it hits a non-basiclit string node type,
|
||||
// hence for cases where recursion is needed, we use this separate function, so that we can still be backwards compatbile.
|
||||
//
|
||||
// This was added to handle a SQL injection concatenation case where the injected value is infixed between two strings, not at the start or end. See example below
|
||||
//
|
||||
// Do note that this will omit non-string values. So for example, if you were to use this node:
|
||||
// ```go
|
||||
// q := "SELECT * FROM foo WHERE name = '" + os.Args[0] + "' AND 1=1" // will result in "SELECT * FROM foo WHERE ” AND 1=1"
|
||||
|
||||
func GetStringRecursive(n ast.Node) (string, error) {
|
||||
if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.STRING {
|
||||
return strconv.Unquote(node.Value)
|
||||
}
|
||||
|
||||
if expr, ok := n.(*ast.BinaryExpr); ok {
|
||||
x, err := GetStringRecursive(expr.X)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
y, err := GetStringRecursive(expr.Y)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return x + y, nil
|
||||
}
|
||||
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// GetString will read and return a string value from an ast.BasicLit
|
||||
func GetString(n ast.Node) (string, error) {
|
||||
if node, ok := n.(*ast.BasicLit); ok && node.Kind == token.STRING {
|
||||
return strconv.Unquote(node.Value)
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("Unexpected AST node type: %T", n)
|
||||
}
|
||||
|
||||
@@ -182,7 +217,7 @@ func GetCallInfo(n ast.Node, ctx *Context) (string, string, error) {
|
||||
}
|
||||
|
||||
// GetCallStringArgsValues returns the values of strings arguments if they can be resolved
|
||||
func GetCallStringArgsValues(n ast.Node, ctx *Context) []string {
|
||||
func GetCallStringArgsValues(n ast.Node, _ *Context) []string {
|
||||
values := []string{}
|
||||
switch node := n.(type) {
|
||||
case *ast.CallExpr:
|
||||
@@ -201,22 +236,21 @@ func GetCallStringArgsValues(n ast.Node, ctx *Context) []string {
|
||||
return values
|
||||
}
|
||||
|
||||
// GetIdentStringValues return the string values of an Ident if they can be resolved
|
||||
func GetIdentStringValues(ident *ast.Ident) []string {
|
||||
func getIdentStringValues(ident *ast.Ident, stringFinder func(ast.Node) (string, error)) []string {
|
||||
values := []string{}
|
||||
obj := ident.Obj
|
||||
if obj != nil {
|
||||
switch decl := obj.Decl.(type) {
|
||||
case *ast.ValueSpec:
|
||||
for _, v := range decl.Values {
|
||||
value, err := GetString(v)
|
||||
value, err := stringFinder(v)
|
||||
if err == nil {
|
||||
values = append(values, value)
|
||||
}
|
||||
}
|
||||
case *ast.AssignStmt:
|
||||
for _, v := range decl.Rhs {
|
||||
value, err := GetString(v)
|
||||
value, err := stringFinder(v)
|
||||
if err == nil {
|
||||
values = append(values, value)
|
||||
}
|
||||
@@ -226,6 +260,18 @@ func GetIdentStringValues(ident *ast.Ident) []string {
|
||||
return values
|
||||
}
|
||||
|
||||
// getIdentStringRecursive returns the string of values of an Ident if they can be resolved
|
||||
// The difference between this and GetIdentStringValues is that it will attempt to resolve the strings recursively,
|
||||
// if it is passed a *ast.BinaryExpr. See GetStringRecursive for details
|
||||
func GetIdentStringValuesRecursive(ident *ast.Ident) []string {
|
||||
return getIdentStringValues(ident, GetStringRecursive)
|
||||
}
|
||||
|
||||
// GetIdentStringValues return the string values of an Ident if they can be resolved
|
||||
func GetIdentStringValues(ident *ast.Ident) []string {
|
||||
return getIdentStringValues(ident, GetString)
|
||||
}
|
||||
|
||||
// GetBinaryExprOperands returns all operands of a binary expression by traversing
|
||||
// the expression tree
|
||||
func GetBinaryExprOperands(be *ast.BinaryExpr) []ast.Node {
|
||||
@@ -301,7 +347,7 @@ func Getenv(key, userDefault string) string {
|
||||
return userDefault
|
||||
}
|
||||
|
||||
// GetPkgRelativePath returns the Go relative relative path derived
|
||||
// GetPkgRelativePath returns the Go relative path derived
|
||||
// form the given path
|
||||
func GetPkgRelativePath(path string) (string, error) {
|
||||
abspath, err := filepath.Abs(path)
|
||||
|
||||
4
vendor/github.com/securego/gosec/v2/import_tracker.go
generated
vendored
4
vendor/github.com/securego/gosec/v2/import_tracker.go
generated
vendored
@@ -51,9 +51,7 @@ func (t *ImportTracker) TrackPackages(pkgs ...*types.Package) {
|
||||
func (t *ImportTracker) TrackImport(imported *ast.ImportSpec) {
|
||||
importPath := strings.Trim(imported.Path.Value, `"`)
|
||||
if imported.Name != nil {
|
||||
if imported.Name.Name == "_" {
|
||||
// Initialization only import
|
||||
} else {
|
||||
if imported.Name.Name != "_" {
|
||||
// Aliased import
|
||||
t.Imported[importPath] = append(t.Imported[importPath], imported.Name.String())
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package gosec
|
||||
package issue
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@@ -77,7 +77,6 @@ var ruleToCWE = map[string]string{
|
||||
"G304": "22",
|
||||
"G305": "22",
|
||||
"G306": "276",
|
||||
"G307": "703",
|
||||
"G401": "326",
|
||||
"G402": "295",
|
||||
"G403": "310",
|
||||
@@ -88,6 +87,7 @@ var ruleToCWE = map[string]string{
|
||||
"G504": "327",
|
||||
"G505": "327",
|
||||
"G601": "118",
|
||||
"G602": "118",
|
||||
}
|
||||
|
||||
// Issue is returned by a gosec rule if it discovers an issue with the scanned code.
|
||||
@@ -105,8 +105,15 @@ type Issue struct {
|
||||
Suppressions []SuppressionInfo `json:"suppressions"` // Suppression info of the issue
|
||||
}
|
||||
|
||||
// SuppressionInfo object is to record the kind and the justification that used
|
||||
// to suppress violations.
|
||||
type SuppressionInfo struct {
|
||||
Kind string `json:"kind"`
|
||||
Justification string `json:"justification"`
|
||||
}
|
||||
|
||||
// FileLocation point out the file path and line number in file
|
||||
func (i Issue) FileLocation() string {
|
||||
func (i *Issue) FileLocation() string {
|
||||
return fmt.Sprintf("%s:%s", i.File, i.Line)
|
||||
}
|
||||
|
||||
@@ -137,11 +144,8 @@ func (c Score) String() string {
|
||||
return "UNDEFINED"
|
||||
}
|
||||
|
||||
// codeSnippet extracts a code snippet based on the ast reference
|
||||
func codeSnippet(file *os.File, start int64, end int64, n ast.Node) (string, error) {
|
||||
if n == nil {
|
||||
return "", fmt.Errorf("invalid AST node provided")
|
||||
}
|
||||
// CodeSnippet extracts a code snippet based on the ast reference
|
||||
func CodeSnippet(file *os.File, start int64, end int64) (string, error) {
|
||||
var pos int64
|
||||
var buf bytes.Buffer
|
||||
scanner := bufio.NewScanner(file)
|
||||
@@ -171,9 +175,8 @@ func codeSnippetEndLine(node ast.Node, fobj *token.File) int64 {
|
||||
return e + SnippetOffset
|
||||
}
|
||||
|
||||
// NewIssue creates a new Issue
|
||||
func NewIssue(ctx *Context, node ast.Node, ruleID, desc string, severity Score, confidence Score) *Issue {
|
||||
fobj := ctx.FileSet.File(node.Pos())
|
||||
// New creates a new Issue
|
||||
func New(fobj *token.File, node ast.Node, ruleID, desc string, severity, confidence Score) *Issue {
|
||||
name := fobj.Name()
|
||||
start, end := fobj.Line(node.Pos()), fobj.Line(node.End())
|
||||
line := strconv.Itoa(start)
|
||||
@@ -183,11 +186,14 @@ func NewIssue(ctx *Context, node ast.Node, ruleID, desc string, severity Score,
|
||||
col := strconv.Itoa(fobj.Position(node.Pos()).Column)
|
||||
|
||||
var code string
|
||||
if file, err := os.Open(fobj.Name()); err == nil {
|
||||
if node == nil {
|
||||
code = "invalid AST node provided"
|
||||
}
|
||||
if file, err := os.Open(fobj.Name()); err == nil && node != nil {
|
||||
defer file.Close() // #nosec
|
||||
s := codeSnippetStartLine(node, fobj)
|
||||
e := codeSnippetEndLine(node, fobj)
|
||||
code, err = codeSnippet(file, s, e, node)
|
||||
code, err = CodeSnippet(file, s, e)
|
||||
if err != nil {
|
||||
code = err.Error()
|
||||
}
|
||||
8
vendor/github.com/securego/gosec/v2/report.go
generated
vendored
8
vendor/github.com/securego/gosec/v2/report.go
generated
vendored
@@ -1,15 +1,19 @@
|
||||
package gosec
|
||||
|
||||
import (
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// ReportInfo this is report information
|
||||
type ReportInfo struct {
|
||||
Errors map[string][]Error `json:"Golang errors"`
|
||||
Issues []*Issue
|
||||
Issues []*issue.Issue
|
||||
Stats *Metrics
|
||||
GosecVersion string
|
||||
}
|
||||
|
||||
// NewReportInfo instantiate a ReportInfo
|
||||
func NewReportInfo(issues []*Issue, metrics *Metrics, errors map[string][]Error) *ReportInfo {
|
||||
func NewReportInfo(issues []*issue.Issue, metrics *Metrics, errors map[string][]Error) *ReportInfo {
|
||||
return &ReportInfo{
|
||||
Errors: errors,
|
||||
Issues: issues,
|
||||
|
||||
5
vendor/github.com/securego/gosec/v2/report/formatter.go
generated
vendored
5
vendor/github.com/securego/gosec/v2/report/formatter.go
generated
vendored
@@ -18,6 +18,7 @@ import (
|
||||
"io"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
"github.com/securego/gosec/v2/report/csv"
|
||||
"github.com/securego/gosec/v2/report/golint"
|
||||
"github.com/securego/gosec/v2/report/html"
|
||||
@@ -81,8 +82,8 @@ func CreateReport(w io.Writer, format string, enableColor bool, rootPaths []stri
|
||||
return err
|
||||
}
|
||||
|
||||
func filterOutSuppressedIssues(issues []*gosec.Issue) []*gosec.Issue {
|
||||
nonSuppressedIssues := []*gosec.Issue{}
|
||||
func filterOutSuppressedIssues(issues []*issue.Issue) []*issue.Issue {
|
||||
nonSuppressedIssues := []*issue.Issue{}
|
||||
for _, issue := range issues {
|
||||
if len(issue.Suppressions) == 0 {
|
||||
nonSuppressedIssues = append(nonSuppressedIssues, issue)
|
||||
|
||||
8
vendor/github.com/securego/gosec/v2/report/html/template.html
generated
vendored
8
vendor/github.com/securego/gosec/v2/report/html/template.html
generated
vendored
@@ -5,12 +5,12 @@
|
||||
<title>Golang Security Checker</title>
|
||||
<link rel="shortcut icon" type="image/png" href="https://securego.io/img/favicon.png">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.4/css/bulma.min.css" integrity="sha512-HqxHUkJM0SYcbvxUw5P60SzdOTy/QVwA1JJrvaXJv4q7lmbDZCmZaqz01UPOaQveoxfYRv1tHozWGPMcuTBuvQ==" crossorigin="anonymous"/>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css" integrity="sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==" crossorigin="anonymous"/>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js" integrity="sha512-bgHRAiTjGrzHzLyKOnpFvaEpGzJet3z4tZnXGjpsCcqOnAH6VGUx9frc5bcIhKTVLEiCO6vEhNAgx5jtLUYrfA==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/languages/go.min.js" integrity="sha512-AzBQVo6m0++RbnY/eU9VbedSeokh6wzxEOTc6XGGjcxdFeKxT43bFyo5sHYEIZe8sf5VfiewyNtwOrhu/Mo55g==" crossorigin="anonymous"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/default.min.css" integrity="sha512-hasIneQUHlh06VNBe7f6ZcHmeRTLIaQWFd43YriJ0UND19bvYRauxthDg8E4eVNPm9bRUhr5JGeqH7FRFXQu5g==" crossorigin="anonymous"/>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js" integrity="sha512-rdhY3cbXURo13l/WU9VlaRyaIYeJ/KBakckXIvJNAQde8DgpOmE+eZf7ha4vdqVjTtwQt69bD2wH2LXob/LB7Q==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/go.min.js" integrity="sha512-Ea+IN1qMvgwTqOnwxM38Hn54IaDS2buEvMJNTdSB5JOT4njx3RvPij353zbUMpT+zYjDqQDr2UbrbnW5+wE54A==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.7.0/react.min.js" integrity="sha512-+TFn1Gqbwx/qgwW3NU1/YtFYTfHGeD1e/8YfJZzkb6TFEZP4SUwp1Az9DMeWh3qC0F+YPKXbV3YclMUwBTvO3g==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js" integrity="sha512-8C49ZG/SaQnWaUgCHTU1o8uIQNYE6R8me38SwF26g2Q0byEXF4Jlvm+T/JAMHMeTBiEVPslSZRv9Xt4AV0pfmw==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.20.15/babel.min.js" integrity="sha512-Oy8gM3nNZgwbgd81x/VCtGpolDzgHK2Hpbn9nq4YhzDvxI4/ipCnoUeSHozXvTjOkzuZ1qqlUYjroqmclLhknA==" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.10/babel.min.js" integrity="sha512-UhgUmmslB4Pi7NNyzbscVQPaL3meon1WMwHwHDjCLui/kWpr2Wz4sRZ8HlG4gZIUuKkF+LWYTX55ZVPzra2HTw==" crossorigin="anonymous"></script>
|
||||
<style>
|
||||
.field-label {
|
||||
min-width: 80px;
|
||||
|
||||
3
vendor/github.com/securego/gosec/v2/report/junit/formatter.go
generated
vendored
3
vendor/github.com/securego/gosec/v2/report/junit/formatter.go
generated
vendored
@@ -5,9 +5,10 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
func generatePlaintext(issue *gosec.Issue) string {
|
||||
func generatePlaintext(issue *issue.Issue) string {
|
||||
cweID := "CWE"
|
||||
if issue.Cwe != nil {
|
||||
cweID = issue.Cwe.ID
|
||||
|
||||
101
vendor/github.com/securego/gosec/v2/report/sarif/formatter.go
generated
vendored
101
vendor/github.com/securego/gosec/v2/report/sarif/formatter.go
generated
vendored
@@ -7,24 +7,19 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/cwe"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// GenerateReport Convert a gosec report to a Sarif Report
|
||||
// GenerateReport converts a gosec report into a SARIF report
|
||||
func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error) {
|
||||
type rule struct {
|
||||
index int
|
||||
rule *ReportingDescriptor
|
||||
}
|
||||
|
||||
rules := make([]*ReportingDescriptor, 0)
|
||||
rulesIndices := make(map[string]rule)
|
||||
lastRuleIndex := -1
|
||||
rules := []*ReportingDescriptor{}
|
||||
|
||||
results := []*Result{}
|
||||
cweTaxa := make([]*ReportingDescriptor, 0)
|
||||
weaknesses := make(map[string]*cwe.Weakness)
|
||||
cweTaxa := []*ReportingDescriptor{}
|
||||
weaknesses := map[string]*cwe.Weakness{}
|
||||
|
||||
for _, issue := range data.Issues {
|
||||
if issue.Cwe != nil {
|
||||
@@ -37,26 +32,26 @@ func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error)
|
||||
}
|
||||
}
|
||||
|
||||
r, ok := rulesIndices[issue.RuleID]
|
||||
if !ok {
|
||||
lastRuleIndex++
|
||||
r = rule{index: lastRuleIndex, rule: parseSarifRule(issue)}
|
||||
rulesIndices[issue.RuleID] = r
|
||||
rules = append(rules, r.rule)
|
||||
}
|
||||
rule := parseSarifRule(issue)
|
||||
var ruleIndex int
|
||||
rules, ruleIndex = addRuleInOrder(rules, rule)
|
||||
|
||||
location, err := parseSarifLocation(issue, rootPaths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := NewResult(r.rule.ID, r.index, getSarifLevel(issue.Severity.String()), issue.What, buildSarifSuppressions(issue.Suppressions)).
|
||||
WithLocations(location)
|
||||
result := NewResult(
|
||||
issue.RuleID,
|
||||
ruleIndex,
|
||||
getSarifLevel(issue.Severity.String()),
|
||||
issue.What,
|
||||
buildSarifSuppressions(issue.Suppressions),
|
||||
).WithLocations(location)
|
||||
|
||||
results = append(results, result)
|
||||
}
|
||||
|
||||
sort.SliceStable(rules, func(i, j int) bool { return rules[i].ID < rules[j].ID })
|
||||
sort.SliceStable(cweTaxa, func(i, j int) bool { return cweTaxa[i].ID < cweTaxa[j].ID })
|
||||
|
||||
tool := NewTool(buildSarifDriver(rules, data.GosecVersion))
|
||||
@@ -71,29 +66,49 @@ func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error)
|
||||
WithRuns(run), nil
|
||||
}
|
||||
|
||||
// addRuleInOrder inserts a rule into the rules slice keeping the rules IDs order, it returns the new rules
|
||||
// slice and the position where the rule was inserted
|
||||
func addRuleInOrder(rules []*ReportingDescriptor, rule *ReportingDescriptor) ([]*ReportingDescriptor, int) {
|
||||
position := 0
|
||||
for i, r := range rules {
|
||||
if r.ID < rule.ID {
|
||||
continue
|
||||
}
|
||||
if r.ID == rule.ID {
|
||||
return rules, i
|
||||
}
|
||||
position = i
|
||||
break
|
||||
}
|
||||
rules = append(rules, nil)
|
||||
copy(rules[position+1:], rules[position:])
|
||||
rules[position] = rule
|
||||
return rules, position
|
||||
}
|
||||
|
||||
// parseSarifRule return SARIF rule field struct
|
||||
func parseSarifRule(issue *gosec.Issue) *ReportingDescriptor {
|
||||
cwe := gosec.GetCweByRule(issue.RuleID)
|
||||
name := issue.RuleID
|
||||
func parseSarifRule(i *issue.Issue) *ReportingDescriptor {
|
||||
cwe := issue.GetCweByRule(i.RuleID)
|
||||
name := i.RuleID
|
||||
if cwe != nil {
|
||||
name = cwe.Name
|
||||
}
|
||||
return &ReportingDescriptor{
|
||||
ID: issue.RuleID,
|
||||
ID: i.RuleID,
|
||||
Name: name,
|
||||
ShortDescription: NewMultiformatMessageString(issue.What),
|
||||
FullDescription: NewMultiformatMessageString(issue.What),
|
||||
ShortDescription: NewMultiformatMessageString(i.What),
|
||||
FullDescription: NewMultiformatMessageString(i.What),
|
||||
Help: NewMultiformatMessageString(fmt.Sprintf("%s\nSeverity: %s\nConfidence: %s\n",
|
||||
issue.What, issue.Severity.String(), issue.Confidence.String())),
|
||||
i.What, i.Severity.String(), i.Confidence.String())),
|
||||
Properties: &PropertyBag{
|
||||
"tags": []string{"security", issue.Severity.String()},
|
||||
"precision": strings.ToLower(issue.Confidence.String()),
|
||||
"tags": []string{"security", i.Severity.String()},
|
||||
"precision": strings.ToLower(i.Confidence.String()),
|
||||
},
|
||||
DefaultConfiguration: &ReportingConfiguration{
|
||||
Level: getSarifLevel(issue.Severity.String()),
|
||||
Level: getSarifLevel(i.Severity.String()),
|
||||
},
|
||||
Relationships: []*ReportingDescriptorRelationship{
|
||||
buildSarifReportingDescriptorRelationship(issue.Cwe),
|
||||
buildSarifReportingDescriptorRelationship(i.Cwe),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -157,27 +172,27 @@ func uuid3(value string) string {
|
||||
}
|
||||
|
||||
// parseSarifLocation return SARIF location struct
|
||||
func parseSarifLocation(issue *gosec.Issue, rootPaths []string) (*Location, error) {
|
||||
region, err := parseSarifRegion(issue)
|
||||
func parseSarifLocation(i *issue.Issue, rootPaths []string) (*Location, error) {
|
||||
region, err := parseSarifRegion(i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
artifactLocation := parseSarifArtifactLocation(issue, rootPaths)
|
||||
artifactLocation := parseSarifArtifactLocation(i, rootPaths)
|
||||
return NewLocation(NewPhysicalLocation(artifactLocation, region)), nil
|
||||
}
|
||||
|
||||
func parseSarifArtifactLocation(issue *gosec.Issue, rootPaths []string) *ArtifactLocation {
|
||||
func parseSarifArtifactLocation(i *issue.Issue, rootPaths []string) *ArtifactLocation {
|
||||
var filePath string
|
||||
for _, rootPath := range rootPaths {
|
||||
if strings.HasPrefix(issue.File, rootPath) {
|
||||
filePath = strings.Replace(issue.File, rootPath+"/", "", 1)
|
||||
if strings.HasPrefix(i.File, rootPath) {
|
||||
filePath = strings.Replace(i.File, rootPath+"/", "", 1)
|
||||
}
|
||||
}
|
||||
return NewArtifactLocation(filePath)
|
||||
}
|
||||
|
||||
func parseSarifRegion(issue *gosec.Issue) (*Region, error) {
|
||||
lines := strings.Split(issue.Line, "-")
|
||||
func parseSarifRegion(i *issue.Issue) (*Region, error) {
|
||||
lines := strings.Split(i.Line, "-")
|
||||
startLine, err := strconv.Atoi(lines[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -189,13 +204,13 @@ func parseSarifRegion(issue *gosec.Issue) (*Region, error) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
col, err := strconv.Atoi(issue.Col)
|
||||
col, err := strconv.Atoi(i.Col)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var code string
|
||||
line := startLine
|
||||
codeLines := strings.Split(issue.Code, "\n")
|
||||
codeLines := strings.Split(i.Code, "\n")
|
||||
for _, codeLine := range codeLines {
|
||||
lineStart := fmt.Sprintf("%d:", line)
|
||||
if strings.HasPrefix(codeLine, lineStart) {
|
||||
@@ -227,7 +242,7 @@ func getSarifLevel(s string) Level {
|
||||
}
|
||||
}
|
||||
|
||||
func buildSarifSuppressions(suppressions []gosec.SuppressionInfo) []*Suppression {
|
||||
func buildSarifSuppressions(suppressions []issue.SuppressionInfo) []*Suppression {
|
||||
var sarifSuppressionList []*Suppression
|
||||
for _, s := range suppressions {
|
||||
sarifSuppressionList = append(sarifSuppressionList, NewSuppression(s.Kind, s.Justification))
|
||||
|
||||
5
vendor/github.com/securego/gosec/v2/report/sonar/formatter.go
generated
vendored
5
vendor/github.com/securego/gosec/v2/report/sonar/formatter.go
generated
vendored
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -36,7 +37,7 @@ func GenerateReport(rootPaths []string, data *gosec.ReportInfo) (*Report, error)
|
||||
return si, nil
|
||||
}
|
||||
|
||||
func parseFilePath(issue *gosec.Issue, rootPaths []string) string {
|
||||
func parseFilePath(issue *issue.Issue, rootPaths []string) string {
|
||||
var sonarFilePath string
|
||||
for _, rootPath := range rootPaths {
|
||||
if strings.HasPrefix(issue.File, rootPath) {
|
||||
@@ -46,7 +47,7 @@ func parseFilePath(issue *gosec.Issue, rootPaths []string) string {
|
||||
return sonarFilePath
|
||||
}
|
||||
|
||||
func parseTextRange(issue *gosec.Issue) (*TextRange, error) {
|
||||
func parseTextRange(issue *issue.Issue) (*TextRange, error) {
|
||||
lines := strings.Split(issue.Line, "-")
|
||||
startLine, err := strconv.Atoi(lines[0])
|
||||
if err != nil {
|
||||
|
||||
12
vendor/github.com/securego/gosec/v2/report/text/writer.go
generated
vendored
12
vendor/github.com/securego/gosec/v2/report/text/writer.go
generated
vendored
@@ -11,7 +11,9 @@ import (
|
||||
"text/template"
|
||||
|
||||
"github.com/gookit/color"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -49,7 +51,7 @@ func plainTextFuncMap(enableColor bool) template.FuncMap {
|
||||
|
||||
// by default those functions return the given content untouched
|
||||
return template.FuncMap{
|
||||
"highlight": func(t string, s gosec.Score, ignored bool) string {
|
||||
"highlight": func(t string, s issue.Score, ignored bool) string {
|
||||
return t
|
||||
},
|
||||
"danger": fmt.Sprint,
|
||||
@@ -60,14 +62,14 @@ func plainTextFuncMap(enableColor bool) template.FuncMap {
|
||||
}
|
||||
|
||||
// highlight returns content t colored based on Score
|
||||
func highlight(t string, s gosec.Score, ignored bool) string {
|
||||
func highlight(t string, s issue.Score, ignored bool) string {
|
||||
if ignored {
|
||||
return defaultTheme.Sprint(t)
|
||||
}
|
||||
switch s {
|
||||
case gosec.High:
|
||||
case issue.High:
|
||||
return errorTheme.Sprint(t)
|
||||
case gosec.Medium:
|
||||
case issue.Medium:
|
||||
return warningTheme.Sprint(t)
|
||||
default:
|
||||
return defaultTheme.Sprint(t)
|
||||
@@ -75,7 +77,7 @@ func highlight(t string, s gosec.Score, ignored bool) string {
|
||||
}
|
||||
|
||||
// printCodeSnippet prints the code snippet from the issue by adding a marker to the affected line
|
||||
func printCodeSnippet(issue *gosec.Issue) string {
|
||||
func printCodeSnippet(issue *issue.Issue) string {
|
||||
start, end := parseLine(issue.Line)
|
||||
scanner := bufio.NewScanner(strings.NewReader(issue.Code))
|
||||
var buf bytes.Buffer
|
||||
|
||||
3
vendor/github.com/securego/gosec/v2/report/yaml/writer.go
generated
vendored
3
vendor/github.com/securego/gosec/v2/report/yaml/writer.go
generated
vendored
@@ -3,8 +3,9 @@ package yaml
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
)
|
||||
|
||||
// WriteReport write a report in yaml format to the output writer
|
||||
|
||||
2
vendor/github.com/securego/gosec/v2/resolve.go
generated
vendored
2
vendor/github.com/securego/gosec/v2/resolve.go
generated
vendored
@@ -66,7 +66,7 @@ func resolveBinExpr(n *ast.BinaryExpr, c *Context) bool {
|
||||
return (TryResolve(n.X, c) && TryResolve(n.Y, c))
|
||||
}
|
||||
|
||||
func resolveCallExpr(n *ast.CallExpr, c *Context) bool {
|
||||
func resolveCallExpr(_ *ast.CallExpr, _ *Context) bool {
|
||||
// TODO(tkelsey): next step, full function resolution
|
||||
return false
|
||||
}
|
||||
|
||||
6
vendor/github.com/securego/gosec/v2/rule.go
generated
vendored
6
vendor/github.com/securego/gosec/v2/rule.go
generated
vendored
@@ -15,12 +15,14 @@ package gosec
|
||||
import (
|
||||
"go/ast"
|
||||
"reflect"
|
||||
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// The Rule interface used by all rules supported by gosec.
|
||||
type Rule interface {
|
||||
ID() string
|
||||
Match(ast.Node, *Context) (*Issue, error)
|
||||
Match(ast.Node, *Context) (*issue.Issue, error)
|
||||
}
|
||||
|
||||
// RuleBuilder is used to register a rule definition with the analyzer
|
||||
@@ -41,7 +43,7 @@ func NewRuleSet() RuleSet {
|
||||
return RuleSet{make(map[reflect.Type][]Rule), make(map[string]bool)}
|
||||
}
|
||||
|
||||
// Register adds a trigger for the supplied rule for the the
|
||||
// Register adds a trigger for the supplied rule for the
|
||||
// specified ast nodes.
|
||||
func (r RuleSet) Register(rule Rule, isSuppressed bool, nodes ...ast.Node) {
|
||||
for _, n := range nodes {
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/archive.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/archive.go
generated
vendored
@@ -5,10 +5,11 @@ import (
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type archive struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
argTypes []string
|
||||
}
|
||||
@@ -18,7 +19,7 @@ func (a *archive) ID() string {
|
||||
}
|
||||
|
||||
// Match inspects AST nodes to determine if the filepath.Joins uses any argument derived from type zip.File or tar.Header
|
||||
func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (a *archive) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if node := a.calls.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
var argType types.Type
|
||||
@@ -38,7 +39,7 @@ func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if argType != nil {
|
||||
for _, t := range a.argTypes {
|
||||
if argType.String() == t {
|
||||
return gosec.NewIssue(c, n, a.ID(), a.What, a.Severity, a.Confidence), nil
|
||||
return c.NewIssue(n, a.ID(), a.What, a.Severity, a.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,17 +49,17 @@ func (a *archive) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
}
|
||||
|
||||
// NewArchive creates a new rule which detects the file traversal when extracting zip/tar archives
|
||||
func NewArchive(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewArchive(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("path/filepath", "Join")
|
||||
calls.Add("path", "Join")
|
||||
return &archive{
|
||||
calls: calls,
|
||||
argTypes: []string{"*archive/zip.File", "*archive/tar.Header"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "File traversal when extracting zip/tar archive",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
96
vendor/github.com/securego/gosec/v2/rules/bad_defer.go
generated
vendored
96
vendor/github.com/securego/gosec/v2/rules/bad_defer.go
generated
vendored
@@ -1,96 +0,0 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
)
|
||||
|
||||
type deferType struct {
|
||||
typ string
|
||||
methods []string
|
||||
}
|
||||
|
||||
type badDefer struct {
|
||||
gosec.MetaData
|
||||
types []deferType
|
||||
}
|
||||
|
||||
func (r *badDefer) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func normalize(typ string) string {
|
||||
return strings.TrimPrefix(typ, "*")
|
||||
}
|
||||
|
||||
func contains(methods []string, method string) bool {
|
||||
for _, m := range methods {
|
||||
if m == method {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if deferStmt, ok := n.(*ast.DeferStmt); ok {
|
||||
for _, deferTyp := range r.types {
|
||||
if typ, method, err := gosec.GetCallInfo(deferStmt.Call, c); err == nil {
|
||||
if normalize(typ) == deferTyp.typ && contains(deferTyp.methods, method) {
|
||||
return gosec.NewIssue(c, n, r.ID(), fmt.Sprintf(r.What, method, typ), r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewDeferredClosing detects unsafe defer of error returning methods
|
||||
func NewDeferredClosing(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &badDefer{
|
||||
types: []deferType{
|
||||
{
|
||||
typ: "os.File",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "io.ReadCloser",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "io.WriteCloser",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "io.ReadWriteCloser",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "io.ReadSeekCloser",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "io.Closer",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "net.Conn",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
{
|
||||
typ: "net.Listener",
|
||||
methods: []string{"Close"},
|
||||
},
|
||||
},
|
||||
MetaData: gosec.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
What: "Deferring unsafe method %q on type %q",
|
||||
},
|
||||
}, []ast.Node{(*ast.DeferStmt)(nil)}
|
||||
}
|
||||
19
vendor/github.com/securego/gosec/v2/rules/bind.go
generated
vendored
19
vendor/github.com/securego/gosec/v2/rules/bind.go
generated
vendored
@@ -19,11 +19,12 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// Looks for net.Listen("0.0.0.0") or net.Listen(":8080")
|
||||
type bindsToAllNetworkInterfaces struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
pattern *regexp.Regexp
|
||||
}
|
||||
@@ -32,7 +33,7 @@ func (r *bindsToAllNetworkInterfaces) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
callExpr := r.calls.ContainsPkgCallExpr(n, c, false)
|
||||
if callExpr == nil {
|
||||
return nil, nil
|
||||
@@ -42,14 +43,14 @@ func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gosec.Context) (*gose
|
||||
if bl, ok := arg.(*ast.BasicLit); ok {
|
||||
if arg, err := gosec.GetString(bl); err == nil {
|
||||
if r.pattern.MatchString(arg) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
} else if ident, ok := arg.(*ast.Ident); ok {
|
||||
values := gosec.GetIdentStringValues(ident)
|
||||
for _, value := range values {
|
||||
if r.pattern.MatchString(value) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -57,7 +58,7 @@ func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gosec.Context) (*gose
|
||||
values := gosec.GetCallStringArgsValues(callExpr.Args[0], c)
|
||||
for _, value := range values {
|
||||
if r.pattern.MatchString(value) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,17 +67,17 @@ func (r *bindsToAllNetworkInterfaces) Match(n ast.Node, c *gosec.Context) (*gose
|
||||
|
||||
// NewBindsToAllNetworkInterfaces detects socket connections that are setup to
|
||||
// listen on all network interfaces.
|
||||
func NewBindsToAllNetworkInterfaces(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewBindsToAllNetworkInterfaces(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("net", "Listen")
|
||||
calls.Add("crypto/tls", "Listen")
|
||||
return &bindsToAllNetworkInterfaces{
|
||||
calls: calls,
|
||||
pattern: regexp.MustCompile(`^(0.0.0.0|:).*$`),
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "Binds to all network interfaces",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
21
vendor/github.com/securego/gosec/v2/rules/blocklist.go
generated
vendored
21
vendor/github.com/securego/gosec/v2/rules/blocklist.go
generated
vendored
@@ -19,27 +19,28 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type blocklistedImport struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
Blocklisted map[string]string
|
||||
}
|
||||
|
||||
func unquote(original string) string {
|
||||
copy := strings.TrimSpace(original)
|
||||
copy = strings.TrimLeft(copy, `"`)
|
||||
return strings.TrimRight(copy, `"`)
|
||||
cleaned := strings.TrimSpace(original)
|
||||
cleaned = strings.TrimLeft(cleaned, `"`)
|
||||
return strings.TrimRight(cleaned, `"`)
|
||||
}
|
||||
|
||||
func (r *blocklistedImport) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *blocklistedImport) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *blocklistedImport) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if node, ok := n.(*ast.ImportSpec); ok {
|
||||
if description, ok := r.Blocklisted[unquote(node.Path.Value)]; ok {
|
||||
return gosec.NewIssue(c, node, r.ID(), description, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(node, r.ID(), description, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
@@ -47,12 +48,12 @@ func (r *blocklistedImport) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, e
|
||||
|
||||
// NewBlocklistedImports reports when a blocklisted import is being used.
|
||||
// Typically when a deprecated technology is being used.
|
||||
func NewBlocklistedImports(id string, conf gosec.Config, blocklist map[string]string) (gosec.Rule, []ast.Node) {
|
||||
func NewBlocklistedImports(id string, _ gosec.Config, blocklist map[string]string) (gosec.Rule, []ast.Node) {
|
||||
return &blocklistedImport{
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
},
|
||||
Blocklisted: blocklist,
|
||||
}, []ast.Node{(*ast.ImportSpec)(nil)}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/decompression-bomb.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/decompression-bomb.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type decompressionBombCheck struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
readerCalls gosec.CallList
|
||||
copyCalls gosec.CallList
|
||||
}
|
||||
@@ -40,7 +41,7 @@ func containsReaderCall(node ast.Node, ctx *gosec.Context, list gosec.CallList)
|
||||
return list.Contains(s, idt)
|
||||
}
|
||||
|
||||
func (d *decompressionBombCheck) Match(node ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (d *decompressionBombCheck) Match(node ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
var readerVarObj map[*ast.Object]struct{}
|
||||
|
||||
// To check multiple lines, ctx.PassedValues is used to store temporary data.
|
||||
@@ -72,7 +73,7 @@ func (d *decompressionBombCheck) Match(node ast.Node, ctx *gosec.Context) (*gose
|
||||
if idt, ok := n.Args[1].(*ast.Ident); ok {
|
||||
if _, ok := readerVarObj[idt.Obj]; ok {
|
||||
// Detect io.Copy(x, r)
|
||||
return gosec.NewIssue(ctx, n, d.ID(), d.What, d.Severity, d.Confidence), nil
|
||||
return ctx.NewIssue(n, d.ID(), d.What, d.Severity, d.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +83,7 @@ func (d *decompressionBombCheck) Match(node ast.Node, ctx *gosec.Context) (*gose
|
||||
}
|
||||
|
||||
// NewDecompressionBombCheck detects if there is potential DoS vulnerability via decompression bomb
|
||||
func NewDecompressionBombCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewDecompressionBombCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
readerCalls := gosec.NewCallList()
|
||||
readerCalls.Add("compress/gzip", "NewReader")
|
||||
readerCalls.AddAll("compress/zlib", "NewReader", "NewReaderDict")
|
||||
@@ -98,10 +99,10 @@ func NewDecompressionBombCheck(id string, conf gosec.Config) (gosec.Rule, []ast.
|
||||
copyCalls.Add("io", "CopyBuffer")
|
||||
|
||||
return &decompressionBombCheck{
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.Medium,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.Medium,
|
||||
What: "Potential DoS vulnerability via decompression bomb",
|
||||
},
|
||||
readerCalls: readerCalls,
|
||||
|
||||
19
vendor/github.com/securego/gosec/v2/rules/directory-traversal.go
generated
vendored
19
vendor/github.com/securego/gosec/v2/rules/directory-traversal.go
generated
vendored
@@ -5,18 +5,19 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type traversal struct {
|
||||
pattern *regexp.Regexp
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
}
|
||||
|
||||
func (r *traversal) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *traversal) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *traversal) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.CallExpr:
|
||||
return r.matchCallExpr(node, ctx)
|
||||
@@ -24,14 +25,14 @@ func (r *traversal) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *traversal) matchCallExpr(assign *ast.CallExpr, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *traversal) matchCallExpr(assign *ast.CallExpr, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
for _, i := range assign.Args {
|
||||
if basiclit, ok1 := i.(*ast.BasicLit); ok1 {
|
||||
if fun, ok2 := assign.Fun.(*ast.SelectorExpr); ok2 {
|
||||
if x, ok3 := fun.X.(*ast.Ident); ok3 {
|
||||
string := x.Name + "." + fun.Sel.Name + "(" + basiclit.Value + ")"
|
||||
if r.pattern.MatchString(string) {
|
||||
return gosec.NewIssue(ctx, assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
str := x.Name + "." + fun.Sel.Name + "(" + basiclit.Value + ")"
|
||||
if r.pattern.MatchString(str) {
|
||||
return ctx.NewIssue(assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,11 +55,11 @@ func NewDirectoryTraversal(id string, conf gosec.Config) (gosec.Rule, []ast.Node
|
||||
|
||||
return &traversal{
|
||||
pattern: regexp.MustCompile(pattern),
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Potential directory traversal",
|
||||
Confidence: gosec.Medium,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: issue.Medium,
|
||||
Severity: issue.Medium,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/errors.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/errors.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type noErrorCheck struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
whitelist gosec.CallList
|
||||
}
|
||||
|
||||
@@ -49,7 +50,7 @@ func returnsError(callExpr *ast.CallExpr, ctx *gosec.Context) int {
|
||||
return -1
|
||||
}
|
||||
|
||||
func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
switch stmt := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
cfg := ctx.Config
|
||||
@@ -61,7 +62,7 @@ func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, erro
|
||||
return nil, nil
|
||||
}
|
||||
if id, ok := stmt.Lhs[pos].(*ast.Ident); ok && id.Name == "_" {
|
||||
return gosec.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return ctx.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,7 +71,7 @@ func (r *noErrorCheck) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, erro
|
||||
if callExpr, ok := stmt.X.(*ast.CallExpr); ok && r.whitelist.ContainsCallExpr(stmt.X, ctx) == nil {
|
||||
pos := returnsError(callExpr, ctx)
|
||||
if pos >= 0 {
|
||||
return gosec.NewIssue(ctx, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return ctx.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,10 +101,10 @@ func NewNoErrorCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
}
|
||||
|
||||
return &noErrorCheck{
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Low,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Low,
|
||||
Confidence: issue.High,
|
||||
What: "Errors unhandled.",
|
||||
},
|
||||
whitelist: whitelist,
|
||||
|
||||
25
vendor/github.com/securego/gosec/v2/rules/fileperms.go
generated
vendored
25
vendor/github.com/securego/gosec/v2/rules/fileperms.go
generated
vendored
@@ -20,10 +20,11 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type filePermissions struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
mode int64
|
||||
pkgs []string
|
||||
calls []string
|
||||
@@ -54,12 +55,12 @@ func modeIsSubset(subset int64, superset int64) bool {
|
||||
return (subset | superset) == superset
|
||||
}
|
||||
|
||||
func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
for _, pkg := range r.pkgs {
|
||||
if callexpr, matched := gosec.MatchCallByPackage(n, c, pkg, r.calls...); matched {
|
||||
modeArg := callexpr.Args[len(callexpr.Args)-1]
|
||||
if mode, err := gosec.GetInt(modeArg); err == nil && !modeIsSubset(mode, r.mode) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,10 +74,10 @@ func NewWritePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
mode: mode,
|
||||
pkgs: []string{"io/ioutil", "os"},
|
||||
calls: []string{"WriteFile"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: fmt.Sprintf("Expect WriteFile permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
@@ -90,10 +91,10 @@ func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
mode: mode,
|
||||
pkgs: []string{"os"},
|
||||
calls: []string{"OpenFile", "Chmod"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: fmt.Sprintf("Expect file permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
@@ -107,10 +108,10 @@ func NewMkdirPerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
mode: mode,
|
||||
pkgs: []string{"os"},
|
||||
calls: []string{"Mkdir", "MkdirAll"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: fmt.Sprintf("Expect directory permissions to be %#o or less", mode),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
81
vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go
generated
vendored
81
vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go
generated
vendored
@@ -20,13 +20,16 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
zxcvbn "github.com/nbutton23/zxcvbn-go"
|
||||
zxcvbn "github.com/ccojocar/zxcvbn-go"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type credentials struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
pattern *regexp.Regexp
|
||||
patternValue *regexp.Regexp // Pattern for matching string values (LHS on assign statements)
|
||||
entropyThreshold float64
|
||||
perCharThreshold float64
|
||||
truncate int
|
||||
@@ -53,7 +56,7 @@ func (r *credentials) isHighEntropyString(str string) bool {
|
||||
entropyPerChar >= r.perCharThreshold))
|
||||
}
|
||||
|
||||
func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
return r.matchAssign(node, ctx)
|
||||
@@ -65,24 +68,41 @@ func (r *credentials) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *credentials) matchAssign(assign *ast.AssignStmt, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
for _, i := range assign.Lhs {
|
||||
if ident, ok := i.(*ast.Ident); ok {
|
||||
// First check LHS to find anything being assigned to variables whose name appears to be a cred
|
||||
if r.pattern.MatchString(ident.Name) {
|
||||
for _, e := range assign.Rhs {
|
||||
if val, err := gosec.GetString(e); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gosec.NewIssue(ctx, assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return ctx.NewIssue(assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that no names were matched, match the RHS to see if the actual values being assigned are creds
|
||||
for _, e := range assign.Rhs {
|
||||
val, err := gosec.GetString(e)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if r.patternValue.MatchString(val) {
|
||||
if r.ignoreEntropy || r.isHighEntropyString(val) {
|
||||
return ctx.NewIssue(assign, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
// Running match against the variable name(s) first. Will catch any creds whose var name matches the pattern,
|
||||
// then will go back over to check the values themselves.
|
||||
for index, ident := range valueSpec.Names {
|
||||
if r.pattern.MatchString(ident.Name) && valueSpec.Values != nil {
|
||||
// const foo, bar = "same value"
|
||||
@@ -91,15 +111,27 @@ func (r *credentials) matchValueSpec(valueSpec *ast.ValueSpec, ctx *gosec.Contex
|
||||
}
|
||||
if val, err := gosec.GetString(valueSpec.Values[index]); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gosec.NewIssue(ctx, valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return ctx.NewIssue(valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that no variable names have been matched, match the actual values to find any creds
|
||||
for _, ident := range valueSpec.Values {
|
||||
if val, err := gosec.GetString(ident); err == nil {
|
||||
if r.patternValue.MatchString(val) {
|
||||
if r.ignoreEntropy || r.isHighEntropyString(val) {
|
||||
return ctx.NewIssue(valueSpec, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
if binaryExpr.Op == token.EQL || binaryExpr.Op == token.NEQ {
|
||||
ident, ok := binaryExpr.X.(*ast.Ident)
|
||||
if !ok {
|
||||
@@ -113,7 +145,23 @@ func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.
|
||||
}
|
||||
if val, err := gosec.GetString(valueNode); err == nil {
|
||||
if r.ignoreEntropy || (!r.ignoreEntropy && r.isHighEntropyString(val)) {
|
||||
return gosec.NewIssue(ctx, binaryExpr, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return ctx.NewIssue(binaryExpr, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that the variable names have been checked, and no matches were found, make sure that
|
||||
// either the left or right operands is a string literal so we can match the value.
|
||||
identStrConst, ok := binaryExpr.X.(*ast.BasicLit)
|
||||
if !ok {
|
||||
identStrConst, ok = binaryExpr.Y.(*ast.BasicLit)
|
||||
}
|
||||
|
||||
if ok && identStrConst.Kind == token.STRING {
|
||||
s, _ := gosec.GetString(identStrConst)
|
||||
if r.patternValue.MatchString(s) {
|
||||
if r.ignoreEntropy || r.isHighEntropyString(s) {
|
||||
return ctx.NewIssue(binaryExpr, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +173,7 @@ func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec.
|
||||
// assigned to variables that appear to be related to credentials.
|
||||
func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
pattern := `(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred`
|
||||
patternValue := "(?i)(^(.*[:;,](\\s)*)?[a-f0-9]{64}$)|(AIza[0-9A-Za-z-_]{35})|(^(.*[:;,](\\s)*)?github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}$)|(^(.*[:;,](\\s)*)?[0-9a-zA-Z-_]{24}$)"
|
||||
entropyThreshold := 80.0
|
||||
perCharThreshold := 3.0
|
||||
ignoreEntropy := false
|
||||
@@ -136,6 +185,13 @@ func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.No
|
||||
pattern = cfgPattern
|
||||
}
|
||||
}
|
||||
|
||||
if configPatternValue, ok := conf["patternValue"]; ok {
|
||||
if cfgPatternValue, ok := configPatternValue.(string); ok {
|
||||
patternValue = cfgPatternValue
|
||||
}
|
||||
}
|
||||
|
||||
if configIgnoreEntropy, ok := conf["ignore_entropy"]; ok {
|
||||
if cfgIgnoreEntropy, ok := configIgnoreEntropy.(bool); ok {
|
||||
ignoreEntropy = cfgIgnoreEntropy
|
||||
@@ -166,15 +222,16 @@ func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.No
|
||||
|
||||
return &credentials{
|
||||
pattern: regexp.MustCompile(pattern),
|
||||
patternValue: regexp.MustCompile(patternValue),
|
||||
entropyThreshold: entropyThreshold,
|
||||
perCharThreshold: perCharThreshold,
|
||||
ignoreEntropy: ignoreEntropy,
|
||||
truncate: truncateString,
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Potential hardcoded credentials",
|
||||
Confidence: gosec.Low,
|
||||
Severity: gosec.High,
|
||||
Confidence: issue.Low,
|
||||
Severity: issue.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.AssignStmt)(nil), (*ast.ValueSpec)(nil), (*ast.BinaryExpr)(nil)}
|
||||
}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/http_serve.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/http_serve.go
generated
vendored
@@ -4,10 +4,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type httpServeWithoutTimeouts struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
@@ -16,23 +17,23 @@ func (r *httpServeWithoutTimeouts) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *httpServeWithoutTimeouts) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
func (r *httpServeWithoutTimeouts) Match(n ast.Node, c *gosec.Context) (gi *issue.Issue, err error) {
|
||||
if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewHTTPServeWithoutTimeouts detects use of net/http serve functions that have no support for setting timeouts.
|
||||
func NewHTTPServeWithoutTimeouts(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewHTTPServeWithoutTimeouts(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &httpServeWithoutTimeouts{
|
||||
pkg: "net/http",
|
||||
calls: []string{"ListenAndServe", "ListenAndServeTLS", "Serve", "ServeTLS"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Use of net/http serve function that has no support for setting timeouts",
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
||||
39
vendor/github.com/securego/gosec/v2/rules/implicit_aliasing.go
generated
vendored
39
vendor/github.com/securego/gosec/v2/rules/implicit_aliasing.go
generated
vendored
@@ -5,10 +5,11 @@ import (
|
||||
"go/token"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type implicitAliasing struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
aliases map[*ast.Object]struct{}
|
||||
rightBrace token.Pos
|
||||
acceptableAlias []*ast.UnaryExpr
|
||||
@@ -27,7 +28,27 @@ func containsUnary(exprs []*ast.UnaryExpr, expr *ast.UnaryExpr) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *implicitAliasing) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func getIdentExpr(expr ast.Expr) *ast.Ident {
|
||||
switch node := expr.(type) {
|
||||
case *ast.Ident:
|
||||
return node
|
||||
case *ast.SelectorExpr:
|
||||
return getIdentExpr(node.X)
|
||||
case *ast.UnaryExpr:
|
||||
switch e := node.X.(type) {
|
||||
case *ast.Ident:
|
||||
return e
|
||||
case *ast.SelectorExpr:
|
||||
return getIdentExpr(e.X)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *implicitAliasing) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.RangeStmt:
|
||||
// When presented with a range statement, get the underlying Object bound to
|
||||
@@ -71,9 +92,9 @@ func (r *implicitAliasing) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, er
|
||||
}
|
||||
|
||||
// If we find a unary op of & (reference) of an object within r.aliases, complain.
|
||||
if ident, ok := node.X.(*ast.Ident); ok && node.Op.String() == "&" {
|
||||
if _, contains := r.aliases[ident.Obj]; contains {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
if identExpr := getIdentExpr(node); identExpr != nil && node.Op.String() == "&" {
|
||||
if _, contains := r.aliases[identExpr.Obj]; contains {
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
case *ast.ReturnStmt:
|
||||
@@ -89,15 +110,15 @@ func (r *implicitAliasing) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, er
|
||||
}
|
||||
|
||||
// NewImplicitAliasing detects implicit memory aliasing of type: for blah := SomeCall() {... SomeOtherCall(&blah) ...}
|
||||
func NewImplicitAliasing(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewImplicitAliasing(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &implicitAliasing{
|
||||
aliases: make(map[*ast.Object]struct{}),
|
||||
rightBrace: token.NoPos,
|
||||
acceptableAlias: make([]*ast.UnaryExpr, 0),
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.Medium,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.Medium,
|
||||
What: "Implicit memory aliasing in for loop.",
|
||||
},
|
||||
}, []ast.Node{(*ast.RangeStmt)(nil), (*ast.UnaryExpr)(nil), (*ast.ReturnStmt)(nil)}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/integer_overflow.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/integer_overflow.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type integerOverflowCheck struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
}
|
||||
|
||||
@@ -30,7 +31,7 @@ func (i *integerOverflowCheck) ID() string {
|
||||
return i.MetaData.ID
|
||||
}
|
||||
|
||||
func (i *integerOverflowCheck) Match(node ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (i *integerOverflowCheck) Match(node ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
var atoiVarObj map[*ast.Object]ast.Node
|
||||
|
||||
// To check multiple lines, ctx.PassedValues is used to store temporary data.
|
||||
@@ -63,7 +64,7 @@ func (i *integerOverflowCheck) Match(node ast.Node, ctx *gosec.Context) (*gosec.
|
||||
if idt, ok := n.Args[0].(*ast.Ident); ok {
|
||||
if _, ok := atoiVarObj[idt.Obj]; ok {
|
||||
// Detect int32(v) and int16(v)
|
||||
return gosec.NewIssue(ctx, n, i.ID(), i.What, i.Severity, i.Confidence), nil
|
||||
return ctx.NewIssue(n, i.ID(), i.What, i.Severity, i.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,14 +75,14 @@ func (i *integerOverflowCheck) Match(node ast.Node, ctx *gosec.Context) (*gosec.
|
||||
}
|
||||
|
||||
// NewIntegerOverflowCheck detects if there is potential Integer OverFlow
|
||||
func NewIntegerOverflowCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewIntegerOverflowCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("strconv", "Atoi")
|
||||
return &integerOverflowCheck{
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.High,
|
||||
Confidence: gosec.Medium,
|
||||
Severity: issue.High,
|
||||
Confidence: issue.Medium,
|
||||
What: "Potential Integer overflow made by strconv.Atoi result conversion to int16/32",
|
||||
},
|
||||
calls: calls,
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/math_big_rat.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/math_big_rat.go
generated
vendored
@@ -4,10 +4,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type usingOldMathBig struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
}
|
||||
|
||||
@@ -15,18 +16,18 @@ func (r *usingOldMathBig) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usingOldMathBig) Match(node ast.Node, ctx *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
func (r *usingOldMathBig) Match(node ast.Node, ctx *gosec.Context) (gi *issue.Issue, err error) {
|
||||
if callExpr := r.calls.ContainsPkgCallExpr(node, ctx, false); callExpr == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
confidence := gosec.Low
|
||||
confidence := issue.Low
|
||||
major, minor, build := gosec.GoVersion()
|
||||
if major == 1 && (minor == 16 && build < 14 || minor == 17 && build < 7) {
|
||||
confidence = gosec.Medium
|
||||
confidence = issue.Medium
|
||||
}
|
||||
|
||||
return gosec.NewIssue(ctx, node, r.ID(), r.What, r.Severity, confidence), nil
|
||||
return ctx.NewIssue(node, r.ID(), r.What, r.Severity, confidence), nil
|
||||
}
|
||||
|
||||
// NewUsingOldMathBig rule detects the use of Rat.SetString from math/big.
|
||||
@@ -35,10 +36,10 @@ func NewUsingOldMathBig(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls.Add("math/big.Rat", "SetString")
|
||||
return &usingOldMathBig{
|
||||
calls: calls,
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Potential uncontrolled memory consumption in Rat.SetString (CVE-2022-23772)",
|
||||
Severity: gosec.High,
|
||||
Severity: issue.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/pprof.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/pprof.go
generated
vendored
@@ -4,10 +4,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type pprofCheck struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
importPath string
|
||||
importName string
|
||||
}
|
||||
@@ -18,22 +19,22 @@ func (p *pprofCheck) ID() string {
|
||||
}
|
||||
|
||||
// Match checks for pprof imports
|
||||
func (p *pprofCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (p *pprofCheck) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if node, ok := n.(*ast.ImportSpec); ok {
|
||||
if p.importPath == unquote(node.Path.Value) && node.Name != nil && p.importName == node.Name.Name {
|
||||
return gosec.NewIssue(c, node, p.ID(), p.What, p.Severity, p.Confidence), nil
|
||||
return c.NewIssue(node, p.ID(), p.What, p.Severity, p.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewPprofCheck detects when the profiling endpoint is automatically exposed
|
||||
func NewPprofCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewPprofCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &pprofCheck{
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.High,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.High,
|
||||
Confidence: issue.High,
|
||||
What: "Profiling endpoint is automatically exposed on /debug/pprof",
|
||||
},
|
||||
importPath: "net/http/pprof",
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/rand.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/rand.go
generated
vendored
@@ -18,10 +18,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type weakRand struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
funcNames []string
|
||||
packagePath string
|
||||
}
|
||||
@@ -30,10 +31,10 @@ func (w *weakRand) ID() string {
|
||||
return w.MetaData.ID
|
||||
}
|
||||
|
||||
func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
for _, funcName := range w.funcNames {
|
||||
if _, matched := gosec.MatchCallByPackage(n, c, w.packagePath, funcName); matched {
|
||||
return gosec.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
return c.NewIssue(n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,17 +42,17 @@ func (w *weakRand) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
}
|
||||
|
||||
// NewWeakRandCheck detects the use of random number generator that isn't cryptographically secure
|
||||
func NewWeakRandCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewWeakRandCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &weakRand{
|
||||
funcNames: []string{
|
||||
"New", "Read", "Float32", "Float64", "Int", "Int31",
|
||||
"Int31n", "Int63", "Int63n", "Intn", "NormalFloat64", "Uint32", "Uint64",
|
||||
},
|
||||
packagePath: "math/rand",
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.High,
|
||||
Confidence: gosec.Medium,
|
||||
Severity: issue.High,
|
||||
Confidence: issue.Medium,
|
||||
What: "Use of weak random number generator (math/rand instead of crypto/rand)",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
25
vendor/github.com/securego/gosec/v2/rules/readfile.go
generated
vendored
25
vendor/github.com/securego/gosec/v2/rules/readfile.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type readfile struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
gosec.CallList
|
||||
pathJoin gosec.CallList
|
||||
clean gosec.CallList
|
||||
@@ -80,13 +81,17 @@ func (r *readfile) isFilepathClean(n *ast.Ident, c *gosec.Context) bool {
|
||||
func (r *readfile) trackFilepathClean(n ast.Node) {
|
||||
if clean, ok := n.(*ast.CallExpr); ok && len(clean.Args) > 0 {
|
||||
if ident, ok := clean.Args[0].(*ast.Ident); ok {
|
||||
r.cleanedVar[ident.Obj.Decl] = n
|
||||
// ident.Obj may be nil if the referenced declaration is in another file. It also may be incorrect.
|
||||
// if it is nil, do not follow it.
|
||||
if ident.Obj != nil {
|
||||
r.cleanedVar[ident.Obj.Decl] = n
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Match inspects AST nodes to determine if the match the methods `os.Open` or `ioutil.ReadFile`
|
||||
func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *readfile) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if node := r.clean.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||
r.trackFilepathClean(n)
|
||||
return nil, nil
|
||||
@@ -96,14 +101,14 @@ func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
// eg. os.Open(filepath.Join("/tmp/", file))
|
||||
if callExpr, ok := arg.(*ast.CallExpr); ok {
|
||||
if r.isJoinFunc(callExpr, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
// handles binary string concatenation eg. ioutil.Readfile("/tmp/" + file + "/blob")
|
||||
if binExp, ok := arg.(*ast.BinaryExpr); ok {
|
||||
// resolve all found identities from the BinaryExpr
|
||||
if _, ok := gosec.FindVarIdentities(binExp, c); ok {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +117,7 @@ func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
if _, ok := obj.(*types.Var); ok &&
|
||||
!gosec.TryResolve(ident, c) &&
|
||||
!r.isFilepathClean(ident, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,16 +126,16 @@ func (r *readfile) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
}
|
||||
|
||||
// NewReadFile detects cases where we read files
|
||||
func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewReadFile(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &readfile{
|
||||
pathJoin: gosec.NewCallList(),
|
||||
clean: gosec.NewCallList(),
|
||||
CallList: gosec.NewCallList(),
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Potential file inclusion via variable",
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
},
|
||||
cleanedVar: map[any]ast.Node{},
|
||||
}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/rsa.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/rsa.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type weakKeyStrength struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
bits int
|
||||
}
|
||||
@@ -31,27 +32,27 @@ func (w *weakKeyStrength) ID() string {
|
||||
return w.MetaData.ID
|
||||
}
|
||||
|
||||
func (w *weakKeyStrength) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (w *weakKeyStrength) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if callExpr := w.calls.ContainsPkgCallExpr(n, c, false); callExpr != nil {
|
||||
if bits, err := gosec.GetInt(callExpr.Args[1]); err == nil && bits < (int64)(w.bits) {
|
||||
return gosec.NewIssue(c, n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
return c.NewIssue(n, w.ID(), w.What, w.Severity, w.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewWeakKeyStrength builds a rule that detects RSA keys < 2048 bits
|
||||
func NewWeakKeyStrength(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewWeakKeyStrength(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("crypto/rsa", "GenerateKey")
|
||||
bits := 2048
|
||||
return &weakKeyStrength{
|
||||
calls: calls,
|
||||
bits: bits,
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: fmt.Sprintf("RSA keys should be at least %d bits", bits),
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
2
vendor/github.com/securego/gosec/v2/rules/rulelist.go
generated
vendored
2
vendor/github.com/securego/gosec/v2/rules/rulelist.go
generated
vendored
@@ -91,7 +91,6 @@ func Generate(trackSuppressions bool, filters ...RuleFilter) RuleList {
|
||||
{"G304", "File path provided as taint input", NewReadFile},
|
||||
{"G305", "File path traversal when extracting zip archive", NewArchive},
|
||||
{"G306", "Poor file permissions used when writing to a file", NewWritePerms},
|
||||
{"G307", "Unsafe defer call of a method returning an error", NewDeferredClosing},
|
||||
|
||||
// crypto
|
||||
{"G401", "Detect the usage of DES, RC4, MD5 or SHA1", NewUsesWeakCryptography},
|
||||
@@ -108,6 +107,7 @@ func Generate(trackSuppressions bool, filters ...RuleFilter) RuleList {
|
||||
|
||||
// memory safety
|
||||
{"G601", "Implicit memory aliasing in RangeStmt", NewImplicitAliasing},
|
||||
{"G602", "Slice access out of bounds", NewSliceBoundCheck},
|
||||
}
|
||||
|
||||
ruleMap := make(map[string]RuleDefinition)
|
||||
|
||||
405
vendor/github.com/securego/gosec/v2/rules/slice_bounds.go
generated
vendored
Normal file
405
vendor/github.com/securego/gosec/v2/rules/slice_bounds.go
generated
vendored
Normal file
@@ -0,0 +1,405 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// sliceOutOfBounds is a rule which checks for slices which are accessed outside their capacity,
|
||||
// either through indexing it out of bounds or through slice expressions whose low or high index
|
||||
// are out of bounds.
|
||||
type sliceOutOfBounds struct {
|
||||
sliceCaps map[*ast.CallExpr]map[string]*int64 // Capacities of slices. Maps function call -> var name -> value.
|
||||
currentScope *types.Scope // Current scope. Map is cleared when scope changes.
|
||||
currentFuncName string // Current function.
|
||||
funcCallArgs map[string][]*int64 // Caps to load once a func declaration is scanned.
|
||||
issue.MetaData // Metadata for this rule.
|
||||
}
|
||||
|
||||
// ID returns the rule ID for sliceOutOfBounds: G602.
|
||||
func (s *sliceOutOfBounds) ID() string {
|
||||
return s.MetaData.ID
|
||||
}
|
||||
|
||||
func (s *sliceOutOfBounds) Match(node ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
if s.currentScope == nil {
|
||||
s.currentScope = ctx.Pkg.Scope()
|
||||
} else if s.currentScope != ctx.Pkg.Scope() {
|
||||
s.currentScope = ctx.Pkg.Scope()
|
||||
|
||||
// Clear slice map, since we are in a new scope
|
||||
sliceMapNil := make(map[string]*int64)
|
||||
sliceCaps := make(map[*ast.CallExpr]map[string]*int64)
|
||||
sliceCaps[nil] = sliceMapNil
|
||||
s.sliceCaps = sliceCaps
|
||||
}
|
||||
|
||||
switch node := node.(type) {
|
||||
case *ast.AssignStmt:
|
||||
return s.matchAssign(node, ctx)
|
||||
case *ast.SliceExpr:
|
||||
return s.matchSliceExpr(node, ctx)
|
||||
case *ast.IndexExpr:
|
||||
return s.matchIndexExpr(node, ctx)
|
||||
case *ast.FuncDecl:
|
||||
s.currentFuncName = node.Name.Name
|
||||
s.loadArgCaps(node)
|
||||
case *ast.CallExpr:
|
||||
if _, ok := node.Fun.(*ast.FuncLit); ok {
|
||||
// Do nothing with func literals for now.
|
||||
break
|
||||
}
|
||||
|
||||
sliceMap := make(map[string]*int64)
|
||||
s.sliceCaps[node] = sliceMap
|
||||
s.setupCallArgCaps(node, ctx)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// updateSliceCaps takes in a variable name and a map of calls we are updating the variables for to the updated values
|
||||
// and will add it to the sliceCaps map.
|
||||
func (s *sliceOutOfBounds) updateSliceCaps(varName string, caps map[*ast.CallExpr]*int64) {
|
||||
for callExpr, cap := range caps {
|
||||
s.sliceCaps[callExpr][varName] = cap
|
||||
}
|
||||
}
|
||||
|
||||
// getAllCalls returns all CallExprs that are calls to the given function.
|
||||
func (s *sliceOutOfBounds) getAllCalls(funcName string, ctx *gosec.Context) []*ast.CallExpr {
|
||||
calls := []*ast.CallExpr{}
|
||||
|
||||
for callExpr := range s.sliceCaps {
|
||||
if callExpr != nil {
|
||||
// Compare the names of the function the code is scanning with the current call we are iterating over
|
||||
_, callFuncName, err := gosec.GetCallInfo(callExpr, ctx)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if callFuncName == funcName {
|
||||
calls = append(calls, callExpr)
|
||||
}
|
||||
}
|
||||
}
|
||||
return calls
|
||||
}
|
||||
|
||||
// getSliceCapsForFunc gets all the capacities for slice with given name that are stored for each call to the passed function.
|
||||
func (s *sliceOutOfBounds) getSliceCapsForFunc(funcName string, varName string, ctx *gosec.Context) map[*ast.CallExpr]*int64 {
|
||||
caps := make(map[*ast.CallExpr]*int64)
|
||||
|
||||
calls := s.getAllCalls(funcName, ctx)
|
||||
for _, call := range calls {
|
||||
if callCaps, ok := s.sliceCaps[call]; ok {
|
||||
caps[call] = callCaps[varName]
|
||||
}
|
||||
}
|
||||
|
||||
return caps
|
||||
}
|
||||
|
||||
// setupCallArgCaps evaluates and saves the caps for any slices in the args so they can be validated when the function is scanned.
|
||||
func (s *sliceOutOfBounds) setupCallArgCaps(callExpr *ast.CallExpr, ctx *gosec.Context) {
|
||||
// Array of caps to be loaded once the function declaration is scanned
|
||||
funcCallArgs := []*int64{}
|
||||
|
||||
// Get function name
|
||||
_, funcName, err := gosec.GetCallInfo(callExpr, ctx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, arg := range callExpr.Args {
|
||||
switch node := arg.(type) {
|
||||
case *ast.SliceExpr:
|
||||
caps := s.evaluateSliceExpr(node, ctx)
|
||||
|
||||
// Simplifying assumption: use the lowest capacity. Storing all possible capacities for slices passed
|
||||
// to a function call would catch the most issues, but would require a data structure like a stack and a
|
||||
// reworking of the code for scanning itself. Use the lowest capacity, as this would be more likely to
|
||||
// raise an issue for being out of bounds.
|
||||
var lowestCap *int64
|
||||
for _, cap := range caps {
|
||||
if cap == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if lowestCap == nil {
|
||||
lowestCap = cap
|
||||
} else if *lowestCap > *cap {
|
||||
lowestCap = cap
|
||||
}
|
||||
}
|
||||
|
||||
if lowestCap == nil {
|
||||
funcCallArgs = append(funcCallArgs, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
// Now create a map of just this value to add it to the sliceCaps
|
||||
funcCallArgs = append(funcCallArgs, lowestCap)
|
||||
case *ast.Ident:
|
||||
ident := arg.(*ast.Ident)
|
||||
caps := s.getSliceCapsForFunc(s.currentFuncName, ident.Name, ctx)
|
||||
|
||||
var lowestCap *int64
|
||||
for _, cap := range caps {
|
||||
if cap == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if lowestCap == nil {
|
||||
lowestCap = cap
|
||||
} else if *lowestCap > *cap {
|
||||
lowestCap = cap
|
||||
}
|
||||
}
|
||||
|
||||
if lowestCap == nil {
|
||||
funcCallArgs = append(funcCallArgs, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
// Now create a map of just this value to add it to the sliceCaps
|
||||
funcCallArgs = append(funcCallArgs, lowestCap)
|
||||
default:
|
||||
funcCallArgs = append(funcCallArgs, nil)
|
||||
}
|
||||
}
|
||||
s.funcCallArgs[funcName] = funcCallArgs
|
||||
}
|
||||
|
||||
// loadArgCaps loads caps that were saved for a call to this function.
|
||||
func (s *sliceOutOfBounds) loadArgCaps(funcDecl *ast.FuncDecl) {
|
||||
sliceMap := make(map[string]*int64)
|
||||
funcName := funcDecl.Name.Name
|
||||
|
||||
// Create a dummmy call expr for the new function. This is so we can still store args for
|
||||
// functions which are not explicitly called in the code by other functions (specifically, main).
|
||||
ident := ast.NewIdent(funcName)
|
||||
dummyCallExpr := ast.CallExpr{
|
||||
Fun: ident,
|
||||
}
|
||||
|
||||
argCaps, ok := s.funcCallArgs[funcName]
|
||||
if !ok || len(argCaps) == 0 {
|
||||
s.sliceCaps[&dummyCallExpr] = sliceMap
|
||||
return
|
||||
}
|
||||
|
||||
params := funcDecl.Type.Params.List
|
||||
if len(params) > len(argCaps) {
|
||||
return // Length of params and args doesn't match, so don't do anything with this.
|
||||
}
|
||||
|
||||
for it := range params {
|
||||
capacity := argCaps[it]
|
||||
if capacity == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(params[it].Names) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if paramName := params[it].Names[0]; paramName != nil {
|
||||
sliceMap[paramName.Name] = capacity
|
||||
}
|
||||
}
|
||||
|
||||
s.sliceCaps[&dummyCallExpr] = sliceMap
|
||||
}
|
||||
|
||||
// matchSliceMake matches calls to make() and stores the capacity of the new slice in the map to compare against future slice usage.
|
||||
func (s *sliceOutOfBounds) matchSliceMake(funcCall *ast.CallExpr, sliceName string, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
_, funcName, err := gosec.GetCallInfo(funcCall, ctx)
|
||||
if err != nil || funcName != "make" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var capacityArg int
|
||||
if len(funcCall.Args) < 2 {
|
||||
return nil, nil // No size passed
|
||||
} else if len(funcCall.Args) == 2 {
|
||||
capacityArg = 1
|
||||
} else if len(funcCall.Args) == 3 {
|
||||
capacityArg = 2
|
||||
} else {
|
||||
return nil, nil // Unexpected, args should always be 2 or 3
|
||||
}
|
||||
|
||||
// Check and get the capacity of the slice passed to make. It must be a literal value, since we aren't evaluating the expression.
|
||||
sliceCapLit, ok := funcCall.Args[capacityArg].(*ast.BasicLit)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
capacity, err := gosec.GetInt(sliceCapLit)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
caps := s.getSliceCapsForFunc(s.currentFuncName, sliceName, ctx)
|
||||
for callExpr := range caps {
|
||||
caps[callExpr] = &capacity
|
||||
}
|
||||
|
||||
s.updateSliceCaps(sliceName, caps)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// evaluateSliceExpr takes a slice expression and evaluates what the capacity of said slice is for each of the
|
||||
// calls to the current function. Returns map of the call expressions of each call to the current function to
|
||||
// the evaluated capacities.
|
||||
func (s *sliceOutOfBounds) evaluateSliceExpr(node *ast.SliceExpr, ctx *gosec.Context) map[*ast.CallExpr]*int64 {
|
||||
// Get ident to get name
|
||||
ident, ok := node.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get cap of old slice to calculate this new slice's cap
|
||||
caps := s.getSliceCapsForFunc(s.currentFuncName, ident.Name, ctx)
|
||||
for callExpr, oldCap := range caps {
|
||||
if oldCap == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get and check low value
|
||||
lowIdent, ok := node.Low.(*ast.BasicLit)
|
||||
if ok && lowIdent != nil {
|
||||
low, _ := gosec.GetInt(lowIdent)
|
||||
|
||||
newCap := *oldCap - low
|
||||
caps[callExpr] = &newCap
|
||||
} else if lowIdent == nil { // If no lower bound, capacity will be same
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return caps
|
||||
}
|
||||
|
||||
// matchSliceAssignment matches slice assignments, calculates capacity of slice if possible to store it in map.
|
||||
func (s *sliceOutOfBounds) matchSliceAssignment(node *ast.SliceExpr, sliceName string, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
// First do the normal match that verifies the slice expr is not out of bounds
|
||||
if i, err := s.matchSliceExpr(node, ctx); err != nil {
|
||||
return i, fmt.Errorf("There was an error while matching a slice expression to check slice bounds for %s: %w", sliceName, err)
|
||||
}
|
||||
|
||||
// Now that the assignment is (presumably) successfully, we can calculate the capacity and add this new slice to the map
|
||||
caps := s.evaluateSliceExpr(node, ctx)
|
||||
s.updateSliceCaps(sliceName, caps)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// matchAssign matches checks if an assignment statement is making a slice, or if it is assigning a slice.
|
||||
func (s *sliceOutOfBounds) matchAssign(node *ast.AssignStmt, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
// Check RHS for calls to make() so we can get the actual size of the slice
|
||||
for it, i := range node.Rhs {
|
||||
// Get the slice name so we can associate the cap with the slice in the map
|
||||
sliceIdent, ok := node.Lhs[it].(*ast.Ident)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
sliceName := sliceIdent.Name
|
||||
|
||||
switch expr := i.(type) {
|
||||
case *ast.CallExpr: // Check for and handle call to make()
|
||||
return s.matchSliceMake(expr, sliceName, ctx)
|
||||
case *ast.SliceExpr: // Handle assignments to a slice
|
||||
return s.matchSliceAssignment(expr, sliceName, ctx)
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// matchSliceExpr validates that a given slice expression (eg, slice[10:30]) is not out of bounds.
|
||||
func (s *sliceOutOfBounds) matchSliceExpr(node *ast.SliceExpr, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
// First get the slice name so we can check the size in our map
|
||||
ident, ok := node.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get slice cap from the map to compare it against high and low
|
||||
caps := s.getSliceCapsForFunc(s.currentFuncName, ident.Name, ctx)
|
||||
|
||||
for _, cap := range caps {
|
||||
if cap == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Get and check high value
|
||||
highIdent, ok := node.High.(*ast.BasicLit)
|
||||
if ok && highIdent != nil {
|
||||
high, _ := gosec.GetInt(highIdent)
|
||||
if high > *cap {
|
||||
return ctx.NewIssue(node, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
|
||||
// Get and check low value
|
||||
lowIdent, ok := node.Low.(*ast.BasicLit)
|
||||
if ok && lowIdent != nil {
|
||||
low, _ := gosec.GetInt(lowIdent)
|
||||
if low > *cap {
|
||||
return ctx.NewIssue(node, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// matchIndexExpr validates that an index into a slice is not out of bounds.
|
||||
func (s *sliceOutOfBounds) matchIndexExpr(node *ast.IndexExpr, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
// First get the slice name so we can check the size in our map
|
||||
ident, ok := node.X.(*ast.Ident)
|
||||
if !ok {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Get slice cap from the map to compare it against high and low
|
||||
caps := s.getSliceCapsForFunc(s.currentFuncName, ident.Name, ctx)
|
||||
|
||||
for _, cap := range caps {
|
||||
if cap == nil {
|
||||
continue
|
||||
}
|
||||
// Get the index literal
|
||||
indexIdent, ok := node.Index.(*ast.BasicLit)
|
||||
if ok && indexIdent != nil {
|
||||
index, _ := gosec.GetInt(indexIdent)
|
||||
if index >= *cap {
|
||||
return ctx.NewIssue(node, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSliceBoundCheck attempts to find any slices being accessed out of bounds
|
||||
// by reslicing or by being indexed.
|
||||
func NewSliceBoundCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
sliceMap := make(map[*ast.CallExpr]map[string]*int64)
|
||||
|
||||
return &sliceOutOfBounds{
|
||||
sliceCaps: sliceMap,
|
||||
currentFuncName: "",
|
||||
funcCallArgs: make(map[string][]*int64),
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.Medium,
|
||||
What: "Potentially accessing slice out of bounds",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil), (*ast.FuncDecl)(nil), (*ast.AssignStmt)(nil), (*ast.SliceExpr)(nil), (*ast.IndexExpr)(nil)}
|
||||
}
|
||||
15
vendor/github.com/securego/gosec/v2/rules/slowloris.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/slowloris.go
generated
vendored
@@ -18,10 +18,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type slowloris struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
}
|
||||
|
||||
func (r *slowloris) ID() string {
|
||||
@@ -44,13 +45,13 @@ func containsReadHeaderTimeout(node *ast.CompositeLit) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *slowloris) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *slowloris) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
switch node := n.(type) {
|
||||
case *ast.CompositeLit:
|
||||
actualType := ctx.Info.TypeOf(node.Type)
|
||||
if actualType != nil && actualType.String() == "net/http.Server" {
|
||||
if !containsReadHeaderTimeout(node) {
|
||||
return gosec.NewIssue(ctx, node, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return ctx.NewIssue(node, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,13 +59,13 @@ func (r *slowloris) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error)
|
||||
}
|
||||
|
||||
// NewSlowloris attempts to find the http.Server struct and check if the ReadHeaderTimeout is configured.
|
||||
func NewSlowloris(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewSlowloris(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &slowloris{
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server",
|
||||
Confidence: gosec.Low,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: issue.Low,
|
||||
Severity: issue.Medium,
|
||||
},
|
||||
}, []ast.Node{(*ast.CompositeLit)(nil)}
|
||||
}
|
||||
|
||||
84
vendor/github.com/securego/gosec/v2/rules/sql.go
generated
vendored
84
vendor/github.com/securego/gosec/v2/rules/sql.go
generated
vendored
@@ -20,10 +20,11 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type sqlStatement struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
gosec.CallList
|
||||
|
||||
// Contains a list of patterns which must all match for the rule to match.
|
||||
@@ -97,6 +98,32 @@ func (s *sqlStrConcat) ID() string {
|
||||
return s.MetaData.ID
|
||||
}
|
||||
|
||||
// findInjectionInBranch walks diwb a set if expressions, and will create new issues if it finds SQL injections
|
||||
// This method assumes you've already verified that the branch contains SQL syntax
|
||||
func (s *sqlStrConcat) findInjectionInBranch(ctx *gosec.Context, branch []ast.Expr) *ast.BinaryExpr {
|
||||
for _, node := range branch {
|
||||
be, ok := node.(*ast.BinaryExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
operands := gosec.GetBinaryExprOperands(be)
|
||||
|
||||
for _, op := range operands {
|
||||
if _, ok := op.(*ast.BasicLit); ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if ident, ok := op.(*ast.Ident); ok && s.checkObject(ident, ctx) {
|
||||
continue
|
||||
}
|
||||
|
||||
return be
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// see if we can figure out what it is
|
||||
func (s *sqlStrConcat) checkObject(n *ast.Ident, c *gosec.Context) bool {
|
||||
if n.Obj != nil {
|
||||
@@ -113,7 +140,7 @@ func (s *sqlStrConcat) checkObject(n *ast.Ident, c *gosec.Context) bool {
|
||||
}
|
||||
|
||||
// checkQuery verifies if the query parameters is a string concatenation
|
||||
func (s *sqlStrConcat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (s *sqlStrConcat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
query, err := findQueryArg(call, ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -134,7 +161,29 @@ func (s *sqlStrConcat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gose
|
||||
if op, ok := op.(*ast.Ident); ok && s.checkObject(op, ctx) {
|
||||
continue
|
||||
}
|
||||
return gosec.NewIssue(ctx, be, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
return ctx.NewIssue(be, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the case where an injection occurs as an infixed string concatenation, ie "SELECT * FROM foo WHERE name = '" + os.Args[0] + "' AND 1=1"
|
||||
if id, ok := query.(*ast.Ident); ok {
|
||||
var match bool
|
||||
for _, str := range gosec.GetIdentStringValuesRecursive(id) {
|
||||
if s.MatchPatterns(str) {
|
||||
match = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !match {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
switch decl := id.Obj.Decl.(type) {
|
||||
case *ast.AssignStmt:
|
||||
if injection := s.findInjectionInBranch(ctx, decl.Rhs); injection != nil {
|
||||
return ctx.NewIssue(injection, s.ID(), s.What, s.Severity, s.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,7 +192,7 @@ func (s *sqlStrConcat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gose
|
||||
}
|
||||
|
||||
// Checks SQL query concatenation issues such as "SELECT * FROM table WHERE " + " ' OR 1=1"
|
||||
func (s *sqlStrConcat) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (s *sqlStrConcat) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
switch stmt := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, expr := range stmt.Rhs {
|
||||
@@ -156,20 +205,21 @@ func (s *sqlStrConcat) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, erro
|
||||
return s.checkQuery(sqlQueryCall, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSQLStrConcat looks for cases where we are building SQL strings via concatenation
|
||||
func NewSQLStrConcat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewSQLStrConcat(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &sqlStrConcat{
|
||||
sqlStatement: sqlStatement{
|
||||
patterns: []*regexp.Regexp{
|
||||
regexp.MustCompile(`(?i)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE) `),
|
||||
regexp.MustCompile("(?i)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE)( |\n|\r|\t)"),
|
||||
},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "SQL string concatenation",
|
||||
},
|
||||
CallList: gosec.NewCallList(),
|
||||
@@ -212,7 +262,7 @@ func (s *sqlStrFormat) constObject(e ast.Expr, c *gosec.Context) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *sqlStrFormat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (s *sqlStrFormat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
query, err := findQueryArg(call, ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -233,7 +283,7 @@ func (s *sqlStrFormat) checkQuery(call *ast.CallExpr, ctx *gosec.Context) (*gose
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) *gosec.Issue {
|
||||
func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) *issue.Issue {
|
||||
// argIndex changes the function argument which gets matched to the regex
|
||||
argIndex := 0
|
||||
if node := s.fmtCalls.ContainsPkgCallExpr(n, ctx, false); node != nil {
|
||||
@@ -286,14 +336,14 @@ func (s *sqlStrFormat) checkFormatting(n ast.Node, ctx *gosec.Context) *gosec.Is
|
||||
}
|
||||
}
|
||||
if s.MatchPatterns(formatter) {
|
||||
return gosec.NewIssue(ctx, n, s.ID(), s.What, s.Severity, s.Confidence)
|
||||
return ctx.NewIssue(n, s.ID(), s.What, s.Severity, s.Confidence)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check SQL query formatting issues such as "fmt.Sprintf("SELECT * FROM foo where '%s', userInput)"
|
||||
func (s *sqlStrFormat) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, error) {
|
||||
func (s *sqlStrFormat) Match(n ast.Node, ctx *gosec.Context) (*issue.Issue, error) {
|
||||
switch stmt := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, expr := range stmt.Rhs {
|
||||
@@ -323,7 +373,7 @@ func (s *sqlStrFormat) Match(n ast.Node, ctx *gosec.Context) (*gosec.Issue, erro
|
||||
}
|
||||
|
||||
// NewSQLStrFormat looks for cases where we're building SQL query strings using format strings
|
||||
func NewSQLStrFormat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewSQLStrFormat(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &sqlStrFormat{
|
||||
CallList: gosec.NewCallList(),
|
||||
fmtCalls: gosec.NewCallList(),
|
||||
@@ -334,10 +384,10 @@ func NewSQLStrFormat(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
regexp.MustCompile("(?i)(SELECT|DELETE|INSERT|UPDATE|INTO|FROM|WHERE)( |\n|\r|\t)"),
|
||||
regexp.MustCompile("%[^bdoxXfFp]"),
|
||||
},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "SQL string formatting",
|
||||
},
|
||||
},
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/ssh.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/ssh.go
generated
vendored
@@ -4,10 +4,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type sshHostKey struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
@@ -16,23 +17,23 @@ func (r *sshHostKey) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *sshHostKey) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
func (r *sshHostKey) Match(n ast.Node, c *gosec.Context) (gi *issue.Issue, err error) {
|
||||
if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSSHHostKey rule detects the use of insecure ssh HostKeyCallback.
|
||||
func NewSSHHostKey(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewSSHHostKey(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &sshHostKey{
|
||||
pkg: "golang.org/x/crypto/ssh",
|
||||
calls: []string{"InsecureIgnoreHostKey"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Use of ssh InsecureIgnoreHostKey should be audited",
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/ssrf.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/ssrf.go
generated
vendored
@@ -5,10 +5,11 @@ import (
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type ssrf struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
gosec.CallList
|
||||
}
|
||||
|
||||
@@ -40,25 +41,25 @@ func (r *ssrf) ResolveVar(n *ast.CallExpr, c *gosec.Context) bool {
|
||||
}
|
||||
|
||||
// Match inspects AST nodes to determine if certain net/http methods are called with variable input
|
||||
func (r *ssrf) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *ssrf) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
// Call expression is using http package directly
|
||||
if node := r.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||
if r.ResolveVar(node, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewSSRFCheck detects cases where HTTP requests are sent
|
||||
func NewSSRFCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewSSRFCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &ssrf{
|
||||
CallList: gosec.NewCallList(),
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Potential HTTP request made with variable url",
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.Medium,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.Medium,
|
||||
},
|
||||
}
|
||||
rule.AddAll("net/http", "Do", "Get", "Head", "Post", "PostForm", "RoundTrip")
|
||||
|
||||
19
vendor/github.com/securego/gosec/v2/rules/subproc.go
generated
vendored
19
vendor/github.com/securego/gosec/v2/rules/subproc.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"go/types"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type subprocess struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
gosec.CallList
|
||||
}
|
||||
|
||||
@@ -39,7 +40,7 @@ func (r *subprocess) ID() string {
|
||||
// is unsafe. For example:
|
||||
//
|
||||
// syscall.Exec("echo", "foobar" + tainted)
|
||||
func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if node := r.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||
args := node.Args
|
||||
if r.isContext(n, c) {
|
||||
@@ -64,7 +65,7 @@ func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
_, assignment := ident.Obj.Decl.(*ast.AssignStmt)
|
||||
if variable && assignment {
|
||||
if !gosec.TryResolve(ident, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil
|
||||
return c.NewIssue(n, r.ID(), "Subprocess launched with variable", issue.Medium, issue.High), nil
|
||||
}
|
||||
}
|
||||
case *ast.Field:
|
||||
@@ -74,21 +75,21 @@ func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
vv, vvok := obj.(*types.Var)
|
||||
|
||||
if vvok && vv.Parent().Lookup(ident.Name) == nil {
|
||||
return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil
|
||||
return c.NewIssue(n, r.ID(), "Subprocess launched with variable", issue.Medium, issue.High), nil
|
||||
}
|
||||
}
|
||||
case *ast.ValueSpec:
|
||||
_, valueSpec := ident.Obj.Decl.(*ast.ValueSpec)
|
||||
if variable && valueSpec {
|
||||
if !gosec.TryResolve(ident, c) {
|
||||
return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil
|
||||
return c.NewIssue(n, r.ID(), "Subprocess launched with variable", issue.Medium, issue.High), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if !gosec.TryResolve(arg, c) {
|
||||
// the arg is not a constant or a variable but instead a function call or os.Args[i]
|
||||
return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with a potential tainted input or cmd arguments", gosec.Medium, gosec.High), nil
|
||||
return c.NewIssue(n, r.ID(), "Subprocess launched with a potential tainted input or cmd arguments", issue.Medium, issue.High), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +97,7 @@ func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
}
|
||||
|
||||
// isContext checks whether or not the node is a CommandContext call or not
|
||||
// Thi is required in order to skip the first argument from the check.
|
||||
// This is required in order to skip the first argument from the check.
|
||||
func (r *subprocess) isContext(n ast.Node, ctx *gosec.Context) bool {
|
||||
selector, indent, err := gosec.GetCallInfo(n, ctx)
|
||||
if err != nil {
|
||||
@@ -109,8 +110,8 @@ func (r *subprocess) isContext(n ast.Node, ctx *gosec.Context) bool {
|
||||
}
|
||||
|
||||
// NewSubproc detects cases where we are forking out to an external process
|
||||
func NewSubproc(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &subprocess{gosec.MetaData{ID: id}, gosec.NewCallList()}
|
||||
func NewSubproc(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
rule := &subprocess{issue.MetaData{ID: id}, gosec.NewCallList()}
|
||||
rule.Add("os/exec", "Command")
|
||||
rule.Add("os/exec", "CommandContext")
|
||||
rule.Add("syscall", "Exec")
|
||||
|
||||
19
vendor/github.com/securego/gosec/v2/rules/tempfiles.go
generated
vendored
19
vendor/github.com/securego/gosec/v2/rules/tempfiles.go
generated
vendored
@@ -19,10 +19,11 @@ import (
|
||||
"regexp"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type badTempFile struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
args *regexp.Regexp
|
||||
argCalls gosec.CallList
|
||||
@@ -33,15 +34,15 @@ func (t *badTempFile) ID() string {
|
||||
return t.MetaData.ID
|
||||
}
|
||||
|
||||
func (t *badTempFile) findTempDirArgs(n ast.Node, c *gosec.Context, suspect ast.Node) *gosec.Issue {
|
||||
func (t *badTempFile) findTempDirArgs(n ast.Node, c *gosec.Context, suspect ast.Node) *issue.Issue {
|
||||
if s, e := gosec.GetString(suspect); e == nil {
|
||||
if t.args.MatchString(s) {
|
||||
return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence)
|
||||
return c.NewIssue(n, t.ID(), t.What, t.Severity, t.Confidence)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if ce := t.argCalls.ContainsPkgCallExpr(suspect, c, false); ce != nil {
|
||||
return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence)
|
||||
return c.NewIssue(n, t.ID(), t.What, t.Severity, t.Confidence)
|
||||
}
|
||||
if be, ok := suspect.(*ast.BinaryExpr); ok {
|
||||
if ops := gosec.GetBinaryExprOperands(be); len(ops) != 0 {
|
||||
@@ -55,7 +56,7 @@ func (t *badTempFile) findTempDirArgs(n ast.Node, c *gosec.Context, suspect ast.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *badTempFile) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
func (t *badTempFile) Match(n ast.Node, c *gosec.Context) (gi *issue.Issue, err error) {
|
||||
if node := t.calls.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||
return t.findTempDirArgs(n, c, node.Args[0]), nil
|
||||
}
|
||||
@@ -63,7 +64,7 @@ func (t *badTempFile) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err
|
||||
}
|
||||
|
||||
// NewBadTempFile detects direct writes to predictable path in temporary directory
|
||||
func NewBadTempFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewBadTempFile(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("io/ioutil", "WriteFile")
|
||||
calls.AddAll("os", "Create", "WriteFile")
|
||||
@@ -77,10 +78,10 @@ func NewBadTempFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
args: regexp.MustCompile(`^(/(usr|var))?/tmp(/.*)?$`),
|
||||
argCalls: argCalls,
|
||||
nestedCalls: nestedCalls,
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "File creation in shared tmp directory without using ioutil.Tempfile",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/templates.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/templates.go
generated
vendored
@@ -18,10 +18,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type templateCheck struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
calls gosec.CallList
|
||||
}
|
||||
|
||||
@@ -29,11 +30,11 @@ func (t *templateCheck) ID() string {
|
||||
return t.MetaData.ID
|
||||
}
|
||||
|
||||
func (t *templateCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (t *templateCheck) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if node := t.calls.ContainsPkgCallExpr(n, c, false); node != nil {
|
||||
for _, arg := range node.Args {
|
||||
if _, ok := arg.(*ast.BasicLit); !ok { // basic lits are safe
|
||||
return gosec.NewIssue(c, n, t.ID(), t.What, t.Severity, t.Confidence), nil
|
||||
return c.NewIssue(n, t.ID(), t.What, t.Severity, t.Confidence), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,7 +43,7 @@ func (t *templateCheck) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error
|
||||
|
||||
// NewTemplateCheck constructs the template check rule. This rule is used to
|
||||
// find use of templates where HTML/JS escaping is not being used
|
||||
func NewTemplateCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewTemplateCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := gosec.NewCallList()
|
||||
calls.Add("html/template", "HTML")
|
||||
calls.Add("html/template", "HTMLAttr")
|
||||
@@ -50,10 +51,10 @@ func NewTemplateCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls.Add("html/template", "URL")
|
||||
return &templateCheck{
|
||||
calls: calls,
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.Low,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.Low,
|
||||
What: "The used method does not auto-escape HTML. This can potentially lead to 'Cross-site Scripting' vulnerabilities, in case the attacker controls the input.",
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
|
||||
27
vendor/github.com/securego/gosec/v2/rules/tls.go
generated
vendored
27
vendor/github.com/securego/gosec/v2/rules/tls.go
generated
vendored
@@ -24,10 +24,11 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type insecureConfigTLS struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
MinVersion int64
|
||||
MaxVersion int64
|
||||
requiredType string
|
||||
@@ -49,13 +50,13 @@ func stringInSlice(a string, list []string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context) *gosec.Issue {
|
||||
func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context) *issue.Issue {
|
||||
if ciphers, ok := n.(*ast.CompositeLit); ok {
|
||||
for _, cipher := range ciphers.Elts {
|
||||
if ident, ok := cipher.(*ast.SelectorExpr); ok {
|
||||
if !stringInSlice(ident.Sel.Name, t.goodCiphers) {
|
||||
err := fmt.Sprintf("TLS Bad Cipher Suite: %s", ident.Sel.Name)
|
||||
return gosec.NewIssue(c, ident, t.ID(), err, gosec.High, gosec.High)
|
||||
return c.NewIssue(ident, t.ID(), err, issue.High, issue.High)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,7 +64,7 @@ func (t *insecureConfigTLS) processTLSCipherSuites(n ast.Node, c *gosec.Context)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSConf(n ast.Node, c *gosec.Context) *gosec.Issue {
|
||||
func (t *insecureConfigTLS) processTLSConf(n ast.Node, c *gosec.Context) *issue.Issue {
|
||||
if kve, ok := n.(*ast.KeyValueExpr); ok {
|
||||
issue := t.processTLSConfVal(kve.Key, kve.Value, c)
|
||||
if issue != nil {
|
||||
@@ -83,27 +84,27 @@ func (t *insecureConfigTLS) processTLSConf(n ast.Node, c *gosec.Context) *gosec.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) processTLSConfVal(key ast.Expr, value ast.Expr, c *gosec.Context) *gosec.Issue {
|
||||
func (t *insecureConfigTLS) processTLSConfVal(key ast.Expr, value ast.Expr, c *gosec.Context) *issue.Issue {
|
||||
if ident, ok := key.(*ast.Ident); ok {
|
||||
switch ident.Name {
|
||||
case "InsecureSkipVerify":
|
||||
if node, ok := value.(*ast.Ident); ok {
|
||||
if node.Name != "false" {
|
||||
return gosec.NewIssue(c, value, t.ID(), "TLS InsecureSkipVerify set true.", gosec.High, gosec.High)
|
||||
return c.NewIssue(value, t.ID(), "TLS InsecureSkipVerify set true.", issue.High, issue.High)
|
||||
}
|
||||
} else {
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gosec.NewIssue(c, value, t.ID(), "TLS InsecureSkipVerify may be true.", gosec.High, gosec.Low)
|
||||
return c.NewIssue(value, t.ID(), "TLS InsecureSkipVerify may be true.", issue.High, issue.Low)
|
||||
}
|
||||
|
||||
case "PreferServerCipherSuites":
|
||||
if node, ok := value.(*ast.Ident); ok {
|
||||
if node.Name == "false" {
|
||||
return gosec.NewIssue(c, value, t.ID(), "TLS PreferServerCipherSuites set false.", gosec.Medium, gosec.High)
|
||||
return c.NewIssue(value, t.ID(), "TLS PreferServerCipherSuites set false.", issue.Medium, issue.High)
|
||||
}
|
||||
} else {
|
||||
// TODO(tk): symbol tab look up to get the actual value
|
||||
return gosec.NewIssue(c, value, t.ID(), "TLS PreferServerCipherSuites may be false.", gosec.Medium, gosec.Low)
|
||||
return c.NewIssue(value, t.ID(), "TLS PreferServerCipherSuites may be false.", issue.Medium, issue.Low)
|
||||
}
|
||||
|
||||
case "MinVersion":
|
||||
@@ -188,16 +189,16 @@ func (t *insecureConfigTLS) mapVersion(version string) int64 {
|
||||
return v
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) checkVersion(n ast.Node, c *gosec.Context) *gosec.Issue {
|
||||
func (t *insecureConfigTLS) checkVersion(n ast.Node, c *gosec.Context) *issue.Issue {
|
||||
if t.actualMaxVersion == 0 && t.actualMinVersion >= t.MinVersion {
|
||||
// no warning is generated since the min version is greater than the secure min version
|
||||
return nil
|
||||
}
|
||||
if t.actualMinVersion < t.MinVersion {
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS MinVersion too low.", gosec.High, gosec.High)
|
||||
return c.NewIssue(n, t.ID(), "TLS MinVersion too low.", issue.High, issue.High)
|
||||
}
|
||||
if t.actualMaxVersion < t.MaxVersion {
|
||||
return gosec.NewIssue(c, n, t.ID(), "TLS MaxVersion too low.", gosec.High, gosec.High)
|
||||
return c.NewIssue(n, t.ID(), "TLS MaxVersion too low.", issue.High, issue.High)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -207,7 +208,7 @@ func (t *insecureConfigTLS) resetVersion() {
|
||||
t.actualMinVersion = 0
|
||||
}
|
||||
|
||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (t *insecureConfigTLS) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
if complit, ok := n.(*ast.CompositeLit); ok && complit.Type != nil {
|
||||
actualType := c.Info.TypeOf(complit.Type)
|
||||
if actualType != nil && actualType.String() == t.requiredType {
|
||||
|
||||
13
vendor/github.com/securego/gosec/v2/rules/tls_config.go
generated
vendored
13
vendor/github.com/securego/gosec/v2/rules/tls_config.go
generated
vendored
@@ -4,13 +4,14 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
// NewModernTLSCheck creates a check for Modern TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewModernTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewModernTLSCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
MetaData: issue.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0304,
|
||||
MaxVersion: 0x0304,
|
||||
@@ -24,9 +25,9 @@ func NewModernTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
|
||||
// NewIntermediateTLSCheck creates a check for Intermediate TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewIntermediateTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewIntermediateTLSCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
MetaData: issue.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0303,
|
||||
MaxVersion: 0x0304,
|
||||
@@ -50,9 +51,9 @@ func NewIntermediateTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.No
|
||||
|
||||
// NewOldTLSCheck creates a check for Old TLS ciphers
|
||||
// DO NOT EDIT - generated by tlsconfig tool
|
||||
func NewOldTLSCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewOldTLSCheck(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &insecureConfigTLS{
|
||||
MetaData: gosec.MetaData{ID: id},
|
||||
MetaData: issue.MetaData{ID: id},
|
||||
requiredType: "crypto/tls.Config",
|
||||
MinVersion: 0x0301,
|
||||
MaxVersion: 0x0304,
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/unsafe.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/unsafe.go
generated
vendored
@@ -18,10 +18,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type usingUnsafe struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
pkg string
|
||||
calls []string
|
||||
}
|
||||
@@ -30,24 +31,24 @@ func (r *usingUnsafe) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usingUnsafe) Match(n ast.Node, c *gosec.Context) (gi *gosec.Issue, err error) {
|
||||
func (r *usingUnsafe) Match(n ast.Node, c *gosec.Context) (gi *issue.Issue, err error) {
|
||||
if _, matches := gosec.MatchCallByPackage(n, c, r.pkg, r.calls...); matches {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsingUnsafe rule detects the use of the unsafe package. This is only
|
||||
// really useful for auditing purposes.
|
||||
func NewUsingUnsafe(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewUsingUnsafe(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
return &usingUnsafe{
|
||||
pkg: "unsafe",
|
||||
calls: []string{"Alignof", "Offsetof", "Sizeof", "Pointer"},
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
What: "Use of unsafe calls should be audited",
|
||||
Severity: gosec.Low,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Low,
|
||||
Confidence: issue.High,
|
||||
},
|
||||
}, []ast.Node{(*ast.CallExpr)(nil)}
|
||||
}
|
||||
|
||||
15
vendor/github.com/securego/gosec/v2/rules/weakcrypto.go
generated
vendored
15
vendor/github.com/securego/gosec/v2/rules/weakcrypto.go
generated
vendored
@@ -18,10 +18,11 @@ import (
|
||||
"go/ast"
|
||||
|
||||
"github.com/securego/gosec/v2"
|
||||
"github.com/securego/gosec/v2/issue"
|
||||
)
|
||||
|
||||
type usesWeakCryptography struct {
|
||||
gosec.MetaData
|
||||
issue.MetaData
|
||||
blocklist map[string][]string
|
||||
}
|
||||
|
||||
@@ -29,17 +30,17 @@ func (r *usesWeakCryptography) ID() string {
|
||||
return r.MetaData.ID
|
||||
}
|
||||
|
||||
func (r *usesWeakCryptography) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) {
|
||||
func (r *usesWeakCryptography) Match(n ast.Node, c *gosec.Context) (*issue.Issue, error) {
|
||||
for pkg, funcs := range r.blocklist {
|
||||
if _, matched := gosec.MatchCallByPackage(n, c, pkg, funcs...); matched {
|
||||
return gosec.NewIssue(c, n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
return c.NewIssue(n, r.ID(), r.What, r.Severity, r.Confidence), nil
|
||||
}
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// NewUsesWeakCryptography detects uses of des.* md5.* or rc4.*
|
||||
func NewUsesWeakCryptography(id string, conf gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
func NewUsesWeakCryptography(id string, _ gosec.Config) (gosec.Rule, []ast.Node) {
|
||||
calls := make(map[string][]string)
|
||||
calls["crypto/des"] = []string{"NewCipher", "NewTripleDESCipher"}
|
||||
calls["crypto/md5"] = []string{"New", "Sum"}
|
||||
@@ -47,10 +48,10 @@ func NewUsesWeakCryptography(id string, conf gosec.Config) (gosec.Rule, []ast.No
|
||||
calls["crypto/rc4"] = []string{"NewCipher"}
|
||||
rule := &usesWeakCryptography{
|
||||
blocklist: calls,
|
||||
MetaData: gosec.MetaData{
|
||||
MetaData: issue.MetaData{
|
||||
ID: id,
|
||||
Severity: gosec.Medium,
|
||||
Confidence: gosec.High,
|
||||
Severity: issue.Medium,
|
||||
Confidence: issue.High,
|
||||
What: "Use of weak cryptographic primitive",
|
||||
},
|
||||
}
|
||||
|
||||
51
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
51
vendor/golang.org/x/crypto/ssh/common.go
generated
vendored
@@ -49,7 +49,8 @@ var supportedKexAlgos = []string{
|
||||
// P384 and P521 are not constant-time yet, but since we don't
|
||||
// reuse ephemeral keys, using them for ECDH should be OK.
|
||||
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
||||
kexAlgoDH14SHA256, kexAlgoDH14SHA1, kexAlgoDH1SHA1,
|
||||
kexAlgoDH14SHA256, kexAlgoDH16SHA512, kexAlgoDH14SHA1,
|
||||
kexAlgoDH1SHA1,
|
||||
}
|
||||
|
||||
// serverForbiddenKexAlgos contains key exchange algorithms, that are forbidden
|
||||
@@ -59,8 +60,9 @@ var serverForbiddenKexAlgos = map[string]struct{}{
|
||||
kexAlgoDHGEXSHA256: {}, // server half implementation is only minimal to satisfy the automated tests
|
||||
}
|
||||
|
||||
// preferredKexAlgos specifies the default preference for key-exchange algorithms
|
||||
// in preference order.
|
||||
// preferredKexAlgos specifies the default preference for key-exchange
|
||||
// algorithms in preference order. The diffie-hellman-group16-sha512 algorithm
|
||||
// is disabled by default because it is a bit slower than the others.
|
||||
var preferredKexAlgos = []string{
|
||||
kexAlgoCurve25519SHA256, kexAlgoCurve25519SHA256LibSSH,
|
||||
kexAlgoECDH256, kexAlgoECDH384, kexAlgoECDH521,
|
||||
@@ -70,12 +72,12 @@ var preferredKexAlgos = []string{
|
||||
// supportedHostKeyAlgos specifies the supported host-key algorithms (i.e. methods
|
||||
// of authenticating servers) in preference order.
|
||||
var supportedHostKeyAlgos = []string{
|
||||
CertAlgoRSASHA512v01, CertAlgoRSASHA256v01,
|
||||
CertAlgoRSASHA256v01, CertAlgoRSASHA512v01,
|
||||
CertAlgoRSAv01, CertAlgoDSAv01, CertAlgoECDSA256v01,
|
||||
CertAlgoECDSA384v01, CertAlgoECDSA521v01, CertAlgoED25519v01,
|
||||
|
||||
KeyAlgoECDSA256, KeyAlgoECDSA384, KeyAlgoECDSA521,
|
||||
KeyAlgoRSASHA512, KeyAlgoRSASHA256,
|
||||
KeyAlgoRSASHA256, KeyAlgoRSASHA512,
|
||||
KeyAlgoRSA, KeyAlgoDSA,
|
||||
|
||||
KeyAlgoED25519,
|
||||
@@ -85,7 +87,7 @@ var supportedHostKeyAlgos = []string{
|
||||
// This is based on RFC 4253, section 6.4, but with hmac-md5 variants removed
|
||||
// because they have reached the end of their useful life.
|
||||
var supportedMACs = []string{
|
||||
"hmac-sha2-512-etm@openssh.com", "hmac-sha2-256-etm@openssh.com", "hmac-sha2-256", "hmac-sha1", "hmac-sha1-96",
|
||||
"hmac-sha2-256-etm@openssh.com", "hmac-sha2-512-etm@openssh.com", "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1", "hmac-sha1-96",
|
||||
}
|
||||
|
||||
var supportedCompressions = []string{compressionNone}
|
||||
@@ -119,6 +121,13 @@ func algorithmsForKeyFormat(keyFormat string) []string {
|
||||
}
|
||||
}
|
||||
|
||||
// isRSA returns whether algo is a supported RSA algorithm, including certificate
|
||||
// algorithms.
|
||||
func isRSA(algo string) bool {
|
||||
algos := algorithmsForKeyFormat(KeyAlgoRSA)
|
||||
return contains(algos, underlyingAlgo(algo))
|
||||
}
|
||||
|
||||
// supportedPubKeyAuthAlgos specifies the supported client public key
|
||||
// authentication algorithms. Note that this doesn't include certificate types
|
||||
// since those use the underlying algorithm. This list is sent to the client if
|
||||
@@ -262,16 +271,16 @@ type Config struct {
|
||||
// unspecified, a size suitable for the chosen cipher is used.
|
||||
RekeyThreshold uint64
|
||||
|
||||
// The allowed key exchanges algorithms. If unspecified then a
|
||||
// default set of algorithms is used.
|
||||
// The allowed key exchanges algorithms. If unspecified then a default set
|
||||
// of algorithms is used. Unsupported values are silently ignored.
|
||||
KeyExchanges []string
|
||||
|
||||
// The allowed cipher algorithms. If unspecified then a sensible
|
||||
// default is used.
|
||||
// The allowed cipher algorithms. If unspecified then a sensible default is
|
||||
// used. Unsupported values are silently ignored.
|
||||
Ciphers []string
|
||||
|
||||
// The allowed MAC algorithms. If unspecified then a sensible default
|
||||
// is used.
|
||||
// The allowed MAC algorithms. If unspecified then a sensible default is
|
||||
// used. Unsupported values are silently ignored.
|
||||
MACs []string
|
||||
}
|
||||
|
||||
@@ -288,7 +297,7 @@ func (c *Config) SetDefaults() {
|
||||
var ciphers []string
|
||||
for _, c := range c.Ciphers {
|
||||
if cipherModes[c] != nil {
|
||||
// reject the cipher if we have no cipherModes definition
|
||||
// Ignore the cipher if we have no cipherModes definition.
|
||||
ciphers = append(ciphers, c)
|
||||
}
|
||||
}
|
||||
@@ -297,10 +306,26 @@ func (c *Config) SetDefaults() {
|
||||
if c.KeyExchanges == nil {
|
||||
c.KeyExchanges = preferredKexAlgos
|
||||
}
|
||||
var kexs []string
|
||||
for _, k := range c.KeyExchanges {
|
||||
if kexAlgoMap[k] != nil {
|
||||
// Ignore the KEX if we have no kexAlgoMap definition.
|
||||
kexs = append(kexs, k)
|
||||
}
|
||||
}
|
||||
c.KeyExchanges = kexs
|
||||
|
||||
if c.MACs == nil {
|
||||
c.MACs = supportedMACs
|
||||
}
|
||||
var macs []string
|
||||
for _, m := range c.MACs {
|
||||
if macModes[m] != nil {
|
||||
// Ignore the MAC if we have no macModes definition.
|
||||
macs = append(macs, m)
|
||||
}
|
||||
}
|
||||
c.MACs = macs
|
||||
|
||||
if c.RekeyThreshold == 0 {
|
||||
// cipher specific default
|
||||
|
||||
12
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
12
vendor/golang.org/x/crypto/ssh/kex.go
generated
vendored
@@ -23,6 +23,7 @@ const (
|
||||
kexAlgoDH1SHA1 = "diffie-hellman-group1-sha1"
|
||||
kexAlgoDH14SHA1 = "diffie-hellman-group14-sha1"
|
||||
kexAlgoDH14SHA256 = "diffie-hellman-group14-sha256"
|
||||
kexAlgoDH16SHA512 = "diffie-hellman-group16-sha512"
|
||||
kexAlgoECDH256 = "ecdh-sha2-nistp256"
|
||||
kexAlgoECDH384 = "ecdh-sha2-nistp384"
|
||||
kexAlgoECDH521 = "ecdh-sha2-nistp521"
|
||||
@@ -430,6 +431,17 @@ func init() {
|
||||
hashFunc: crypto.SHA256,
|
||||
}
|
||||
|
||||
// This is the group called diffie-hellman-group16-sha512 in RFC
|
||||
// 8268 and Oakley Group 16 in RFC 3526.
|
||||
p, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF", 16)
|
||||
|
||||
kexAlgoMap[kexAlgoDH16SHA512] = &dhGroup{
|
||||
g: new(big.Int).SetInt64(2),
|
||||
p: p,
|
||||
pMinus1: new(big.Int).Sub(p, bigOne),
|
||||
hashFunc: crypto.SHA512,
|
||||
}
|
||||
|
||||
kexAlgoMap[kexAlgoECDH521] = &ecdh{elliptic.P521()}
|
||||
kexAlgoMap[kexAlgoECDH384] = &ecdh{elliptic.P384()}
|
||||
kexAlgoMap[kexAlgoECDH256] = &ecdh{elliptic.P256()}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user