/
extend.go
88 lines (75 loc) · 2.65 KB
/
extend.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package output
import (
"encoding/json"
"fmt"
"strings"
)
// Extending the autogenerated output structs.
// Create an alias for the entire struct.
type Output = SemgrepOutputV1Jsonschema
// Deserialize the JSON output to a Go struct.
func Deserialize(data []byte) (Output, error) {
var out Output
if err := out.UnmarshalJSON(data); err != nil {
return out, fmt.Errorf("failed to deserialize Semgrep's output: %w", err)
}
return out, nil
}
// Serialize the Go struct to JSON. If beautify is true, the output is indented.
func (o Output) Serialize(beautify bool) ([]byte, error) {
if beautify {
return json.MarshalIndent(o, "", " ")
}
return json.Marshal(o)
}
// ------
// RuleID returns the rule ID of a match/hit/result as a string.
func (c CliMatch) RuleID() string {
return string(c.CheckId)
}
// FilePath returns the file path of a match/hit/result as a string.
func (c CliMatch) FilePath() string {
return string(c.Path)
}
// Return the message of a match/hit/result as a string.
func (c CliMatch) Message() string {
return c.Extra.Message
}
// Return the value of a metavariable in the result. We will convert the
// metavariable name to upper case and prepend it with `$` if it's missing.
// E.g., `path` -> `$PATH`. If both `abstract_content` and `propagated_value`
// fields are populated, we return `propagated_value`. Return an error if the
// metavariable doesn't exist.
func (c CliMatch) Metavar(name string) (string, error) {
// Convert the string to upper case.
up := strings.ToUpper(name)
// Check if it starts with `$` and add if not.
if !strings.HasPrefix(up, "$") {
up = "$" + up
}
// Check if the metavariable exists in the map.
if val, exists := c.Extra.Metavars[up]; exists {
// Check if `propagated_value` exists and return if it does.
if val.PropagatedValue != nil {
return val.PropagatedValue.SvalueAbstractContent, nil
}
// If not, return `abstract_content`.
return val.AbstractContent, nil
}
return "", fmt.Errorf("Metavariable %s doesn't exist in the result.", name)
}
// Return the value of a metadata field. These come directly from the metadata
// field in the rule. They're freeform, but usually map[string]interface{}.
// Return an error if they key doesn't exist.
func (c CliMatch) Metadata(name string) (interface{}, error) {
// try to cast it to map[string]interface{}
cast, ok := c.Extra.Metadata.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("Couldn't cast metadata to map[string]interface{}. Got: %T", c.Extra.Metadata)
}
// Check if the key exists in the map
if val, exists := cast[name]; exists {
return val, nil
}
return nil, fmt.Errorf("Metadata field %s doesn't exist in result.", name)
}