Newer
Older
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
---
sidebar_position: 2
---
import { Tabs, Callout } from 'nextra/components'
# SARIF per Repository
<Callout type="info">
`GET /api/v1/repositories/{repositoryUrl}/sarif[?timestamp=<unix_timestamp>]`
</Callout>
This endpoint gets parameterized with the repository url. The repository url is the url of the repository that should be scanned.
The url should be in the following format: `https://gitlab.opencode.de/zendis-repo-scanner`. **The url must be url encoded.**
(`https%3A%2F%2Fgitlab.opencode.de%2Fzendis-repo-scanner`)
Using this format already opens the possibility to scan repositories from other platforms like GitHub, Bitbucket, etc. Besides
that, caching is simplified because the url is unique (instead of using the project id and a platform url as query string for
example) and the url is human readable, at least after url decoding. This might improve debugging in the future.
The timestamp parameter is optional. If it is provided, the endpoint will return the scan result that is closest (but never in
the future) to the given timestamp. If it is not provided, the endpoint will return the latest scan result.
The result is returned in [SARIF format](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning).
**SARIF simplifies possible later integration with other tools. It is an open standard and widely supported.**
### Example Request
<Tabs items={['GO', 'JavaScript', 'curl']}>
<Tabs.Tab>
```go filename="main.go" copy
package main
import (
"fmt"
"io"
"net/http"
)
func main() {
url := "https://scanner.zend.is/api/v1/repositories/https%3A%2F%2Fgitlab.opencode.de%2Fzendis-repo-scanner/sarif"
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
</Tabs.Tab>
<Tabs.Tab>
```js filename="main.js" copy
const fetch = require('node-fetch');
const url = 'https://scanner.zend.is/api/v1/repositories/https%3A%2F%2Fgitlab.opencode.de%2Fzendis-repo-scanner/sarif';
fetch(url)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
</Tabs.Tab>
<Tabs.Tab>
```bash filename="cli" copy
curl -X GET "https://scanner.zend.is/api/v1/repositories/https%3A%2F%2Fgitlab.opencode.de%2Fzendis-repo-scanner/sarif"
```
</Tabs.Tab>
</Tabs>
### Example JSON Response
```json
{
"$schema": "https://www.schemastore.org/schemas/json/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "zendis-repo-scanner",
"version": "1.0.0",
"informationUri": "https://gitlab.opencode.de/zendis-repo-scanner",
"rules": [
{
"id": "ISSUE_REACTION_TIME",
"name": "Issue Reaction Time",
"fullDescription": {
"text": "Measures the average time it takes to respond to reported issues."
},
"help": {
"text": "The average issue reaction time is calculated by dividing the sum of the time it took to respond to all issues by the number of issues. The reaction time is so important because it shows how quickly the project team can respond to issues and bugs. The faster the reaction time, the more likely the project is to be maintained and improved."
},
"properties": {
"unit": "days",
"thresholds": [
{ "min": 0, "max": 1, "status": "gold" },
{ "min": 2, "max": 7, "status": "silver" },
{ "min": 8, "max": 14, "status": "bronze" }
{ "min": 15, "max": null, "status": "fail" }
],
}
},
{
"id": "BUS_FACTOR",
"name": "Bus Factor",
"fullDescription": {
"text": "Calculates the bus factor of the project, indicating how many contributors must become unavailable to jeopardize the project."
},
"help": {
"text": "The bus factor is a measure of the project's resilience to losing contributors. The higher the bus factor, the more contributors can become unavailable before the project is in danger. The bus factor is so important because it shows how many people are familiar with the project and can take over if necessary."
},
"properties": {
"unit": "contributors",
"thresholds": [
{ "min": 4, "max": null, "status": "gold" },
{ "min": 3, "max": 3, "status": "silver" },
{ "min": 2, "max": 2, "status": "bronze" }
{ "min": 0, "max": 1, "status": "fail" }
],
}
},
{
"id": "SECURITY_POLICY",
"name": "Security Policy",
"fullDescription": {
"text": "Checks if the project has a security policy."
},
"help": {
"text": "A security policy is a set of rules and practices that the project team follows to ensure the security of the project. The security policy is so important because it shows how seriously the project team takes security and how well they are prepared to handle security incidents."
},
"properties": {
"type": "boolean",
"positiveStatus": "gold",
"negativeStatus": "fail"
}
}
]
}
},
"properties": {
"timestamp": 1630000000,
"badges": [
{
"badgeUrl": "https://img.shields.io/badge/maintenance-silver-lightgrey.svg",
"badgeId": "MAINTENANCE",
"badgeStatus": "silver",
"badgeInformationUri": "https://gitlab.opencode.de/zendis-repo-scanner/badges/maintenance.md",
"badgeExplanation": {
"criteria": [
{
"description": "The average issue reaction time qualifies as silver (4 days, between 1 and 7 days).",
"ruleId": "ISSUE_REACTION_TIME",
"value": 4,
"status": "silver"
},
{
"description": "The bus factor qualifies as gold (3 contributors or more).",
"ruleId": "BUS_FACTOR",
"value": 3,
"status": "gold"
},
],
"conclusion": "Based on the evaluation of the above criteria, this project is classified as Silver level maintenance."
}
},
{
"badgeUrl": "https://img.shields.io/badge/security-fail-red.svg",
"badgeId": "SECURITY",
"badgeStatus": "fail",
"badgeInformationUri": "https://gitlab.opencode.de/zendis-repo-scanner/badges/security.md",
"badgeExplanation": {
"criteria": [
{
"description": "A security policy does not exist for this project.",
"ruleId": "SECURITY_POLICY",
"value": false,
"status": "fail"
}
],
"conclusion": "Based on the evaluation of the above criteria, this project is not granted a security badge."
}
}
]
},
"results": [
{
"ruleId": "ISSUE_REACTION_TIME",
"level": "note",
"message": {
"text": "The average issue reaction time is 4 days, which qualifies as silver (between 1 and 7 days)."
},
"properties": {
"value": 4,
"status": "silver",
"unit": "days"
}
},
{
"ruleId": "BUS_FACTOR",
"level": "note",
"message": {
"text": "The bus factor is 3, which qualifies as gold (3 contributors or more)."
},
"properties": {
"value": 4,
"status": "gold",
"unit": "contributors"
}
},
{
"ruleId": "SECURITY_POLICY",
"level": "warning",
"message": {
"text": "A security policy does not exist for this project."
},
"properties": {
"value": false,
"status": "fail"
}
}
]
}
]
}
```
### Response Explanation
This JSON response contains the following information:
- The tool that generated the report (which will probably always be the same string)
- The properties of the tool, such as the version and the informationUri, basically to comply with the SARIF standard.
- The rules that the tool uses to evaluate the repository
- Rule Ids will be all uppercase and snake case (e.g. `ISSUE_REACTION_TIME`) and will be unique.
- The properties of the rules, such as thresholds and units - those are dynamically added into the json. The report should never be stored like this inside the database. Thresholds are subject to change due to optimization. The database stores normalized entries like: `BUS_FACTOR: 3` and `ISSUE_REACTION_TIME: 4`. Thus the badges can be changed by modifying the thresholds and applied to past reports as well.
- The results of the run, which contain the following elements:
- ruleId: The rule that was evaluated
- level: The level of the result (warning if the rule is not met, note if the rule is met (the threshold or state does not matter))
- message: The message of the result
- properties: The properties of the result, such as the value, status, range, and unit
- The properties of the run, such as badges, which are dynamically added into the json. They contain the following elements:
- badgeUrl: The url to the badge image - will be a dynamically generated svg
- badgeId: The title of the badge
- badgeInformationUri: The url to additional documentation about that badge
- badgeStatus: The level of the badge, which can be one of the following:
- `gold`
- `silver`
- `bronze`
- `fail`
- `expired`
- badgeExplanation: The explanation of the badge, which contains the following elements:
- criteria: A list of criteria that were evaluated to determine the badge
- description: A description of the criteria
- ruleId: The rule that was evaluated
- value: The value that was evaluated
- status: The status of the evaluation
- range: The range of the evaluation
- conclusion: The conclusion of the badge. This is a summary of the criteria that were evaluated.