@sectester/scan 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +301 -0
- package/package.json +56 -0
- package/src/DefaultScans.d.ts +20 -0
- package/src/DefaultScans.js +63 -0
- package/src/DefaultScans.js.map +1 -0
- package/src/Scan.d.ts +33 -0
- package/src/Scan.js +133 -0
- package/src/Scan.js.map +1 -0
- package/src/ScanFactory.d.ts +19 -0
- package/src/ScanFactory.js +96 -0
- package/src/ScanFactory.js.map +1 -0
- package/src/ScanSettings.d.ts +47 -0
- package/src/ScanSettings.js +113 -0
- package/src/ScanSettings.js.map +1 -0
- package/src/Scans.d.ts +20 -0
- package/src/Scans.js +5 -0
- package/src/Scans.js.map +1 -0
- package/src/commands/CreateScan.d.ts +17 -0
- package/src/commands/CreateScan.js +15 -0
- package/src/commands/CreateScan.js.map +1 -0
- package/src/commands/DeleteScan.d.ts +4 -0
- package/src/commands/DeleteScan.js +16 -0
- package/src/commands/DeleteScan.js.map +1 -0
- package/src/commands/GetScan.d.ts +5 -0
- package/src/commands/GetScan.js +14 -0
- package/src/commands/GetScan.js.map +1 -0
- package/src/commands/ListIssues.d.ts +5 -0
- package/src/commands/ListIssues.js +14 -0
- package/src/commands/ListIssues.js.map +1 -0
- package/src/commands/StopScan.d.ts +4 -0
- package/src/commands/StopScan.js +15 -0
- package/src/commands/StopScan.js.map +1 -0
- package/src/commands/UploadHar.d.ts +8 -0
- package/src/commands/UploadHar.js +23 -0
- package/src/commands/UploadHar.js.map +1 -0
- package/src/commands/index.d.ts +6 -0
- package/src/commands/index.js +10 -0
- package/src/commands/index.js.map +1 -0
- package/src/exceptions/ScanAborted.d.ts +7 -0
- package/src/exceptions/ScanAborted.js +15 -0
- package/src/exceptions/ScanAborted.js.map +1 -0
- package/src/exceptions/ScanException.d.ts +6 -0
- package/src/exceptions/ScanException.js +11 -0
- package/src/exceptions/ScanException.js.map +1 -0
- package/src/exceptions/ScanExceptionCode.d.ts +4 -0
- package/src/exceptions/ScanExceptionCode.js +9 -0
- package/src/exceptions/ScanExceptionCode.js.map +1 -0
- package/src/exceptions/ScanTimedOut.d.ts +6 -0
- package/src/exceptions/ScanTimedOut.js +15 -0
- package/src/exceptions/ScanTimedOut.js.map +1 -0
- package/src/exceptions/index.d.ts +4 -0
- package/src/exceptions/index.js +8 -0
- package/src/exceptions/index.js.map +1 -0
- package/src/index.d.ts +7 -0
- package/src/index.js +11 -0
- package/src/index.js.map +1 -0
- package/src/models/AttackParamLocation.d.ts +9 -0
- package/src/models/AttackParamLocation.js +14 -0
- package/src/models/AttackParamLocation.js.map +1 -0
- package/src/models/Discovery.d.ts +5 -0
- package/src/models/Discovery.js +10 -0
- package/src/models/Discovery.js.map +1 -0
- package/src/models/HttpMethod.d.ts +18 -0
- package/src/models/HttpMethod.js +24 -0
- package/src/models/HttpMethod.js.map +1 -0
- package/src/models/Issue.d.ts +54 -0
- package/src/models/Issue.js +3 -0
- package/src/models/Issue.js.map +1 -0
- package/src/models/IssueGroup.d.ts +5 -0
- package/src/models/IssueGroup.js +3 -0
- package/src/models/IssueGroup.js.map +1 -0
- package/src/models/Module.d.ts +4 -0
- package/src/models/Module.js +9 -0
- package/src/models/Module.js.map +1 -0
- package/src/models/ScanConfig.d.ts +20 -0
- package/src/models/ScanConfig.js +3 -0
- package/src/models/ScanConfig.js.map +1 -0
- package/src/models/ScanState.d.ts +14 -0
- package/src/models/ScanState.js +3 -0
- package/src/models/ScanState.js.map +1 -0
- package/src/models/ScanStatus.d.ts +11 -0
- package/src/models/ScanStatus.js +16 -0
- package/src/models/ScanStatus.js.map +1 -0
- package/src/models/Severity.d.ts +8 -0
- package/src/models/Severity.js +37 -0
- package/src/models/Severity.js.map +1 -0
- package/src/models/TestType.d.ts +48 -0
- package/src/models/TestType.js +53 -0
- package/src/models/TestType.js.map +1 -0
- package/src/models/index.d.ts +11 -0
- package/src/models/index.js +15 -0
- package/src/models/index.js.map +1 -0
- package/src/register.d.ts +1 -0
- package/src/register.js +14 -0
- package/src/register.js.map +1 -0
- package/src/target/Target.d.ts +48 -0
- package/src/target/Target.js +166 -0
- package/src/target/Target.js.map +1 -0
- package/src/target/body-parsers/BinaryBodyParser.d.ts +6 -0
- package/src/target/body-parsers/BinaryBodyParser.js +14 -0
- package/src/target/body-parsers/BinaryBodyParser.js.map +1 -0
- package/src/target/body-parsers/BodyParser.d.ts +12 -0
- package/src/target/body-parsers/BodyParser.js +5 -0
- package/src/target/body-parsers/BodyParser.js.map +1 -0
- package/src/target/body-parsers/FormDataBodyParser.d.ts +9 -0
- package/src/target/body-parsers/FormDataBodyParser.js +63 -0
- package/src/target/body-parsers/FormDataBodyParser.js.map +1 -0
- package/src/target/body-parsers/JsonBodyParser.d.ts +7 -0
- package/src/target/body-parsers/JsonBodyParser.js +24 -0
- package/src/target/body-parsers/JsonBodyParser.js.map +1 -0
- package/src/target/body-parsers/TextBodyParser.d.ts +6 -0
- package/src/target/body-parsers/TextBodyParser.js +15 -0
- package/src/target/body-parsers/TextBodyParser.js.map +1 -0
- package/src/target/body-parsers/UrlEncodedBodyParser.d.ts +7 -0
- package/src/target/body-parsers/UrlEncodedBodyParser.js +25 -0
- package/src/target/body-parsers/UrlEncodedBodyParser.js.map +1 -0
- package/src/target/body-parsers/index.d.ts +2 -0
- package/src/target/body-parsers/index.js +6 -0
- package/src/target/body-parsers/index.js.map +1 -0
- package/src/target/body-parsers/register.d.ts +1 -0
- package/src/target/body-parsers/register.js +26 -0
- package/src/target/body-parsers/register.js.map +1 -0
- package/src/target/index.d.ts +2 -0
- package/src/target/index.js +6 -0
- package/src/target/index.js.map +1 -0
- package/src/utils/entries-to-list.d.ts +7 -0
- package/src/utils/entries-to-list.js +10 -0
- package/src/utils/entries-to-list.js.map +1 -0
- package/src/utils/escape.d.ts +1 -0
- package/src/utils/escape.js +19 -0
- package/src/utils/escape.js.map +1 -0
- package/src/utils/index.d.ts +2 -0
- package/src/utils/index.js +6 -0
- package/src/utils/index.js.map +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Bright Security
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# @sectester/scan
|
|
2
|
+
|
|
3
|
+
[](https://codeclimate.com/github/NeuraLegion/sectester-js/maintainability)
|
|
4
|
+
[](https://codeclimate.com/github/NeuraLegion/sectester-js/test_coverage)
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+
|
|
8
|
+
The package defines a simple public API to manage scans and their expectations.
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm i -s @sectester/scan
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
To start scanning your application, you have to create a `ScanFactory` as follows:
|
|
19
|
+
|
|
20
|
+
```ts
|
|
21
|
+
import { Configuration } from '@sectester/core';
|
|
22
|
+
import { ScanFactory } from '@sectester/scan';
|
|
23
|
+
|
|
24
|
+
const config = new Configuration({
|
|
25
|
+
hostname: 'app.neuralegion.com'
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const scanFactory = new ScanFactory(config);
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
To create a new scan, you have to define a target first (for details, see [here](#defining-a-target-for-attack)):
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { Target } from '@sectester/scan';
|
|
35
|
+
|
|
36
|
+
const target = new Target({
|
|
37
|
+
url: 'https://example.com'
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The factory exposes the `createScan` method that returns a new [Scan instance](#managing-a-scan):
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { TestType } from '@sectester/scan';
|
|
45
|
+
|
|
46
|
+
const scan = await scanFactory.createScan({
|
|
47
|
+
target,
|
|
48
|
+
tests: [TestType.HEADER_SECURITY]
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Below you will find a list of parameters that can be used to configure a `Scan`:
|
|
53
|
+
|
|
54
|
+
| Option | Description |
|
|
55
|
+
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `target` | The target that will be attacked. For details, see [here](#defining-a-target-for-attack). |
|
|
57
|
+
| `tests` | The list of tests to be performed against the target application. [Learn more about tests](https://docs.brightsec.com/docs/vulnerability-guide) |
|
|
58
|
+
| `repeaterId` | Connects the scan to a Repeater agent, which provides secure access to local networks. |
|
|
59
|
+
| `smart` | Minimize scan time by using automatic smart decisions regarding parameter skipping, detection phases, etc. Enabled by default. |
|
|
60
|
+
| `skipStaticParams` | Use an advanced algorithm to automatically determine if a parameter has any effect on the target system's behavior when changed, and skip testing such static parameters. Enabled by default. |
|
|
61
|
+
| `poolSize` | Sets the maximum concurrent requests for the scan, to control the load on your server. By default, `10`. |
|
|
62
|
+
| `attackParamLocations` | Defines which part of the request to attack. By default, `body`, `query`, and `fragment`. |
|
|
63
|
+
| `slowEpTimeout` | Automatically validate entry-point response time before initiating the vulnerability testing, and reduce scan time by skipping any entry-points that take too long to respond. By default, 1000ms. |
|
|
64
|
+
| `targetTimeout` | Measure timeout responses from the target application globally, and stop the scan if the target is unresponsive for longer than the specified time. By default, 5min. |
|
|
65
|
+
| `name` | The scan name. The method and hostname by default, e.g. `GET example.com`. |
|
|
66
|
+
|
|
67
|
+
### Defining a target for attack
|
|
68
|
+
|
|
69
|
+
The target can accept the following options:
|
|
70
|
+
|
|
71
|
+
#### url
|
|
72
|
+
|
|
73
|
+
- type: `string`
|
|
74
|
+
|
|
75
|
+
The server URL that will be used for the request. Usually the `url` represents a WHATWG URL:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
import { Target } from '@sectester/scan';
|
|
79
|
+
|
|
80
|
+
const target = new Target({
|
|
81
|
+
url: 'https://example.com'
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
If `url` contains a query string, they will be parsed as search params:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { Target } from '@sectester/scan';
|
|
89
|
+
|
|
90
|
+
const target = new Target({
|
|
91
|
+
url: 'https://example.com?foo=bar'
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
console.log(target.queryString); // foo=bar
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
If you pass a `query` parameter, it will override these which obtained from `url`:
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
import { Target } from '@sectester/scan';
|
|
101
|
+
|
|
102
|
+
const target = new Target({
|
|
103
|
+
url: 'https://example.com?foo=bar',
|
|
104
|
+
query: '?bar=foo'
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log(target.queryString); // bar=foo
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### method
|
|
111
|
+
|
|
112
|
+
- type: `string | HttpMethod`
|
|
113
|
+
|
|
114
|
+
The request method to be used when making the request, `GET` by default:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import { Target, HttpMethod } from '@sectester/scan';
|
|
118
|
+
|
|
119
|
+
const target = new Target({
|
|
120
|
+
url: 'https://example.com',
|
|
121
|
+
method: HttpMethod.DELETE
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
#### query
|
|
126
|
+
|
|
127
|
+
- type: `string | URLSearchParams | Record<string, string | string[]>`
|
|
128
|
+
|
|
129
|
+
The query parameters to be sent with the request:
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
import { Target } from '@sectester/scan';
|
|
133
|
+
|
|
134
|
+
const target = new Target({
|
|
135
|
+
url: 'https://example.com',
|
|
136
|
+
query: {
|
|
137
|
+
hello: 'world',
|
|
138
|
+
foo: '123'
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
console.log(target.queryString); // hello=world&foo=123
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
If you need to pass an array, you can do it using a `URLSearchParams` instance:
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
import { Target } from '@sectester/scan';
|
|
149
|
+
|
|
150
|
+
const target = new Target({
|
|
151
|
+
url: 'https://example.com',
|
|
152
|
+
query: new URLSearchParams([
|
|
153
|
+
['key', 'a'],
|
|
154
|
+
['key', 'b']
|
|
155
|
+
])
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
console.log(target.queryString); // key=a&key=b
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
> This will override the query string in url.
|
|
162
|
+
|
|
163
|
+
It is possible to define a custom serializer for query parameters:
|
|
164
|
+
|
|
165
|
+
```ts
|
|
166
|
+
import { Target } from '@sectester/scan';
|
|
167
|
+
import { stringify } from 'qs';
|
|
168
|
+
|
|
169
|
+
const target = new Target({
|
|
170
|
+
url: 'https://example.com',
|
|
171
|
+
query: { a: ['b', 'c', 'd'] },
|
|
172
|
+
serializeQuery(params: Record<string, string | string[]>): string {
|
|
173
|
+
return stringify(params);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
console.log(target.queryString); // a[0]=b&a[1]=c&a[2]=d
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
#### headers
|
|
181
|
+
|
|
182
|
+
- type: `Record<string, string | string[]>`
|
|
183
|
+
|
|
184
|
+
The HTTP headers to be sent:
|
|
185
|
+
|
|
186
|
+
```ts
|
|
187
|
+
import { Target } from '@sectester/scan';
|
|
188
|
+
|
|
189
|
+
const target = new Target({
|
|
190
|
+
url: 'https://example.com',
|
|
191
|
+
headers: {
|
|
192
|
+
'content-type': 'application/json'
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### body
|
|
198
|
+
|
|
199
|
+
- type: `unknown`
|
|
200
|
+
|
|
201
|
+
The data to be sent as the request body. Makes sense only for `POST`, `PUT`, `PATCH`, and `DELETE`:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { Target } from '@sectester/scan';
|
|
205
|
+
|
|
206
|
+
const target = new Target({
|
|
207
|
+
url: 'https://example.com',
|
|
208
|
+
body: {
|
|
209
|
+
foo: 'bar'
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
You can use `FormData` objects, such as [form-data](https://www.npmjs.com/package/form-data), as request body as well:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
import { Target } from '@sectester/scan';
|
|
218
|
+
import FormData from 'form-data';
|
|
219
|
+
|
|
220
|
+
const form = new FormData();
|
|
221
|
+
form.append('greeting', 'Hello, world!');
|
|
222
|
+
|
|
223
|
+
const target = new Target({
|
|
224
|
+
url: 'https://example.com',
|
|
225
|
+
body: form
|
|
226
|
+
});
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
It is possible to set a form as body using an instance of `URLSearchParams`:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
import { Target } from '@sectester/scan';
|
|
233
|
+
|
|
234
|
+
const target = new Target({
|
|
235
|
+
url: 'https://example.com',
|
|
236
|
+
body: new URLSearchParams('foo=bar')
|
|
237
|
+
});
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Managing a scan
|
|
241
|
+
|
|
242
|
+
The `Scan` provides a lightweight API to revise and control the status of test execution.
|
|
243
|
+
|
|
244
|
+
For instance, to get a list of found issues, you can use the `issues` method:
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
const issues = await scan.issues();
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
To wait for certain conditions you can use the `expect` method:
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
await scan.expect(Severity.HIGH);
|
|
254
|
+
const issues = await scan.issues();
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
> It returns control as soon as a scan is done, timeout is gone, or an expectation is satisfied.
|
|
258
|
+
|
|
259
|
+
You can also define a custom expectation passing a function that accepts an instance of `Scan` as follows:
|
|
260
|
+
|
|
261
|
+
```ts
|
|
262
|
+
await scan.expect((scan: Scan) => scan.done);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
It might return a `Promise` instance as well:
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
await scan.expect(async (scan: Scan) => {
|
|
269
|
+
const issues = await scan.issues();
|
|
270
|
+
|
|
271
|
+
return issues.length > 3;
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
You can use the `status` method to obtain scan status, to ensure that the scan is done and nothing prevents the user to check for issues, or for other reasons:
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
for await (const state of scan.status()) {
|
|
279
|
+
// your code
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
> This `for...of` will work while a scan is active.
|
|
284
|
+
|
|
285
|
+
To stop scan, use the `stop` method:
|
|
286
|
+
|
|
287
|
+
```ts
|
|
288
|
+
await scan.stop();
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
To dispose a scan, you just need to call the `dispose` method:
|
|
292
|
+
|
|
293
|
+
```ts
|
|
294
|
+
await scan.dispose();
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## License
|
|
298
|
+
|
|
299
|
+
Copyright © 2022 [Bright Security](https://brightsec.com/).
|
|
300
|
+
|
|
301
|
+
This project is licensed under the MIT License - see the [LICENSE file](LICENSE) for details.
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sectester/scan",
|
|
3
|
+
"version": "0.16.1",
|
|
4
|
+
"description": "The package defines a simple public API to manage scans and their expectations.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/NeuraLegion/sectester-js.git"
|
|
8
|
+
},
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=16",
|
|
11
|
+
"npm": "^8.1.0"
|
|
12
|
+
},
|
|
13
|
+
"author": {
|
|
14
|
+
"name": "Artem Derevnjuk",
|
|
15
|
+
"email": "artem.derevnjuk@brightsec.com"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/NeuraLegion/sectester-js/issues"
|
|
20
|
+
},
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"keywords": [
|
|
25
|
+
"security",
|
|
26
|
+
"testing",
|
|
27
|
+
"e2e",
|
|
28
|
+
"test",
|
|
29
|
+
"typescript",
|
|
30
|
+
"appsec",
|
|
31
|
+
"pentesting",
|
|
32
|
+
"qa",
|
|
33
|
+
"brightsec",
|
|
34
|
+
"scan",
|
|
35
|
+
"dast"
|
|
36
|
+
],
|
|
37
|
+
"peerDependencies": {
|
|
38
|
+
"@sectester/bus": ">=0.16.0 <1.0.0",
|
|
39
|
+
"@sectester/core": ">=0.16.0 <1.0.0"
|
|
40
|
+
},
|
|
41
|
+
"main": "./src/index.js",
|
|
42
|
+
"typings": "./src/index.d.ts",
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"reflect-metadata": "^0.1.13",
|
|
45
|
+
"uuid": "^8.3.2",
|
|
46
|
+
"tsyringe": "^4.6.0",
|
|
47
|
+
"chalk": "^4.1.2",
|
|
48
|
+
"form-data": "^4.0.0",
|
|
49
|
+
"axios": "^0.26.1",
|
|
50
|
+
"axios-rate-limit": "^1.3.0",
|
|
51
|
+
"amqp-connection-manager": "^4.1.1",
|
|
52
|
+
"amqplib": "^0.8.0",
|
|
53
|
+
"@har-sdk/core": "^1.4.3",
|
|
54
|
+
"ci-info": "^3.3.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Scans, UploadHarOptions } from './Scans';
|
|
2
|
+
import { Issue, ScanConfig, ScanState } from './models';
|
|
3
|
+
import { CommandDispatcher, Configuration } from '@sectester/core';
|
|
4
|
+
export declare class DefaultScans implements Scans {
|
|
5
|
+
private readonly configuration;
|
|
6
|
+
private readonly commandDispatcher;
|
|
7
|
+
constructor(configuration: Configuration, commandDispatcher: CommandDispatcher);
|
|
8
|
+
createScan(config: ScanConfig): Promise<{
|
|
9
|
+
id: string;
|
|
10
|
+
}>;
|
|
11
|
+
listIssues(id: string): Promise<Issue[]>;
|
|
12
|
+
stopScan(id: string): Promise<void>;
|
|
13
|
+
deleteScan(id: string): Promise<void>;
|
|
14
|
+
getScan(id: string): Promise<ScanState>;
|
|
15
|
+
uploadHar(options: UploadHarOptions): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
}>;
|
|
18
|
+
private sendCommand;
|
|
19
|
+
private assertReply;
|
|
20
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DefaultScans = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const commands_1 = require("./commands");
|
|
6
|
+
const tsyringe_1 = require("tsyringe");
|
|
7
|
+
const core_1 = require("@sectester/core");
|
|
8
|
+
const ci_info_1 = (0, tslib_1.__importDefault)(require("ci-info"));
|
|
9
|
+
let DefaultScans = class DefaultScans {
|
|
10
|
+
constructor(configuration, commandDispatcher) {
|
|
11
|
+
this.configuration = configuration;
|
|
12
|
+
this.commandDispatcher = commandDispatcher;
|
|
13
|
+
}
|
|
14
|
+
createScan(config) {
|
|
15
|
+
return this.sendCommand(new commands_1.CreateScan({
|
|
16
|
+
...config,
|
|
17
|
+
info: {
|
|
18
|
+
source: 'utlib',
|
|
19
|
+
provider: ci_info_1.default.name,
|
|
20
|
+
client: {
|
|
21
|
+
name: this.configuration.name,
|
|
22
|
+
version: this.configuration.version
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
27
|
+
async listIssues(id) {
|
|
28
|
+
const issues = await this.sendCommand(new commands_1.ListIssues(id));
|
|
29
|
+
return issues.map(x => ({
|
|
30
|
+
...x,
|
|
31
|
+
link: `${this.configuration.api}/scans/${id}/issues/${x.id}`
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
async stopScan(id) {
|
|
35
|
+
await this.commandDispatcher.execute(new commands_1.StopScan(id));
|
|
36
|
+
}
|
|
37
|
+
async deleteScan(id) {
|
|
38
|
+
await this.commandDispatcher.execute(new commands_1.DeleteScan(id));
|
|
39
|
+
}
|
|
40
|
+
getScan(id) {
|
|
41
|
+
return this.sendCommand(new commands_1.GetScan(id));
|
|
42
|
+
}
|
|
43
|
+
uploadHar(options) {
|
|
44
|
+
return this.sendCommand(new commands_1.UploadHar(options));
|
|
45
|
+
}
|
|
46
|
+
async sendCommand(command) {
|
|
47
|
+
const result = await this.commandDispatcher.execute(command);
|
|
48
|
+
this.assertReply(result);
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
assertReply(result) {
|
|
52
|
+
if (!result) {
|
|
53
|
+
throw new Error('Something went wrong. Please try again later.');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
DefaultScans = (0, tslib_1.__decorate)([
|
|
58
|
+
(0, tsyringe_1.injectable)(),
|
|
59
|
+
(0, tslib_1.__param)(1, (0, tsyringe_1.inject)(core_1.CommandDispatcher)),
|
|
60
|
+
(0, tslib_1.__metadata)("design:paramtypes", [core_1.Configuration, Object])
|
|
61
|
+
], DefaultScans);
|
|
62
|
+
exports.DefaultScans = DefaultScans;
|
|
63
|
+
//# sourceMappingURL=DefaultScans.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DefaultScans.js","sourceRoot":"","sources":["../../../../packages/scan/src/DefaultScans.ts"],"names":[],"mappings":";;;;AACA,yCAOoB;AAEpB,uCAA8C;AAC9C,0CAA4E;AAC5E,mEAAyB;AAGzB,IAAa,YAAY,GAAzB,MAAa,YAAY;IACvB,YACmB,aAA4B,EAE5B,iBAAoC;QAFpC,kBAAa,GAAb,aAAa,CAAe;QAE5B,sBAAiB,GAAjB,iBAAiB,CAAmB;IACpD,CAAC;IAEG,UAAU,CAAC,MAAkB;QAClC,OAAO,IAAI,CAAC,WAAW,CACrB,IAAI,qBAAU,CAAC;YACb,GAAG,MAAM;YACT,IAAI,EAAE;gBACJ,MAAM,EAAE,OAAO;gBACf,QAAQ,EAAE,iBAAE,CAAC,IAAI;gBACjB,MAAM,EAAE;oBACN,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI;oBAC7B,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,OAAO;iBACpC;aACF;SACF,CAAC,CACH,CAAC;IACJ,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,EAAU;QAChC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,qBAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QAE1D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACtB,GAAG,CAAC;YACJ,IAAI,EAAE,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,UAAU,EAAE,WAAW,CAAC,CAAC,EAAE,EAAE;SAC7D,CAAC,CAAC,CAAC;IACN,CAAC;IAEM,KAAK,CAAC,QAAQ,CAAC,EAAU;QAC9B,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,mBAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;IACzD,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,EAAU;QAChC,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,IAAI,qBAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;IAEM,OAAO,CAAC,EAAU;QACvB,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,kBAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,CAAC;IAEM,SAAS,CAAC,OAAyB;QACxC,OAAO,IAAI,CAAC,WAAW,CAAC,IAAI,oBAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAClD,CAAC;IAEO,KAAK,CAAC,WAAW,CAAO,OAAsB;QACpD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAE7D,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAEzB,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,WAAW,CACjB,MAAqB;QAErB,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;SAClE;IACH,CAAC;CACF,CAAA;AA/DY,YAAY;IADxB,IAAA,qBAAU,GAAE;IAIR,wBAAA,IAAA,iBAAM,EAAC,wBAAiB,CAAC,CAAA;kDADM,oBAAa;GAFpC,YAAY,CA+DxB;AA/DY,oCAAY"}
|
package/src/Scan.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Scans } from './Scans';
|
|
2
|
+
import { Issue, ScanState, Severity } from './models';
|
|
3
|
+
import { Logger } from '@sectester/core';
|
|
4
|
+
export interface ScanOptions {
|
|
5
|
+
id: string;
|
|
6
|
+
scans: Scans;
|
|
7
|
+
logger?: Logger;
|
|
8
|
+
pollingInterval?: number;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class Scan {
|
|
12
|
+
readonly id: string;
|
|
13
|
+
private readonly ACTIVE_STATUSES;
|
|
14
|
+
private readonly DONE_STATUSES;
|
|
15
|
+
private readonly scans;
|
|
16
|
+
private readonly pollingInterval;
|
|
17
|
+
private readonly logger;
|
|
18
|
+
private readonly timeout;
|
|
19
|
+
private state;
|
|
20
|
+
constructor({ id, scans, logger, timeout, pollingInterval }: ScanOptions);
|
|
21
|
+
get active(): boolean;
|
|
22
|
+
get done(): boolean;
|
|
23
|
+
issues(): Promise<Issue[]>;
|
|
24
|
+
status(): AsyncIterableIterator<ScanState>;
|
|
25
|
+
expect(expectation: Severity | ((scan: Scan) => unknown)): Promise<void>;
|
|
26
|
+
dispose(): Promise<void>;
|
|
27
|
+
stop(): Promise<void>;
|
|
28
|
+
private assert;
|
|
29
|
+
private refreshState;
|
|
30
|
+
private changingStatus;
|
|
31
|
+
private createPredicate;
|
|
32
|
+
private satisfyExpectation;
|
|
33
|
+
}
|
package/src/Scan.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Scan = void 0;
|
|
4
|
+
const models_1 = require("./models");
|
|
5
|
+
const exceptions_1 = require("./exceptions");
|
|
6
|
+
const core_1 = require("@sectester/core");
|
|
7
|
+
class Scan {
|
|
8
|
+
constructor({ id, scans, logger, timeout, pollingInterval = 5 * 1000 }) {
|
|
9
|
+
this.ACTIVE_STATUSES = new Set([
|
|
10
|
+
models_1.ScanStatus.PENDING,
|
|
11
|
+
models_1.ScanStatus.RUNNING,
|
|
12
|
+
models_1.ScanStatus.QUEUED
|
|
13
|
+
]);
|
|
14
|
+
this.DONE_STATUSES = new Set([
|
|
15
|
+
models_1.ScanStatus.DISRUPTED,
|
|
16
|
+
models_1.ScanStatus.DONE,
|
|
17
|
+
models_1.ScanStatus.FAILED,
|
|
18
|
+
models_1.ScanStatus.STOPPED
|
|
19
|
+
]);
|
|
20
|
+
this.state = { status: models_1.ScanStatus.PENDING };
|
|
21
|
+
this.scans = scans;
|
|
22
|
+
this.logger = logger;
|
|
23
|
+
this.id = id;
|
|
24
|
+
this.pollingInterval = pollingInterval;
|
|
25
|
+
this.timeout = timeout;
|
|
26
|
+
}
|
|
27
|
+
get active() {
|
|
28
|
+
return this.ACTIVE_STATUSES.has(this.state.status);
|
|
29
|
+
}
|
|
30
|
+
get done() {
|
|
31
|
+
return this.DONE_STATUSES.has(this.state.status);
|
|
32
|
+
}
|
|
33
|
+
async issues() {
|
|
34
|
+
await this.refreshState();
|
|
35
|
+
return this.scans.listIssues(this.id);
|
|
36
|
+
}
|
|
37
|
+
async *status() {
|
|
38
|
+
while (this.active) {
|
|
39
|
+
await (0, core_1.delay)(this.pollingInterval);
|
|
40
|
+
yield this.refreshState();
|
|
41
|
+
}
|
|
42
|
+
return this.state;
|
|
43
|
+
}
|
|
44
|
+
async expect(expectation) {
|
|
45
|
+
let timeoutPassed = false;
|
|
46
|
+
const timer = this.timeout
|
|
47
|
+
? setTimeout(() => (timeoutPassed = true), this.timeout)
|
|
48
|
+
: undefined;
|
|
49
|
+
const predicate = this.createPredicate(expectation);
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
51
|
+
for await (const _ of this.status()) {
|
|
52
|
+
const preventFurtherPolling = (await predicate()) || this.done || timeoutPassed;
|
|
53
|
+
if (preventFurtherPolling) {
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (timer) {
|
|
58
|
+
clearTimeout(timer);
|
|
59
|
+
}
|
|
60
|
+
this.assert(timeoutPassed);
|
|
61
|
+
}
|
|
62
|
+
async dispose() {
|
|
63
|
+
try {
|
|
64
|
+
await this.refreshState();
|
|
65
|
+
if (!this.active) {
|
|
66
|
+
await this.scans.deleteScan(this.id);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
// noop
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
async stop() {
|
|
74
|
+
try {
|
|
75
|
+
await this.refreshState();
|
|
76
|
+
if (this.active) {
|
|
77
|
+
await this.scans.stopScan(this.id);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// noop
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
assert(timeoutPassed) {
|
|
85
|
+
var _a;
|
|
86
|
+
const { status } = this.state;
|
|
87
|
+
if (this.done && status !== models_1.ScanStatus.DONE) {
|
|
88
|
+
throw new exceptions_1.ScanAborted(status);
|
|
89
|
+
}
|
|
90
|
+
if (timeoutPassed) {
|
|
91
|
+
throw new exceptions_1.ScanTimedOut((_a = this.timeout) !== null && _a !== void 0 ? _a : 0);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async refreshState() {
|
|
95
|
+
if (!this.done) {
|
|
96
|
+
const lastState = this.state;
|
|
97
|
+
this.state = await this.scans.getScan(this.id);
|
|
98
|
+
this.changingStatus(lastState.status, this.state.status);
|
|
99
|
+
}
|
|
100
|
+
return this.state;
|
|
101
|
+
}
|
|
102
|
+
changingStatus(from, to) {
|
|
103
|
+
var _a, _b;
|
|
104
|
+
if (from !== models_1.ScanStatus.QUEUED && to === models_1.ScanStatus.QUEUED) {
|
|
105
|
+
(_a = this.logger) === null || _a === void 0 ? void 0 : _a.warn('The maximum amount of concurrent scans has been reached for the organization, ' +
|
|
106
|
+
'the execution will resume once a free engine will be available. ' +
|
|
107
|
+
'If you want to increase the execution concurrency, ' +
|
|
108
|
+
'please upgrade your subscription or contact your system administrator');
|
|
109
|
+
}
|
|
110
|
+
if (from === models_1.ScanStatus.QUEUED && to !== models_1.ScanStatus.QUEUED) {
|
|
111
|
+
(_b = this.logger) === null || _b === void 0 ? void 0 : _b.log('Connected to engine, resuming execution');
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
createPredicate(expectation) {
|
|
115
|
+
return () => {
|
|
116
|
+
try {
|
|
117
|
+
return typeof expectation === 'function'
|
|
118
|
+
? expectation(this)
|
|
119
|
+
: this.satisfyExpectation(expectation);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// noop
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
satisfyExpectation(severity) {
|
|
127
|
+
var _a;
|
|
128
|
+
const issueGroups = (_a = this.state.issuesBySeverity) !== null && _a !== void 0 ? _a : [];
|
|
129
|
+
return issueGroups.some((x) => { var _a; return ((_a = models_1.severityRanges.get(severity)) === null || _a === void 0 ? void 0 : _a.includes(x.type)) && x.number > 0; });
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
exports.Scan = Scan;
|
|
133
|
+
//# sourceMappingURL=Scan.js.map
|
package/src/Scan.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Scan.js","sourceRoot":"","sources":["../../../../packages/scan/src/Scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Scan } from './Scan';
|
|
2
|
+
import { ScanSettings, ScanSettingsOptions } from './ScanSettings';
|
|
3
|
+
import { Configuration } from '@sectester/core';
|
|
4
|
+
export declare class ScanFactory {
|
|
5
|
+
private readonly configuration;
|
|
6
|
+
private readonly scans;
|
|
7
|
+
private readonly container;
|
|
8
|
+
private readonly logger;
|
|
9
|
+
constructor(configuration: Configuration);
|
|
10
|
+
createScan(settings: ScanSettings | ScanSettingsOptions, options?: {
|
|
11
|
+
timeout?: number;
|
|
12
|
+
pollingInterval?: number;
|
|
13
|
+
}): Promise<Scan>;
|
|
14
|
+
private buildScanConfig;
|
|
15
|
+
private createAndUploadHar;
|
|
16
|
+
private generateFilename;
|
|
17
|
+
private createHarEntry;
|
|
18
|
+
private createHar;
|
|
19
|
+
}
|