gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/securego/gosec/issue.go (about) 1 // (c) Copyright 2016 Hewlett Packard Enterprise Development LP 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package gosec 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "go/ast" 21 "os" 22 "strconv" 23 ) 24 25 // Score type used by severity and confidence values 26 type Score int 27 28 const ( 29 // Low severity or confidence 30 Low Score = iota 31 // Medium severity or confidence 32 Medium 33 // High severity or confidence 34 High 35 ) 36 37 // Issue is returnd by a gosec rule if it discovers an issue with the scanned code. 38 type Issue struct { 39 Severity Score `json:"severity"` // issue severity (how problematic it is) 40 Confidence Score `json:"confidence"` // issue confidence (how sure we are we found it) 41 RuleID string `json:"rule_id"` // Human readable explanation 42 What string `json:"details"` // Human readable explanation 43 File string `json:"file"` // File name we found it in 44 Code string `json:"code"` // Impacted code line 45 Line string `json:"line"` // Line number in file 46 } 47 48 // MetaData is embedded in all gosec rules. The Severity, Confidence and What message 49 // will be passed tbhrough to reported issues. 50 type MetaData struct { 51 ID string 52 Severity Score 53 Confidence Score 54 What string 55 } 56 57 // MarshalJSON is used convert a Score object into a JSON representation 58 func (c Score) MarshalJSON() ([]byte, error) { 59 return json.Marshal(c.String()) 60 } 61 62 // String converts a Score into a string 63 func (c Score) String() string { 64 switch c { 65 case High: 66 return "HIGH" 67 case Medium: 68 return "MEDIUM" 69 case Low: 70 return "LOW" 71 } 72 return "UNDEFINED" 73 } 74 75 func codeSnippet(file *os.File, start int64, end int64, n ast.Node) (string, error) { 76 if n == nil { 77 return "", fmt.Errorf("Invalid AST node provided") 78 } 79 80 size := (int)(end - start) // Go bug, os.File.Read should return int64 ... 81 file.Seek(start, 0) // #nosec 82 83 buf := make([]byte, size) 84 if nread, err := file.Read(buf); err != nil || nread != size { 85 return "", fmt.Errorf("Unable to read code") 86 } 87 return string(buf), nil 88 } 89 90 // NewIssue creates a new Issue 91 func NewIssue(ctx *Context, node ast.Node, ruleID, desc string, severity Score, confidence Score) *Issue { 92 var code string 93 fobj := ctx.FileSet.File(node.Pos()) 94 name := fobj.Name() 95 96 start, end := fobj.Line(node.Pos()), fobj.Line(node.End()) 97 line := strconv.Itoa(start) 98 if start != end { 99 line = fmt.Sprintf("%d-%d", start, end) 100 } 101 102 // #nosec 103 if file, err := os.Open(fobj.Name()); err == nil { 104 defer file.Close() 105 s := (int64)(fobj.Position(node.Pos()).Offset) // Go bug, should be int64 106 e := (int64)(fobj.Position(node.End()).Offset) // Go bug, should be int64 107 code, err = codeSnippet(file, s, e, node) 108 if err != nil { 109 code = err.Error() 110 } 111 } 112 113 return &Issue{ 114 File: name, 115 Line: line, 116 RuleID: ruleID, 117 What: desc, 118 Confidence: confidence, 119 Severity: severity, 120 Code: code, 121 } 122 }