Skip to content

Commit 505fe8d

Browse files
author
sg
committed
close feature 405, modelscan component
1 parent 68aaa00 commit 505fe8d

File tree

5 files changed

+348
-0
lines changed

5 files changed

+348
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"modelscan_version": "0.5.0",
3+
"timestamp": "2024-01-25T17:56:00.855056",
4+
"input_path": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
5+
"total_issues": 1,
6+
"summary": {
7+
"total_issues_by_severity": {
8+
"LOW": 0,
9+
"MEDIUM": 0,
10+
"HIGH": 0,
11+
"CRITICAL": 1
12+
}
13+
},
14+
"issues_by_severity": {
15+
"CRITICAL": [
16+
{
17+
"description": "Use of unsafe operator 'system' from module 'posix'",
18+
"operator": "system",
19+
"module": "posix",
20+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
21+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
22+
}
23+
],
24+
"MEDIUM": [
25+
{
26+
"description": "Use of unsafe operator 'system' from module 'posix'",
27+
"operator": "system",
28+
"module": "posix",
29+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
30+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
31+
}
32+
],
33+
"HIGH": [
34+
{
35+
"description": "Use of unsafe operator 'system' from module 'posix'",
36+
"operator": "system",
37+
"module": "posix",
38+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
39+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
40+
}
41+
],
42+
"LOW": [
43+
{
44+
"description": "Use of unsafe operator 'system' from module 'posix'",
45+
"operator": "system",
46+
"module": "posix",
47+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
48+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
49+
}
50+
]
51+
},
52+
"errors": [],
53+
"scanned": {
54+
"total_scanned": 4,
55+
"scanned_files": [
56+
"/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl"
57+
]
58+
}
59+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
 �͙�햞�gosec�
3+
O/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl%modelscan.scanners.PickleUnsafeOpScan3Use of unsafe operator 'system' from module 'posix':3Use of unsafe operator 'system' from module 'posix'Bunknown�
4+
O/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl%modelscan.scanners.PickleUnsafeOpScan3Use of unsafe operator 'system' from module 'posix':3Use of unsafe operator 'system' from module 'posix'Bunknown�
5+
O/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl%modelscan.scanners.PickleUnsafeOpScan3Use of unsafe operator 'system' from module 'posix':3Use of unsafe operator 'system' from module 'posix'Bunknown�
6+
O/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl%modelscan.scanners.PickleUnsafeOpScan3Use of unsafe operator 'system' from module 'posix':3Use of unsafe operator 'system' from module 'posix'Bunknown
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"log"
6+
"log/slog"
7+
8+
v1 "github.com/ocurity/dracon/api/proto/v1"
9+
10+
"github.com/ocurity/dracon/components/producers"
11+
)
12+
13+
func main() {
14+
if err := producers.ParseFlags(); err != nil {
15+
log.Fatal(err)
16+
}
17+
18+
inFile, err := producers.ReadInFile()
19+
if err != nil {
20+
log.Fatal(err)
21+
}
22+
23+
var results ModelScanOut
24+
if err := json.Unmarshal(inFile, &results); err != nil {
25+
log.Fatal(err)
26+
}
27+
28+
issues, err := parseIssues(&results)
29+
if err != nil {
30+
log.Fatal(err)
31+
}
32+
if err := producers.WriteDraconOut(
33+
"modelscan",
34+
issues,
35+
); err != nil {
36+
log.Fatal(err)
37+
}
38+
}
39+
40+
func parseIssues(out *ModelScanOut) ([]*v1.Issue, error) {
41+
issues := make([]*v1.Issue, 0, len(out.Issues))
42+
slog.Info("found Critical issues", slog.Int("numCrit", out.Summary.TotalIssuesBySeverity.Critical))
43+
slog.Info("found High issues", slog.Int("numCrit", out.Summary.TotalIssuesBySeverity.High))
44+
slog.Info("found Medium issues", slog.Int("numCrit", out.Summary.TotalIssuesBySeverity.Medium))
45+
slog.Info("found Low issues", slog.Int("numCrit", out.Summary.TotalIssuesBySeverity.Low))
46+
for _, issue := range out.Issues {
47+
issues = append(issues,
48+
&v1.Issue{
49+
Target: "file:///" + issue.Source,
50+
Type: issue.Scanner,
51+
Description: issue.Description,
52+
Title: issue.Description,
53+
Severity: modelScanSeverityToDracon(issue.Severity),
54+
Confidence: v1.Confidence_CONFIDENCE_UNSPECIFIED,
55+
})
56+
}
57+
return issues, nil
58+
}
59+
60+
func modelScanSeverityToDracon(severity string) v1.Severity {
61+
switch severity {
62+
case "CRITICAL":
63+
return v1.Severity_SEVERITY_CRITICAL
64+
case "HIGH":
65+
return v1.Severity_SEVERITY_HIGH
66+
case "MEDIUM":
67+
return v1.Severity_SEVERITY_MEDIUM
68+
case "LOW":
69+
return v1.Severity_SEVERITY_LOW
70+
default:
71+
return v1.Severity_SEVERITY_UNSPECIFIED
72+
}
73+
}
74+
75+
type ModelScanOut struct {
76+
Summary ModelScanSummary `json:"summary,omitempty"`
77+
Issues []ModelScanIssue `json:"issues,omitempty"`
78+
Errors []any `json:"errors,omitempty"`
79+
}
80+
81+
type ModelScanIssue struct {
82+
Description string `json:"description,omitempty"`
83+
Operator string `json:"operator,omitempty"`
84+
Module string `json:"module,omitempty"`
85+
Source string `json:"source,omitempty"`
86+
Scanner string `json:"scanner,omitempty"`
87+
Severity string `json:"severity,omitempty"`
88+
}
89+
90+
type ModelScanSummary struct {
91+
TotalIssuesBySeverity TotalIssuesBySeverity `json:"total_issues_by_severity,omitempty"`
92+
TotalIssues int `json:"total_issues,omitempty"`
93+
InputPath string `json:"input_path,omitempty"`
94+
AbsolutePath string `json:"absolute_path,omitempty"`
95+
ModelscanVersion string `json:"modelscan_version,omitempty"`
96+
Timestamp string `json:"timestamp,omitempty"`
97+
Scanned Scanned `json:"scanned,omitempty"`
98+
}
99+
100+
type TotalIssuesBySeverity struct {
101+
Low int `json:"LOW,omitempty"`
102+
Medium int `json:"MEDIUM,omitempty"`
103+
High int `json:"HIGH,omitempty"`
104+
Critical int `json:"CRITICAL,omitempty"`
105+
}
106+
107+
type Scanned struct {
108+
TotalScanned int `json:"total_scanned,omitempty"`
109+
ScannedFiles []string `json:"scanned_files,omitempty"`
110+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"testing"
6+
7+
v1 "github.com/ocurity/dracon/api/proto/v1"
8+
9+
"github.com/stretchr/testify/require"
10+
)
11+
12+
func TestParseIssues(t *testing.T) {
13+
var results ModelScanOut
14+
err := json.Unmarshal([]byte(modelScanOut), &results)
15+
require.NoError(t, err)
16+
17+
issues, err := parseIssues(&results)
18+
require.NoError(t, err)
19+
expectedIssue := []*v1.Issue{
20+
21+
{
22+
Target: "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
23+
Type: "modelscan.scanners.PickleUnsafeOpScan",
24+
Title: "Use of unsafe operator 'system' from module 'posix'",
25+
Description: "Use of unsafe operator 'system' from module 'posix'",
26+
},
27+
{
28+
Target: "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
29+
Type: "modelscan.scanners.PickleUnsafeOpScan",
30+
Title: "Use of unsafe operator 'system' from module 'posix'",
31+
Description: "Use of unsafe operator 'system' from module 'posix'",
32+
},
33+
{
34+
Target: "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
35+
Type: "modelscan.scanners.PickleUnsafeOpScan",
36+
Title: "Use of unsafe operator 'system' from module 'posix'",
37+
Description: "Use of unsafe operator 'system' from module 'posix'",
38+
},
39+
{
40+
Target: "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
41+
Type: "modelscan.scanners.PickleUnsafeOpScan",
42+
Title: "Use of unsafe operator 'system' from module 'posix'",
43+
Description: "Use of unsafe operator 'system' from module 'posix'",
44+
},
45+
}
46+
47+
require.Equal(t, expectedIssue, issues)
48+
}
49+
50+
const modelScanOut = `{
51+
"modelscan_version": "0.5.0",
52+
"timestamp": "2024-01-25T17:56:00.855056",
53+
"input_path": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
54+
"total_issues": 4,
55+
"summary": {
56+
"total_issues_by_severity": {
57+
"LOW": 1,
58+
"MEDIUM": 1,
59+
"HIGH": 1,
60+
"CRITICAL": 1
61+
}
62+
},
63+
"issues_by_severity": {
64+
"CRITICAL": [
65+
{
66+
"description": "Use of unsafe operator 'system' from module 'posix'",
67+
"operator": "system",
68+
"module": "posix",
69+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
70+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
71+
}
72+
],
73+
"MEDIUM": [
74+
{
75+
"description": "Use of unsafe operator 'system' from module 'posix'",
76+
"operator": "system",
77+
"module": "posix",
78+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
79+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
80+
}
81+
],
82+
"HIGH": [
83+
{
84+
"description": "Use of unsafe operator 'system' from module 'posix'",
85+
"operator": "system",
86+
"module": "posix",
87+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
88+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
89+
}
90+
],
91+
"LOW": [
92+
{
93+
"description": "Use of unsafe operator 'system' from module 'posix'",
94+
"operator": "system",
95+
"module": "posix",
96+
"source": "/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl",
97+
"scanner": "modelscan.scanners.PickleUnsafeOpScan"
98+
}
99+
]
100+
},
101+
"errors": [],
102+
"scanned": {
103+
"total_scanned": 4,
104+
"scanned_files": [
105+
"/Users/mehrinkiani/Documents/modelscan/notebooks/XGBoostModels/unsafe_model.pkl"
106+
]
107+
}
108+
}
109+
`
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
---
2+
apiVersion: tekton.dev/v1beta1
3+
kind: Task
4+
metadata:
5+
name: producer-modelscan
6+
labels:
7+
v1.dracon.ocurity.com/component: producer
8+
v1.dracon.ocurity.com/test-type: sast
9+
v1.dracon.ocurity.com/language: python
10+
spec:
11+
description: Analyse Go source code to look for security issues.
12+
params:
13+
- name: producer-modelscan-relative-path-to-model
14+
type: string
15+
volumes:
16+
- name: scratch
17+
emptyDir: {}
18+
workspaces:
19+
- name: output
20+
description: The workspace containing the source-code to scan.
21+
steps:
22+
- name: run-modelscan
23+
image: python:3.11-alpine
24+
imagePullPolicy: Always
25+
script: |
26+
set -x
27+
set +e
28+
29+
pip install 'modelscan'
30+
modelscan --path "$(workspaces.output.path)/source-code/$(params.producer-modelscan-relative-path-to-model)" --reporting-format json --output-file /scratch/out.json
31+
exitCode=$?
32+
33+
if [[ $exitCode -eq 1 ]]; then
34+
echo "ModelScan found vulnerabilities"
35+
exit 0
36+
elif [[ $exitCode -eq 2 ]]; then
37+
echo "ModelScan failed, error while scanning"
38+
exit $exitCode
39+
elif [[ $exitCode -eq 3 ]]; then
40+
echo "ModelScan did not find any supported files while scanning"
41+
exit $exitCode
42+
elif [[ $exitCode -eq 4 ]]; then
43+
echo "ModelScan encountered an error whle parsing CLI variables, the task definition has a bug"
44+
exit $exitCode
45+
elif [[ $exitCode -eq 0 ]]; then
46+
echo "ModelScan did not find any vulnerabilities"
47+
exit $exitCode
48+
else
49+
echo "Received unexpected exit code, exiting"
50+
exit $exitCode
51+
fi
52+
volumeMounts:
53+
- mountPath: /scratch
54+
name: scratch
55+
- name: produce-issues
56+
imagePullPolicy: Always
57+
image: '{{ default "ghcr.io/ocurity/dracon" .Values.image.registry }}/components/producers/modelscan:{{ .Chart.AppVersion }}'
58+
command: ["/app/components/producers/modelscan/modelscan-parser"]
59+
args:
60+
- "-in=/scratch/out.json"
61+
- "-out=$(workspaces.output.path)/.dracon/producers/modelscan.pb"
62+
volumeMounts:
63+
- mountPath: /scratch
64+
name: scratch

0 commit comments

Comments
 (0)