/
local_check_security.go
95 lines (81 loc) · 3.29 KB
/
local_check_security.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
89
90
91
92
93
94
95
package commands
import (
"fmt"
"os"
"github.com/fabpot/local-php-security-checker/v2/security"
"github.com/pkg/errors"
"github.com/symfony-cli/console"
"github.com/symfony-cli/terminal"
)
var localSecurityCheckCmd = &console.Command{
Category: "local",
Name: "check:security",
Aliases: []*console.Alias{{Name: "security:check"}, {Name: "check:security"}, {Name: "local:security:check"}},
Usage: "Check security issues in project dependencies",
Description: `Checks security issues in project dependencies. Without arguments, it looks
for a "composer.lock" file in the current directory. Pass it explicitly to check
a specific "composer.lock" file.`,
Flags: []console.Flag{
dirFlag,
&console.StringFlag{
Name: "format",
DefaultValue: "ansi",
Usage: "The output format (ansi, markdown, json, junit, or yaml)",
Validator: func(ctx *console.Context, format string) error {
if format != "" && format != "markdown" && format != "json" && format != "yaml" && format != "ansi" && format != "junit" {
return errors.Errorf(`format "%s" does not exist (supported formats: markdown, ansi, json, junit, and yaml)`, format)
}
return nil
},
},
&console.StringFlag{Name: "archive", DefaultValue: security.AdvisoryArchiveURL, Usage: "Advisory archive URL"},
&console.BoolFlag{Name: "local", Usage: "Do not make HTTP calls (needs a valid cache file)"},
&console.BoolFlag{Name: "no-dev", Usage: "Do not check packages listed under require-dev"},
&console.BoolFlag{Name: "update-cache", Usage: "Update the cache (other flags are ignored)"},
&console.BoolFlag{Name: "disable-exit-code", Usage: "Whether to fail when issues are detected"},
&console.StringFlag{Name: "cache-dir", DefaultValue: os.TempDir(), Usage: "Cache directory"},
},
Action: func(c *console.Context) error {
format := c.String("format")
path := c.String("dir")
advisoryArchiveURL := c.String("archive")
db, err := security.NewDB(c.Bool("local"), advisoryArchiveURL, c.String("cache-dir"))
if err != nil {
return console.Exit(fmt.Sprintf("unable to load the advisory DB: %s", err), 127)
}
if c.Bool("update-cache") {
return nil
}
lockReader, err := security.LocateLock(path)
if err != nil {
return console.Exit(err.Error(), 127)
}
lock, err := security.NewLock(lockReader)
if err != nil {
return console.Exit(fmt.Sprintf("unable to load the lock file: %s", err), 127)
}
vulns := security.Analyze(lock, db, c.Bool("no-dev"))
output, err := security.Format(vulns, format)
if err != nil {
return console.Exit(fmt.Sprintf("unable to output the results: %s", err), 127)
}
terminal.Stdout.Write(output)
if os.Getenv("GITHUB_WORKSPACE") != "" {
gOutFile := os.Getenv("GITHUB_OUTPUT")
f, err := os.OpenFile(gOutFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return console.Exit(fmt.Sprintf("unable to open github output: %s", err), 127)
}
defer f.Close()
// Ran inside a GitHub action, export vulns
output, _ := security.Format(vulns, "raw_json")
if _, err = f.WriteString("vulns=" + string(output) + "\n"); err != nil {
return console.Exit(fmt.Sprintf("unable to write into github output: %s", err), 127)
}
}
if vulns.Count() > 0 && !c.Bool(("disable-exit-code")) {
return console.Exit("", 1)
}
return nil
},
}