secure-review-extension 1.0.6 → 1.0.9
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/README.md +364 -203
- package/extension.js +92 -11
- package/package.json +2 -2
- package/src/scanners/static-scan.js +23 -7
package/README.md
CHANGED
|
@@ -1,76 +1,123 @@
|
|
|
1
|
-
# Secure Review
|
|
1
|
+
# Secure Review
|
|
2
2
|
|
|
3
|
-
Secure Review is a VS Code extension
|
|
3
|
+
Secure Review is a VS Code extension and local CLI for static secure code review, dependency review, and Docker-based dynamic web security testing.
|
|
4
4
|
|
|
5
|
-
It
|
|
5
|
+
It is designed to help developers and security teams scan local repositories or Bitbucket-hosted repositories without needing to manually stitch together multiple tools.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## What You Can Do With It
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
9
|
+
- Run static workspace scans inside VS Code
|
|
10
|
+
- Scan the currently open file
|
|
11
|
+
- Review findings in a dedicated activity bar view
|
|
12
|
+
- See inline diagnostics in the editor
|
|
13
|
+
- Open a report webview with summaries, evidence, and remediation guidance
|
|
14
|
+
- Export findings as DOCX from the extension
|
|
15
|
+
- Run the same engine from the terminal with the `secure-review` CLI
|
|
16
|
+
- Scan Bitbucket repositories directly by URL
|
|
17
|
+
- Enrich results with local tools such as `semgrep`, `eslint`, `bandit`, `pip-audit`, `gosec`, `cppcheck`, and others when available
|
|
18
|
+
- Run OWASP ZAP dynamic scans against developer-controlled local or test web applications
|
|
19
|
+
|
|
20
|
+
## Key Capabilities
|
|
21
|
+
|
|
22
|
+
### Static review
|
|
23
|
+
|
|
24
|
+
Secure Review combines built-in rule packs, repository heuristics, optional external tools, and stack-aware checks.
|
|
25
|
+
|
|
26
|
+
It covers areas such as:
|
|
27
|
+
|
|
28
|
+
- hard-coded secrets and credentials
|
|
29
|
+
- weak cryptography usage
|
|
30
|
+
- command execution risks
|
|
31
|
+
- injection-style patterns
|
|
32
|
+
- auth and authorization issues
|
|
33
|
+
- dependency and supply-chain risks
|
|
34
|
+
- configuration and infrastructure risks
|
|
35
|
+
- testing gaps
|
|
36
|
+
- reliability, maintainability, and performance smells
|
|
37
|
+
|
|
38
|
+
### Dynamic review
|
|
39
|
+
|
|
40
|
+
Secure Review can launch OWASP ZAP through Docker and run:
|
|
41
|
+
|
|
42
|
+
- baseline scans for passive checks
|
|
43
|
+
- full scans for active testing
|
|
44
|
+
- API-focused scans using an API definition URL when available
|
|
45
|
+
|
|
46
|
+
Dynamic findings are grouped and normalized into the same reporting model used by static scans.
|
|
47
|
+
|
|
48
|
+
### CLI agent
|
|
49
|
+
|
|
50
|
+
The `secure-review` CLI supports:
|
|
51
|
+
|
|
52
|
+
- local repository inspection
|
|
53
|
+
- bootstrap planning for scanner tools
|
|
54
|
+
- local path scans
|
|
55
|
+
- Bitbucket repository scans by HTTPS or SSH URL
|
|
56
|
+
- optional report export
|
|
57
|
+
- optional dynamic scan integration
|
|
19
58
|
|
|
20
59
|
## Installation
|
|
21
60
|
|
|
22
|
-
### Visual Studio Marketplace
|
|
61
|
+
### Option 1: Install From Visual Studio Marketplace
|
|
23
62
|
|
|
24
|
-
1.
|
|
25
|
-
2.
|
|
26
|
-
3.
|
|
63
|
+
1. Open VS Code.
|
|
64
|
+
2. Open the Extensions view.
|
|
65
|
+
3. Search for `Secure Review`.
|
|
66
|
+
4. Click `Install`.
|
|
27
67
|
|
|
28
|
-
### VSIX
|
|
68
|
+
### Option 2: Install From VSIX
|
|
29
69
|
|
|
30
|
-
|
|
70
|
+
If you have a packaged `.vsix` file:
|
|
71
|
+
|
|
72
|
+
1. Open VS Code.
|
|
73
|
+
2. Open the Extensions view.
|
|
74
|
+
3. Choose `Extensions: Install from VSIX...`
|
|
75
|
+
4. Select the `.vsix` file.
|
|
76
|
+
|
|
77
|
+
If you are packaging the extension from source:
|
|
31
78
|
|
|
32
79
|
```bash
|
|
80
|
+
npm install
|
|
81
|
+
npm run verify
|
|
33
82
|
npm run package
|
|
34
83
|
```
|
|
35
84
|
|
|
36
|
-
|
|
37
|
-
3. Select the generated `.vsix` file.
|
|
85
|
+
This creates a `.vsix` package in the repository root.
|
|
38
86
|
|
|
39
|
-
### CLI
|
|
87
|
+
### Option 3: Install The CLI
|
|
40
88
|
|
|
41
|
-
|
|
89
|
+
From npm:
|
|
42
90
|
|
|
43
91
|
```bash
|
|
44
|
-
npm
|
|
92
|
+
npm install -g secure-review-extension
|
|
45
93
|
```
|
|
46
94
|
|
|
47
|
-
Then
|
|
95
|
+
Then run:
|
|
48
96
|
|
|
49
97
|
```bash
|
|
50
98
|
secure-review help
|
|
51
99
|
```
|
|
52
100
|
|
|
53
|
-
|
|
101
|
+
If you are using the source repository locally:
|
|
54
102
|
|
|
55
103
|
```bash
|
|
56
|
-
npm
|
|
57
|
-
npm
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
To build the tarball you would share or publish:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
npm run pack:cli
|
|
104
|
+
npm install
|
|
105
|
+
npm link
|
|
106
|
+
secure-review help
|
|
64
107
|
```
|
|
65
108
|
|
|
66
|
-
|
|
109
|
+
## Quick Start In VS Code
|
|
67
110
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
111
|
+
1. Open a project folder in VS Code.
|
|
112
|
+
2. Open the Command Palette.
|
|
113
|
+
3. Run `Secure Review: Scan Workspace`.
|
|
114
|
+
4. Open the `Secure Review` activity bar view to inspect findings.
|
|
115
|
+
5. Run `Secure Review: Open Review Report` to see the in-editor report.
|
|
116
|
+
6. Run `Secure Review: Export Findings Report` to create a DOCX report.
|
|
71
117
|
|
|
72
|
-
|
|
118
|
+
Available extension commands:
|
|
73
119
|
|
|
120
|
+
- `Secure Review: Check Workspace Requirements`
|
|
74
121
|
- `Secure Review: Scan Workspace`
|
|
75
122
|
- `Secure Review: Scan Current File`
|
|
76
123
|
- `Secure Review: Dynamic Scan Local App`
|
|
@@ -79,183 +126,192 @@ npm run publish:npm
|
|
|
79
126
|
- `Secure Review: Clear Findings`
|
|
80
127
|
- `Secure Review: Ignore Finding`
|
|
81
128
|
|
|
82
|
-
## CLI
|
|
129
|
+
## Quick Start In The CLI
|
|
83
130
|
|
|
84
|
-
|
|
131
|
+
Inspect a local repository:
|
|
85
132
|
|
|
86
133
|
```bash
|
|
87
134
|
secure-review inspect /path/to/repo
|
|
88
|
-
secure-review inspect https://bitbucket.org/acme/payments-service
|
|
89
|
-
secure-review inspect https://bitbucket.org/acme/payments-service/src/main/
|
|
90
|
-
secure-review bootstrap /path/to/repo
|
|
91
|
-
secure-review bootstrap /path/to/repo --run
|
|
92
|
-
secure-review bootstrap git@bitbucket.org:acme/payments-service.git
|
|
93
|
-
secure-review scan /path/to/repo --severity medium
|
|
94
|
-
secure-review scan https://bitbucket.org/acme/payments-service/src/release-1.2/ --severity high
|
|
95
|
-
secure-review scan /path/to/repo --format html --out report.html
|
|
96
|
-
secure-review scan /path/to/repo --format docx --out report.docx
|
|
97
|
-
secure-review scan /path/to/repo --dynamic-url http://127.0.0.1:3001 --dynamic-mode baseline
|
|
98
135
|
```
|
|
99
136
|
|
|
100
|
-
|
|
101
|
-
- `inspect`
|
|
102
|
-
Shows detected languages, frameworks, and recommended scanner tools for a workspace or Bitbucket repository URL.
|
|
103
|
-
- `bootstrap`
|
|
104
|
-
Prints the install plan for the workspace, or runs the supported install commands with `--run`.
|
|
105
|
-
- `scan`
|
|
106
|
-
Runs static review, optionally adds a Docker-based ZAP dynamic scan, and can export text, JSON, HTML, Markdown, or DOCX output.
|
|
107
|
-
|
|
108
|
-
Bitbucket remote scan support:
|
|
109
|
-
- pass a normal Bitbucket repo URL such as `https://bitbucket.org/workspace/repo`
|
|
110
|
-
- pass a Bitbucket browser URL such as `https://bitbucket.org/workspace/repo/src/main/`
|
|
111
|
-
- pass an SSH clone URL such as `git@bitbucket.org:workspace/repo.git`
|
|
112
|
-
- Secure Review clones the repo to a temporary workspace, scans it, then cleans up automatically
|
|
113
|
-
- use `--branch <name>` to override the branch when the URL does not already specify one
|
|
114
|
-
- default scan exclusions skip noisy dependency and build folders such as `.venv`, `venv`, `node_modules`, `dist`, `build`, `target`, `coverage`, and `__pycache__`
|
|
115
|
-
|
|
116
|
-
## npm Publishing Notes
|
|
117
|
-
|
|
118
|
-
Before publishing the CLI package for other users:
|
|
119
|
-
- replace the placeholder npm package name in [package.json](/home/ankit.singh/CODE_REVIEW_TOOL/package.json) if needed
|
|
120
|
-
- replace placeholder homepage, repository, and bugs URLs
|
|
121
|
-
- make sure the package name is actually available on npm
|
|
122
|
-
- run `npm run verify`
|
|
123
|
-
- run `npm run pack:cli:dry-run`
|
|
124
|
-
- run `npm run pack:cli`
|
|
125
|
-
- test the generated tarball locally with `npm install -g ./<tarball>.tgz`
|
|
126
|
-
- publish with `npm run publish:npm`
|
|
127
|
-
|
|
128
|
-
## What The Extension Checks
|
|
129
|
-
|
|
130
|
-
### Static checks
|
|
137
|
+
Inspect a Bitbucket repository:
|
|
131
138
|
|
|
132
|
-
|
|
133
|
-
-
|
|
134
|
-
|
|
135
|
-
- command execution sinks
|
|
136
|
-
- dangerous HTML injection patterns
|
|
137
|
-
- debug and verbose logging smells
|
|
138
|
-
- unsafe eval-like execution
|
|
139
|
-
|
|
140
|
-
### Review domains
|
|
141
|
-
|
|
142
|
-
- security and vulnerability checks
|
|
143
|
-
- dependency and supply-chain checks
|
|
144
|
-
- code quality and maintainability
|
|
145
|
-
- reliability and error handling
|
|
146
|
-
- performance smells
|
|
147
|
-
- outdated practices
|
|
148
|
-
- testing gaps
|
|
139
|
+
```bash
|
|
140
|
+
secure-review inspect https://bitbucket.org/workspace/repository
|
|
141
|
+
```
|
|
149
142
|
|
|
150
|
-
|
|
143
|
+
See which optional scanner tools are recommended:
|
|
151
144
|
|
|
152
|
-
|
|
153
|
-
-
|
|
154
|
-
|
|
155
|
-
- cookie issues
|
|
156
|
-
- information disclosure
|
|
157
|
-
- XSS and injection candidates surfaced by ZAP
|
|
158
|
-
|
|
159
|
-
Dynamic scans are intended only for developer-controlled local or test URLs. Full scan mode is intrusive and requires explicit confirmation.
|
|
145
|
+
```bash
|
|
146
|
+
secure-review bootstrap /path/to/repo
|
|
147
|
+
```
|
|
160
148
|
|
|
161
|
-
|
|
149
|
+
Run a scan:
|
|
162
150
|
|
|
163
|
-
|
|
164
|
-
-
|
|
165
|
-
|
|
166
|
-
- report date
|
|
167
|
-
- scan type
|
|
168
|
-
- optional notes
|
|
169
|
-
- Reports include:
|
|
170
|
-
- executive summary
|
|
171
|
-
- severity summary
|
|
172
|
-
- findings by category
|
|
173
|
-
- findings by review domain
|
|
174
|
-
- overview grouped by severity
|
|
175
|
-
- detailed findings with evidence, why-it-matters, remediation, and suggestions
|
|
176
|
-
- recommendations summary
|
|
177
|
-
- methodology, limitations, and scan configuration
|
|
151
|
+
```bash
|
|
152
|
+
secure-review scan /path/to/repo --severity medium
|
|
153
|
+
```
|
|
178
154
|
|
|
179
|
-
|
|
155
|
+
Export HTML output:
|
|
180
156
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
4. Run `Secure Review: Scan Workspace` from the Command Palette.
|
|
185
|
-
5. Open the `Secure Review` activity bar icon to inspect findings.
|
|
186
|
-
6. Run `Secure Review: Open Review Report` to see the webview report.
|
|
187
|
-
7. Run `Secure Review: Export Findings Report` to create the Word report.
|
|
157
|
+
```bash
|
|
158
|
+
secure-review scan /path/to/repo --format html --out review.html
|
|
159
|
+
```
|
|
188
160
|
|
|
189
|
-
|
|
161
|
+
Export DOCX output:
|
|
190
162
|
|
|
191
|
-
|
|
163
|
+
```bash
|
|
164
|
+
secure-review scan /path/to/repo --format docx --out review.docx
|
|
165
|
+
```
|
|
192
166
|
|
|
193
|
-
|
|
167
|
+
Run a scan against a Bitbucket repository without cloning it manually:
|
|
194
168
|
|
|
195
169
|
```bash
|
|
196
|
-
|
|
170
|
+
secure-review scan git@bitbucket.org:workspace/repository.git --severity medium
|
|
197
171
|
```
|
|
198
172
|
|
|
199
|
-
|
|
173
|
+
## CLI Commands
|
|
174
|
+
|
|
175
|
+
### `inspect`
|
|
176
|
+
|
|
177
|
+
Displays detected languages, frameworks, and recommended scanner tools for:
|
|
178
|
+
|
|
179
|
+
- a local workspace path
|
|
180
|
+
- a Bitbucket repository URL
|
|
181
|
+
- a Bitbucket browser URL with `/src/<branch>/`
|
|
182
|
+
- a Bitbucket SSH clone URL
|
|
183
|
+
|
|
184
|
+
Examples:
|
|
200
185
|
|
|
201
186
|
```bash
|
|
202
|
-
secure-review inspect /
|
|
187
|
+
secure-review inspect /path/to/repo
|
|
188
|
+
secure-review inspect https://bitbucket.org/acme/payments-service
|
|
189
|
+
secure-review inspect https://bitbucket.org/acme/payments-service/src/main/
|
|
190
|
+
secure-review inspect git@bitbucket.org:acme/payments-service.git
|
|
203
191
|
```
|
|
204
192
|
|
|
205
|
-
|
|
193
|
+
### `bootstrap`
|
|
194
|
+
|
|
195
|
+
Prints the install plan for matching scanner tools. With `--run`, Secure Review executes the supported install commands when possible.
|
|
196
|
+
|
|
197
|
+
Examples:
|
|
206
198
|
|
|
207
199
|
```bash
|
|
208
|
-
secure-review
|
|
200
|
+
secure-review bootstrap /path/to/repo
|
|
201
|
+
secure-review bootstrap /path/to/repo --run
|
|
202
|
+
secure-review bootstrap git@bitbucket.org:acme/payments-service.git
|
|
209
203
|
```
|
|
210
204
|
|
|
211
|
-
|
|
205
|
+
### `scan`
|
|
206
|
+
|
|
207
|
+
Runs static review, optional dynamic review, and optional report export.
|
|
208
|
+
|
|
209
|
+
Examples:
|
|
212
210
|
|
|
213
211
|
```bash
|
|
214
|
-
secure-review
|
|
212
|
+
secure-review scan /path/to/repo --severity low
|
|
213
|
+
secure-review scan /path/to/repo --severity high --format json --out findings.json
|
|
214
|
+
secure-review scan /path/to/repo --format html --out review.html
|
|
215
|
+
secure-review scan /path/to/repo --format docx --out review.docx
|
|
216
|
+
secure-review scan https://bitbucket.org/acme/payments-service/src/release-1.2/ --severity medium
|
|
217
|
+
secure-review scan git@bitbucket.org:acme/payments-service.git --branch main --severity medium
|
|
215
218
|
```
|
|
216
219
|
|
|
217
|
-
|
|
220
|
+
## Bitbucket Repository Support
|
|
221
|
+
|
|
222
|
+
Secure Review can scan repositories that are not already present on the local machine.
|
|
223
|
+
|
|
224
|
+
Supported inputs:
|
|
225
|
+
|
|
226
|
+
- `https://bitbucket.org/workspace/repo`
|
|
227
|
+
- `https://bitbucket.org/workspace/repo/src/main/`
|
|
228
|
+
- `git@bitbucket.org:workspace/repo.git`
|
|
229
|
+
|
|
230
|
+
Behavior:
|
|
231
|
+
|
|
232
|
+
- the repository is cloned to a temporary directory
|
|
233
|
+
- the requested branch is resolved automatically when possible
|
|
234
|
+
- the scan runs against that temporary workspace
|
|
235
|
+
- the temporary clone is cleaned up after the scan
|
|
236
|
+
|
|
237
|
+
Tips:
|
|
238
|
+
|
|
239
|
+
- use SSH URLs for private repositories if SSH access is already configured
|
|
240
|
+
- use `--branch <name>` to override the branch when the URL does not specify one
|
|
241
|
+
|
|
242
|
+
## Dynamic Scan Usage
|
|
243
|
+
|
|
244
|
+
Dynamic scanning is intended only for applications and endpoints you control.
|
|
245
|
+
|
|
246
|
+
Requirements:
|
|
247
|
+
|
|
248
|
+
- Docker installed and running
|
|
249
|
+
- a reachable local or test web application
|
|
250
|
+
- a configured target URL
|
|
251
|
+
|
|
252
|
+
Example local app:
|
|
218
253
|
|
|
219
254
|
```bash
|
|
220
|
-
|
|
255
|
+
PORT=3001 node sample-workspace/dev-server.js
|
|
221
256
|
```
|
|
222
257
|
|
|
223
|
-
|
|
258
|
+
CLI example:
|
|
224
259
|
|
|
225
260
|
```bash
|
|
226
|
-
secure-review scan
|
|
261
|
+
secure-review scan /path/to/repo \
|
|
262
|
+
--dynamic-url http://127.0.0.1:3001 \
|
|
263
|
+
--dynamic-mode baseline
|
|
227
264
|
```
|
|
228
265
|
|
|
229
|
-
|
|
266
|
+
API scan mode example:
|
|
230
267
|
|
|
231
268
|
```bash
|
|
232
|
-
secure-review scan /
|
|
269
|
+
secure-review scan /path/to/repo \
|
|
270
|
+
--dynamic-url http://127.0.0.1:3001 \
|
|
271
|
+
--dynamic-mode api \
|
|
272
|
+
--dynamic-api-url http://127.0.0.1:3001/openapi.json
|
|
233
273
|
```
|
|
234
274
|
|
|
235
|
-
|
|
275
|
+
Dynamic scan modes:
|
|
236
276
|
|
|
237
|
-
|
|
238
|
-
|
|
277
|
+
- `baseline`: passive checks and safer first pass
|
|
278
|
+
- `full`: active testing for controlled targets only
|
|
279
|
+
- `api`: API-oriented scan using a provided definition URL
|
|
239
280
|
|
|
240
|
-
|
|
241
|
-
PORT=3001 node sample-workspace/dev-server.js
|
|
242
|
-
```
|
|
281
|
+
Typical dynamic findings include:
|
|
243
282
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
283
|
+
- missing security headers
|
|
284
|
+
- cookie security issues
|
|
285
|
+
- information disclosure
|
|
286
|
+
- reflected or stored attack candidates surfaced by ZAP
|
|
287
|
+
- transport and response hardening issues
|
|
247
288
|
|
|
248
|
-
##
|
|
289
|
+
## What Secure Review Checks
|
|
249
290
|
|
|
250
|
-
|
|
291
|
+
Secure Review blends several scan styles into one findings model.
|
|
251
292
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
293
|
+
### Built-in static rules
|
|
294
|
+
|
|
295
|
+
- secrets and credentials
|
|
296
|
+
- dangerous sinks such as shell execution, HTML injection, and weak crypto
|
|
297
|
+
- auth and authorization patterns
|
|
298
|
+
- framework-aware checks
|
|
299
|
+
- code quality and maintainability warnings
|
|
300
|
+
|
|
301
|
+
### Repository heuristics
|
|
302
|
+
|
|
303
|
+
- dependency hygiene and supply-chain risks
|
|
304
|
+
- runtime and environment configuration concerns
|
|
305
|
+
- Docker, Kubernetes, Terraform, and compose issues
|
|
306
|
+
- package-manager and deployment misconfiguration
|
|
307
|
+
|
|
308
|
+
### External tool integrations
|
|
309
|
+
|
|
310
|
+
When the relevant tools are installed locally, Secure Review can enrich results using:
|
|
255
311
|
|
|
256
|
-
That command inspects the current workspace and prints the install plan for tools such as:
|
|
257
312
|
- `semgrep`
|
|
258
313
|
- `eslint`
|
|
314
|
+
- `npm audit`
|
|
259
315
|
- `bandit`
|
|
260
316
|
- `pip-audit`
|
|
261
317
|
- `spotbugs`
|
|
@@ -264,65 +320,170 @@ That command inspects the current workspace and prints the install plan for tool
|
|
|
264
320
|
- `cargo-audit`
|
|
265
321
|
- `clippy`
|
|
266
322
|
- `cppcheck`
|
|
323
|
+
- `brakeman`
|
|
324
|
+
- `phpstan`
|
|
325
|
+
- `.NET` package vulnerability checks
|
|
267
326
|
|
|
268
|
-
|
|
327
|
+
### Finding quality metadata
|
|
269
328
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
329
|
+
Findings include richer classification so the output is more honest and easier to review manually. Depending on the engine and evidence, findings may be classified as:
|
|
330
|
+
|
|
331
|
+
- likely vulnerabilities
|
|
332
|
+
- runtime vulnerabilities
|
|
333
|
+
- dependency risks
|
|
334
|
+
- contextual warnings
|
|
335
|
+
- recommendations
|
|
336
|
+
|
|
337
|
+
They may also include evidence strength, origin, and a manual-review recommendation flag.
|
|
338
|
+
|
|
339
|
+
## Default Scan Exclusions
|
|
340
|
+
|
|
341
|
+
To reduce noise and improve performance, Secure Review skips common dependency and build folders by default, including:
|
|
342
|
+
|
|
343
|
+
- `.git`
|
|
344
|
+
- `node_modules`
|
|
345
|
+
- `.venv`
|
|
346
|
+
- `venv`
|
|
347
|
+
- `env`
|
|
348
|
+
- `vendor`
|
|
349
|
+
- `dist`
|
|
350
|
+
- `build`
|
|
351
|
+
- `target`
|
|
352
|
+
- `coverage`
|
|
353
|
+
- `__pycache__`
|
|
354
|
+
|
|
355
|
+
This helps the scanner stay focused on project code rather than vendored packages and generated artifacts.
|
|
356
|
+
|
|
357
|
+
## Report Output
|
|
358
|
+
|
|
359
|
+
### In VS Code
|
|
360
|
+
|
|
361
|
+
The extension can export findings as a DOCX report.
|
|
362
|
+
|
|
363
|
+
The export flow prompts for:
|
|
364
|
+
|
|
365
|
+
- project name
|
|
366
|
+
- report date
|
|
367
|
+
- scan type
|
|
368
|
+
- optional notes
|
|
369
|
+
|
|
370
|
+
The report includes:
|
|
371
|
+
|
|
372
|
+
- executive summary
|
|
373
|
+
- severity summary
|
|
374
|
+
- findings by category
|
|
375
|
+
- findings by review domain
|
|
376
|
+
- severity-grouped overview
|
|
377
|
+
- detailed findings with evidence and remediation guidance
|
|
378
|
+
- recommendations summary
|
|
379
|
+
- methodology, limitations, and scan configuration
|
|
273
380
|
|
|
274
|
-
|
|
275
|
-
- it detects the languages and frameworks present in the workspace
|
|
276
|
-
- it chooses the matching scanner tools
|
|
277
|
-
- it only auto-runs commands when there is a reasonable local install path
|
|
278
|
-
- some tools, such as `SpotBugs`, may still need a manual install depending on your OS and package manager setup
|
|
381
|
+
### In The CLI
|
|
279
382
|
|
|
280
|
-
|
|
383
|
+
The CLI supports:
|
|
281
384
|
|
|
282
|
-
|
|
385
|
+
- plain terminal output
|
|
386
|
+
- `json`
|
|
387
|
+
- `html`
|
|
388
|
+
- `md`
|
|
389
|
+
- `docx`
|
|
390
|
+
|
|
391
|
+
Examples:
|
|
283
392
|
|
|
284
393
|
```bash
|
|
285
|
-
|
|
394
|
+
secure-review scan /path/to/repo --format json --out findings.json
|
|
395
|
+
secure-review scan /path/to/repo --format html --out review.html
|
|
396
|
+
secure-review scan /path/to/repo --format md --out review.md
|
|
397
|
+
secure-review scan /path/to/repo --format docx --out review.docx
|
|
286
398
|
```
|
|
287
399
|
|
|
288
|
-
|
|
400
|
+
## Preparing Optional Scanner Tools
|
|
401
|
+
|
|
402
|
+
If you want deeper language-specific coverage, you can inspect or bootstrap recommended local tools before running a scan.
|
|
403
|
+
|
|
404
|
+
From the repository source:
|
|
289
405
|
|
|
290
406
|
```bash
|
|
291
|
-
npm run
|
|
407
|
+
npm run bootstrap:tools
|
|
292
408
|
```
|
|
293
409
|
|
|
294
|
-
|
|
410
|
+
To execute supported install commands:
|
|
295
411
|
|
|
296
412
|
```bash
|
|
297
|
-
npm run
|
|
413
|
+
npm run bootstrap:tools:run
|
|
298
414
|
```
|
|
299
415
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
-
|
|
303
|
-
-
|
|
416
|
+
The bootstrap flow is best-effort:
|
|
417
|
+
|
|
418
|
+
- it detects the languages and frameworks present in the target workspace
|
|
419
|
+
- it recommends matching external tools
|
|
420
|
+
- it runs only supported install paths
|
|
421
|
+
- some tools may still require manual installation depending on the operating system and package manager
|
|
304
422
|
|
|
305
423
|
## Security And Privacy Notes
|
|
306
424
|
|
|
307
|
-
-
|
|
308
|
-
-
|
|
309
|
-
-
|
|
310
|
-
-
|
|
311
|
-
- The extension does not send findings to remote services.
|
|
312
|
-
- The rule engine is intentionally local and portable so it can be tested immediately in this workspace.
|
|
425
|
+
- Static scans operate on the repository or workspace you explicitly choose.
|
|
426
|
+
- Dynamic scans use OWASP ZAP through Docker and should only target developer-controlled local or test applications.
|
|
427
|
+
- Secure Review is designed to work locally and does not require a remote analysis service.
|
|
428
|
+
- External tool integrations run only when the corresponding tools are available on the machine.
|
|
313
429
|
|
|
314
430
|
## Troubleshooting
|
|
315
431
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
432
|
+
### No findings appear
|
|
433
|
+
|
|
434
|
+
- Lower the minimum severity threshold.
|
|
435
|
+
- Confirm excluded globs are not hiding the relevant files.
|
|
436
|
+
- Check whether built-in rules or external tool integrations are disabled.
|
|
437
|
+
|
|
438
|
+
### Dynamic scan fails
|
|
439
|
+
|
|
440
|
+
- Confirm Docker is installed and running.
|
|
441
|
+
- Confirm the target app is reachable from Docker.
|
|
442
|
+
- Start with `baseline` mode before trying `full`.
|
|
443
|
+
|
|
444
|
+
### A Bitbucket scan fails on a private repository
|
|
445
|
+
|
|
446
|
+
- Prefer an SSH URL such as `git@bitbucket.org:workspace/repo.git`
|
|
447
|
+
- or configure HTTPS access with the appropriate Bitbucket credentials
|
|
448
|
+
|
|
449
|
+
### The editor shows too many problem decorations
|
|
450
|
+
|
|
451
|
+
- Run `Secure Review: Clear Findings`
|
|
452
|
+
- or disable VS Code problem decorations if you only want to hide the visual markers
|
|
453
|
+
|
|
454
|
+
### A CLI scan seems stuck
|
|
455
|
+
|
|
456
|
+
- use the progress output to see which tool is running
|
|
457
|
+
- increase or lower `--tool-timeout-ms` depending on the workspace size and installed tools
|
|
458
|
+
- verify that optional tools such as `semgrep` or `bandit` are installed and working independently
|
|
459
|
+
|
|
460
|
+
## Developing From Source
|
|
461
|
+
|
|
462
|
+
If you want to test the extension from source:
|
|
463
|
+
|
|
464
|
+
1. Clone the repository.
|
|
465
|
+
2. Run `npm install`.
|
|
466
|
+
3. Press `Fn + F5` in VS Code, or launch `Run Secure Review Extension` from `Run and Debug`.
|
|
467
|
+
4. In the Extension Development Host, open a target project and run `Secure Review: Scan Workspace`.
|
|
468
|
+
|
|
469
|
+
This repository includes a deliberately vulnerable sample in `sample-workspace`, which is useful for smoke testing.
|
|
470
|
+
|
|
471
|
+
## For Maintainers
|
|
472
|
+
|
|
473
|
+
Common maintenance commands:
|
|
474
|
+
|
|
475
|
+
```bash
|
|
476
|
+
npm run verify
|
|
477
|
+
npm run package
|
|
478
|
+
npm run pack:cli:dry-run
|
|
479
|
+
npm run pack:cli
|
|
480
|
+
npm run publish:npm
|
|
481
|
+
npm run publish:marketplace
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Before releasing:
|
|
485
|
+
|
|
486
|
+
- verify package metadata in `package.json`
|
|
487
|
+
- confirm the publisher ID is correct
|
|
488
|
+
- validate the packaged VSIX locally
|
|
489
|
+
- validate the npm tarball locally if you are shipping the CLI
|
package/extension.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const vscode = require("vscode");
|
|
2
2
|
const { FindingsStore } = require("./src/store");
|
|
3
3
|
const { FindingsProvider } = require("./src/findings-provider");
|
|
4
|
-
const { scanWorkspace,
|
|
4
|
+
const { scanWorkspace, scanFileAtPath } = require("./src/scanners/static-scan");
|
|
5
5
|
const { runDockerZapScan } = require("./src/scanners/dynamic-scan");
|
|
6
6
|
const { detectWorkspace, buildInstallPlan, formatInstallPlan } = require("./src/scanners/bootstrap-tools");
|
|
7
7
|
const { applyDiagnostics } = require("./src/diagnostics");
|
|
@@ -11,6 +11,7 @@ const { severityOrder } = require("./src/constants");
|
|
|
11
11
|
|
|
12
12
|
let reportPanel;
|
|
13
13
|
let lastReportMetadata;
|
|
14
|
+
const saveScanTimers = new Map();
|
|
14
15
|
|
|
15
16
|
function activate(context) {
|
|
16
17
|
const store = new FindingsStore();
|
|
@@ -82,13 +83,7 @@ function activate(context) {
|
|
|
82
83
|
cancellable: false
|
|
83
84
|
},
|
|
84
85
|
async () => {
|
|
85
|
-
|
|
86
|
-
const otherStaticFindings = store.findings.filter(
|
|
87
|
-
(item) => item.source === "static" && item.filePath !== editor.document.uri.fsPath
|
|
88
|
-
);
|
|
89
|
-
const dynamicFindings = store.findings.filter((item) => item.source === "dynamic");
|
|
90
|
-
|
|
91
|
-
store.setFindings(sortFindings([...otherStaticFindings, ...currentFileFindings, ...dynamicFindings]));
|
|
86
|
+
await rescanFile(editor.document.uri.fsPath);
|
|
92
87
|
vscode.window.showInformationMessage(`Secure Review updated findings for ${editor.document.fileName}.`);
|
|
93
88
|
}
|
|
94
89
|
);
|
|
@@ -263,11 +258,97 @@ function activate(context) {
|
|
|
263
258
|
vscode.commands.registerCommand("secureReview.ignoreFinding", ignoreFinding)
|
|
264
259
|
);
|
|
265
260
|
|
|
261
|
+
async function rescanFile(filePath) {
|
|
262
|
+
const currentFileFindings = await scanFileAtPath(filePath, {
|
|
263
|
+
workspaceRoot: vscode.workspace.workspaceFolders?.[0]?.uri.fsPath,
|
|
264
|
+
excludeGlobs: configAccessor().get("excludeGlobs", []),
|
|
265
|
+
maxFiles: configAccessor().get("maxFiles", 400)
|
|
266
|
+
});
|
|
267
|
+
const otherStaticFindings = store.findings.filter(
|
|
268
|
+
(item) => item.source === "static" && item.filePath !== filePath
|
|
269
|
+
);
|
|
270
|
+
const dynamicFindings = store.findings.filter((item) => item.source === "dynamic");
|
|
271
|
+
store.setFindings(sortFindings([...otherStaticFindings, ...currentFileFindings, ...dynamicFindings]));
|
|
272
|
+
return currentFileFindings;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async function handleRunOnSave(document) {
|
|
276
|
+
if (!document || document.uri.scheme !== "file") {
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const workspaceFolder = vscode.workspace.getWorkspaceFolder(document.uri);
|
|
281
|
+
if (!workspaceFolder) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const filePath = document.uri.fsPath;
|
|
286
|
+
const existingFindings = store.findings.filter(
|
|
287
|
+
(item) => item.source === "static" && item.filePath === filePath
|
|
288
|
+
);
|
|
289
|
+
const previousIds = new Set(existingFindings.map((item) => item.id));
|
|
290
|
+
|
|
291
|
+
const updatedFindings = await rescanFile(filePath);
|
|
292
|
+
const nextIds = new Set(updatedFindings.map((item) => item.id));
|
|
293
|
+
const newCount = updatedFindings.filter((item) => !previousIds.has(item.id)).length;
|
|
294
|
+
const resolvedCount = existingFindings.filter((item) => !nextIds.has(item.id)).length;
|
|
295
|
+
|
|
296
|
+
if (!updatedFindings.length && !resolvedCount) {
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
const message = updatedFindings.length
|
|
301
|
+
? `Secure Review found ${updatedFindings.length} finding${updatedFindings.length === 1 ? "" : "s"} in ${document.fileName}${newCount || resolvedCount ? ` (${newCount} new, ${resolvedCount} resolved)` : ""}.`
|
|
302
|
+
: `Secure Review resolved all findings in ${document.fileName}.`;
|
|
303
|
+
|
|
304
|
+
const action = await vscode.window.showInformationMessage(
|
|
305
|
+
message,
|
|
306
|
+
"Open Findings",
|
|
307
|
+
"Open Report",
|
|
308
|
+
"Export DOCX"
|
|
309
|
+
);
|
|
310
|
+
|
|
311
|
+
if (action === "Open Findings") {
|
|
312
|
+
await vscode.commands.executeCommand("secureReview.findingsView.focus");
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (action === "Open Report") {
|
|
317
|
+
openReport();
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (action === "Export DOCX") {
|
|
322
|
+
await exportFindingsReport();
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
266
326
|
context.subscriptions.push(
|
|
267
|
-
vscode.workspace.onDidSaveTextDocument(async () => {
|
|
268
|
-
if (configAccessor().get("runOnSave", false)) {
|
|
269
|
-
|
|
327
|
+
vscode.workspace.onDidSaveTextDocument(async (document) => {
|
|
328
|
+
if (!configAccessor().get("runOnSave", false)) {
|
|
329
|
+
return;
|
|
270
330
|
}
|
|
331
|
+
|
|
332
|
+
const filePath = document?.uri?.fsPath;
|
|
333
|
+
if (!filePath) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const existingTimer = saveScanTimers.get(filePath);
|
|
338
|
+
if (existingTimer) {
|
|
339
|
+
clearTimeout(existingTimer);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const timer = setTimeout(async () => {
|
|
343
|
+
saveScanTimers.delete(filePath);
|
|
344
|
+
try {
|
|
345
|
+
await handleRunOnSave(document);
|
|
346
|
+
} catch (error) {
|
|
347
|
+
vscode.window.showErrorMessage(`Secure Review run-on-save scan failed: ${error.message}`);
|
|
348
|
+
}
|
|
349
|
+
}, 250);
|
|
350
|
+
|
|
351
|
+
saveScanTimers.set(filePath, timer);
|
|
271
352
|
})
|
|
272
353
|
);
|
|
273
354
|
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"name": "secure-review-extension",
|
|
3
3
|
"displayName": "Secure Review",
|
|
4
4
|
"description": "Run deep static and Docker-based dynamic secure code reviews directly inside VS Code.",
|
|
5
|
-
"version": "1.0.
|
|
6
|
-
"publisher": "
|
|
5
|
+
"version": "1.0.9",
|
|
6
|
+
"publisher": "Ankit-QI",
|
|
7
7
|
"icon": "media/shield.png",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"homepage": "https://bitbucket.org/macehand/secure-review-extension",
|
|
@@ -135,16 +135,31 @@ async function scanCurrentFile() {
|
|
|
135
135
|
return [];
|
|
136
136
|
}
|
|
137
137
|
|
|
138
|
-
|
|
138
|
+
return scanFileAtPath(editor.document.uri.fsPath);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async function scanFileAtPath(filePath, options = {}) {
|
|
142
|
+
const content = await readText(filePath);
|
|
139
143
|
if (content === null) {
|
|
140
144
|
return [];
|
|
141
145
|
}
|
|
142
146
|
|
|
143
|
-
const workspaceRoot =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
147
|
+
const workspaceRoot = options.workspaceRoot
|
|
148
|
+
|| vscode?.workspace?.workspaceFolders?.[0]?.uri.fsPath
|
|
149
|
+
|| path.dirname(filePath);
|
|
150
|
+
const workspaceProfile = await buildWorkspaceProfileForRoot(workspaceRoot, {
|
|
151
|
+
excludeGlobs: options.excludeGlobs || [],
|
|
152
|
+
maxFiles: options.maxFiles || 400
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
if (!shouldAnalyzeFile(filePath)) {
|
|
156
|
+
return [];
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return dedupeFindings(scanContent(filePath, content, workspaceRoot, {
|
|
160
|
+
languages: workspaceProfile.languages,
|
|
161
|
+
frameworks: workspaceProfile.frameworks,
|
|
162
|
+
isSecureReviewWorkspace: workspaceProfile.isSecureReviewWorkspace
|
|
148
163
|
}));
|
|
149
164
|
}
|
|
150
165
|
|
|
@@ -654,7 +669,8 @@ async function readText(filePath) {
|
|
|
654
669
|
module.exports = {
|
|
655
670
|
scanWorkspace,
|
|
656
671
|
scanWorkspaceAtPath,
|
|
657
|
-
scanCurrentFile
|
|
672
|
+
scanCurrentFile,
|
|
673
|
+
scanFileAtPath
|
|
658
674
|
};
|
|
659
675
|
|
|
660
676
|
function analyzeRepository(files, workspaceRoot) {
|