tc-scanner 0.1.0 → 0.1.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/README.md +243 -46
- package/bin/cli.js +199 -88
- package/package.json +1 -1
- package/.env +0 -1
- package/reports/scan-report.html +0 -61
- package/reports/scan-report.json +0 -21
- package/reports/scan-report.txt +0 -20
package/README.md
CHANGED
|
@@ -1,46 +1,177 @@
|
|
|
1
1
|
# tc-scanner
|
|
2
2
|
|
|
3
|
-
CI security scanner for Dockerfiles, dependencies, and secrets. Powered by Trivy.
|
|
3
|
+
A CI security scanner for Dockerfiles, container images, dependencies, and secrets. Powered by [Trivy](https://trivy.dev/).
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
7
|
-
**Docker is required.**
|
|
7
|
+
**Docker is required.** The scanner runs Trivy inside a container, so no additional installation is needed. All major CI platforms (Bitbucket Pipelines, GitHub Actions, GitLab CI, CircleCI) have Docker available by default.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
No installation required. Use directly with `npx`:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npx tc-scanner scan ./Dockerfile
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or install globally:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install -g tc-scanner
|
|
21
|
+
tc-scan scan ./Dockerfile
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
10
25
|
|
|
11
26
|
```bash
|
|
12
|
-
# Scan a Dockerfile
|
|
27
|
+
# Scan a Dockerfile for misconfigurations
|
|
13
28
|
npx tc-scanner scan ./Dockerfile
|
|
14
29
|
|
|
15
|
-
# Scan dependencies
|
|
16
|
-
npx tc-scanner deps
|
|
30
|
+
# Scan project dependencies for known vulnerabilities
|
|
31
|
+
npx tc-scanner deps .
|
|
17
32
|
|
|
18
|
-
# Scan for secrets
|
|
33
|
+
# Scan code for hardcoded secrets
|
|
19
34
|
npx tc-scanner secrets ./src
|
|
20
35
|
|
|
21
36
|
# Scan a container image
|
|
22
37
|
npx tc-scanner image nginx:latest
|
|
23
38
|
```
|
|
24
39
|
|
|
25
|
-
##
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
### `scan` - Dockerfile Security
|
|
43
|
+
|
|
44
|
+
Scans Dockerfiles for security misconfigurations.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npx tc-scanner scan ./Dockerfile
|
|
48
|
+
npx tc-scanner scan ./Dockerfile --severity HIGH
|
|
49
|
+
npx tc-scanner scan ./Dockerfile --output ./reports/dockerfile-scan
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**What it detects:**
|
|
53
|
+
- Running as root user
|
|
54
|
+
- Missing HEALTHCHECK instruction
|
|
55
|
+
- Using `latest` tag instead of pinned versions
|
|
56
|
+
- Insecure `ADD` instead of `COPY`
|
|
57
|
+
- Exposed sensitive ports
|
|
58
|
+
- Missing USER instruction
|
|
59
|
+
|
|
60
|
+
### `deps` - Dependency Vulnerabilities
|
|
61
|
+
|
|
62
|
+
Scans package lockfiles for known CVEs (similar to Snyk/npm audit).
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npx tc-scanner deps .
|
|
66
|
+
npx tc-scanner deps ./backend --severity CRITICAL
|
|
67
|
+
npx tc-scanner deps . --include-dev
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Supported lockfiles:**
|
|
71
|
+
- `package-lock.json` (npm)
|
|
72
|
+
- `yarn.lock` (Yarn)
|
|
73
|
+
- `pnpm-lock.yaml` (pnpm)
|
|
74
|
+
- `Gemfile.lock` (Ruby)
|
|
75
|
+
- `requirements.txt` / `Pipfile.lock` (Python)
|
|
76
|
+
- `go.sum` (Go)
|
|
77
|
+
- `composer.lock` (PHP)
|
|
78
|
+
|
|
79
|
+
### `secrets` - Secret Detection
|
|
80
|
+
|
|
81
|
+
Scans code for hardcoded secrets and sensitive data.
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npx tc-scanner secrets .
|
|
85
|
+
npx tc-scanner secrets ./src --output ./reports/secrets
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**What it detects:**
|
|
89
|
+
- AWS access keys and secrets
|
|
90
|
+
- API tokens (Stripe, GitHub, Slack, etc.)
|
|
91
|
+
- Private keys (RSA, SSH, PGP)
|
|
92
|
+
- Database connection strings
|
|
93
|
+
- Hardcoded passwords
|
|
94
|
+
- JWT secrets
|
|
95
|
+
|
|
96
|
+
### `image` - Container Image Scanning
|
|
97
|
+
|
|
98
|
+
Scans container images for OS and application vulnerabilities.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npx tc-scanner image nginx:latest
|
|
102
|
+
npx tc-scanner image myapp:v1.2.3 --severity HIGH,CRITICAL
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**What it detects:**
|
|
106
|
+
- OS package vulnerabilities (Alpine, Debian, Ubuntu, RHEL, etc.)
|
|
107
|
+
- Application dependencies inside the image
|
|
108
|
+
- Embedded secrets and misconfigurations
|
|
109
|
+
|
|
110
|
+
## Options
|
|
111
|
+
|
|
112
|
+
| Option | Alias | Description | Default |
|
|
113
|
+
|--------|-------|-------------|---------|
|
|
114
|
+
| `--severity` | `-s` | Minimum severity level: `LOW`, `MEDIUM`, `HIGH`, `CRITICAL` | `HIGH` |
|
|
115
|
+
| `--output` | `-o` | Save reports to file (creates `.json`, `.txt`, `.html`) | - |
|
|
116
|
+
| `--webhook` | `-w` | Send results to a webhook URL | - |
|
|
117
|
+
| `--exit-code` | - | Exit code when issues are found | `1` |
|
|
118
|
+
| `--include-dev` | - | Include dev dependencies (deps command only) | `false` |
|
|
119
|
+
|
|
120
|
+
## Reports
|
|
121
|
+
|
|
122
|
+
Generate reports in multiple formats:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
npx tc-scanner scan ./Dockerfile --output ./reports/scan-report
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
This creates:
|
|
129
|
+
- `scan-report.json` - Structured data for APIs and integrations
|
|
130
|
+
- `scan-report.txt` - Plain text for email notifications
|
|
131
|
+
- `scan-report.html` - Styled HTML report for attachments
|
|
132
|
+
|
|
133
|
+
## Webhooks
|
|
134
|
+
|
|
135
|
+
Send scan results to any webhook endpoint:
|
|
26
136
|
|
|
27
137
|
```bash
|
|
28
|
-
|
|
29
|
-
npx tc-scanner
|
|
138
|
+
# Generic webhook
|
|
139
|
+
npx tc-scanner scan ./Dockerfile --webhook https://your-api.com/security-alerts
|
|
140
|
+
|
|
141
|
+
# Slack incoming webhook
|
|
142
|
+
npx tc-scanner scan ./Dockerfile --webhook https://hooks.slack.com/services/xxx/yyy/zzz
|
|
30
143
|
```
|
|
31
144
|
|
|
32
|
-
Webhook payload
|
|
145
|
+
**Webhook payload:**
|
|
146
|
+
|
|
33
147
|
```json
|
|
34
148
|
{
|
|
35
149
|
"scanner": "tc-scanner",
|
|
36
150
|
"scanType": "dockerfile",
|
|
37
151
|
"timestamp": "2024-01-15T10:30:00.000Z",
|
|
38
|
-
"
|
|
39
|
-
"
|
|
152
|
+
"target": "./Dockerfile",
|
|
153
|
+
"summary": {
|
|
154
|
+
"total": 3,
|
|
155
|
+
"critical": 0,
|
|
156
|
+
"high": 1,
|
|
157
|
+
"medium": 2,
|
|
158
|
+
"low": 0
|
|
159
|
+
},
|
|
160
|
+
"issues": [
|
|
161
|
+
{
|
|
162
|
+
"id": "DS-0002",
|
|
163
|
+
"severity": "HIGH",
|
|
164
|
+
"title": "Last USER command should not be 'root'",
|
|
165
|
+
"description": "Running containers with 'root' user can lead to container escape.",
|
|
166
|
+
"url": "https://avd.aquasec.com/misconfig/ds-0002"
|
|
167
|
+
}
|
|
168
|
+
]
|
|
40
169
|
}
|
|
41
170
|
```
|
|
42
171
|
|
|
43
|
-
##
|
|
172
|
+
## CI/CD Integration
|
|
173
|
+
|
|
174
|
+
### Bitbucket Pipelines
|
|
44
175
|
|
|
45
176
|
```yaml
|
|
46
177
|
image: node:20
|
|
@@ -59,72 +190,138 @@ pipelines:
|
|
|
59
190
|
script:
|
|
60
191
|
- npx tc-scanner scan ./Dockerfile --severity HIGH
|
|
61
192
|
- npx tc-scanner deps . --severity HIGH
|
|
193
|
+
|
|
194
|
+
pull-requests:
|
|
195
|
+
'**':
|
|
196
|
+
- step:
|
|
197
|
+
name: PR Security Check
|
|
198
|
+
services:
|
|
199
|
+
- docker
|
|
200
|
+
script:
|
|
201
|
+
- npx tc-scanner scan ./Dockerfile --severity CRITICAL
|
|
202
|
+
- npx tc-scanner secrets ./src
|
|
62
203
|
```
|
|
63
204
|
|
|
64
|
-
|
|
205
|
+
### GitHub Actions
|
|
65
206
|
|
|
66
207
|
```yaml
|
|
208
|
+
name: Security Scan
|
|
209
|
+
|
|
210
|
+
on: [push, pull_request]
|
|
211
|
+
|
|
67
212
|
jobs:
|
|
68
213
|
security:
|
|
69
214
|
runs-on: ubuntu-latest
|
|
70
215
|
steps:
|
|
71
216
|
- uses: actions/checkout@v4
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
217
|
+
|
|
218
|
+
- name: Scan Dockerfile
|
|
219
|
+
run: npx tc-scanner scan ./Dockerfile --severity HIGH
|
|
220
|
+
|
|
221
|
+
- name: Scan Dependencies
|
|
222
|
+
run: npx tc-scanner deps . --severity HIGH
|
|
223
|
+
|
|
224
|
+
- name: Scan for Secrets
|
|
225
|
+
run: npx tc-scanner secrets ./src
|
|
76
226
|
```
|
|
77
227
|
|
|
78
|
-
|
|
228
|
+
### GitLab CI
|
|
79
229
|
|
|
80
230
|
```yaml
|
|
81
231
|
security-scan:
|
|
82
232
|
image: node:20
|
|
83
233
|
services:
|
|
84
234
|
- docker:dind
|
|
235
|
+
variables:
|
|
236
|
+
DOCKER_HOST: tcp://docker:2375
|
|
85
237
|
script:
|
|
86
238
|
- npx tc-scanner scan ./Dockerfile --severity HIGH
|
|
87
239
|
- npx tc-scanner deps . --severity HIGH
|
|
240
|
+
- npx tc-scanner secrets ./src
|
|
241
|
+
artifacts:
|
|
242
|
+
paths:
|
|
243
|
+
- reports/
|
|
244
|
+
when: always
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### CircleCI
|
|
248
|
+
|
|
249
|
+
```yaml
|
|
250
|
+
version: 2.1
|
|
251
|
+
|
|
252
|
+
jobs:
|
|
253
|
+
security-scan:
|
|
254
|
+
docker:
|
|
255
|
+
- image: cimg/node:20.0
|
|
256
|
+
steps:
|
|
257
|
+
- checkout
|
|
258
|
+
- setup_remote_docker
|
|
259
|
+
- run:
|
|
260
|
+
name: Security Scan
|
|
261
|
+
command: |
|
|
262
|
+
npx tc-scanner scan ./Dockerfile --severity HIGH
|
|
263
|
+
npx tc-scanner deps . --severity HIGH
|
|
264
|
+
|
|
265
|
+
workflows:
|
|
266
|
+
main:
|
|
267
|
+
jobs:
|
|
268
|
+
- security-scan
|
|
88
269
|
```
|
|
89
270
|
|
|
90
|
-
##
|
|
271
|
+
## Exit Codes
|
|
272
|
+
|
|
273
|
+
| Code | Meaning |
|
|
274
|
+
|------|---------|
|
|
275
|
+
| `0` | No issues found (or below severity threshold) |
|
|
276
|
+
| `1` | Issues found at or above severity threshold |
|
|
91
277
|
|
|
278
|
+
Use `--exit-code 0` to always pass (useful for non-blocking scans):
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
npx tc-scanner scan ./Dockerfile --exit-code 0
|
|
92
282
|
```
|
|
93
|
-
Usage: tc-scan [command] [options]
|
|
94
283
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
284
|
+
## Severity Levels
|
|
285
|
+
|
|
286
|
+
| Level | Description |
|
|
287
|
+
|-------|-------------|
|
|
288
|
+
| `CRITICAL` | Severe vulnerabilities requiring immediate action |
|
|
289
|
+
| `HIGH` | Important security issues that should be fixed soon |
|
|
290
|
+
| `MEDIUM` | Moderate issues to address in regular maintenance |
|
|
291
|
+
| `LOW` | Minor issues or best practice recommendations |
|
|
100
292
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
293
|
+
## Examples
|
|
294
|
+
|
|
295
|
+
**Fail CI only on critical issues:**
|
|
296
|
+
```bash
|
|
297
|
+
npx tc-scanner scan ./Dockerfile --severity CRITICAL
|
|
106
298
|
```
|
|
107
299
|
|
|
108
|
-
|
|
300
|
+
**Full security audit with reports:**
|
|
301
|
+
```bash
|
|
302
|
+
npx tc-scanner scan ./Dockerfile --output ./reports/dockerfile --severity LOW
|
|
303
|
+
npx tc-scanner deps . --output ./reports/deps --severity LOW --include-dev
|
|
304
|
+
npx tc-scanner secrets ./src --output ./reports/secrets
|
|
305
|
+
```
|
|
109
306
|
|
|
307
|
+
**Send alerts to Slack on failures:**
|
|
110
308
|
```bash
|
|
111
|
-
|
|
112
|
-
npx tc-scanner scan ./Dockerfile --output ./reports/scan-report
|
|
309
|
+
npx tc-scanner scan ./Dockerfile --webhook $SLACK_WEBHOOK_URL
|
|
113
310
|
```
|
|
114
311
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
-
|
|
312
|
+
## Troubleshooting
|
|
313
|
+
|
|
314
|
+
**"Docker is required"**
|
|
315
|
+
- Ensure Docker is installed and running
|
|
316
|
+
- In CI, enable the Docker service (see examples above)
|
|
119
317
|
|
|
120
|
-
|
|
318
|
+
**"No lockfile found" (deps command)**
|
|
319
|
+
- The scanner needs `package-lock.json`, `yarn.lock`, or similar
|
|
320
|
+
- Run `npm install` or your package manager to generate a lockfile
|
|
121
321
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
| `deps` | Known CVEs in npm/yarn/pnpm packages |
|
|
126
|
-
| `secrets` | API keys, tokens, passwords, private keys in code |
|
|
127
|
-
| `image` | OS package vulnerabilities + app dependencies in containers |
|
|
322
|
+
**Slow first run**
|
|
323
|
+
- First run downloads the Trivy Docker image (~50MB) and vulnerability database (~80MB)
|
|
324
|
+
- Subsequent runs are faster due to caching
|
|
128
325
|
|
|
129
326
|
## License
|
|
130
327
|
|
package/bin/cli.js
CHANGED
|
@@ -6,128 +6,239 @@ import { scanDockerfile, scanImage, scanFilesystem, sendWebhook } from '../src/s
|
|
|
6
6
|
const main = defineCommand({
|
|
7
7
|
meta: {
|
|
8
8
|
name: 'tc-scan',
|
|
9
|
-
version: '0.1.
|
|
10
|
-
description: 'CI security scanner for Dockerfiles, dependencies, and secrets.
|
|
9
|
+
version: '0.1.1',
|
|
10
|
+
description: 'CI security scanner for Dockerfiles, images, dependencies, and secrets.\n\nRequires Docker. Powered by Trivy.',
|
|
11
11
|
},
|
|
12
12
|
subCommands: {
|
|
13
13
|
scan: defineCommand({
|
|
14
|
-
meta: {
|
|
14
|
+
meta: {
|
|
15
|
+
name: 'scan',
|
|
16
|
+
description: 'Scan a Dockerfile for security misconfigurations.\n\nDetects: running as root, missing HEALTHCHECK, unpinned versions, insecure ADD, and more.',
|
|
17
|
+
},
|
|
15
18
|
args: {
|
|
16
|
-
path: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
path: {
|
|
20
|
+
type: 'positional',
|
|
21
|
+
description: 'Path to Dockerfile',
|
|
22
|
+
default: './Dockerfile',
|
|
23
|
+
},
|
|
24
|
+
severity: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
alias: 's',
|
|
27
|
+
description: 'Minimum severity to report (LOW, MEDIUM, HIGH, CRITICAL)',
|
|
28
|
+
default: 'HIGH',
|
|
29
|
+
},
|
|
30
|
+
output: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
alias: 'o',
|
|
33
|
+
description: 'Save report to file (creates .json, .txt, .html)',
|
|
34
|
+
},
|
|
35
|
+
webhook: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
alias: 'w',
|
|
38
|
+
description: 'Send results to webhook URL (Slack, custom endpoint)',
|
|
39
|
+
},
|
|
40
|
+
'exit-code': {
|
|
41
|
+
type: 'string',
|
|
42
|
+
description: 'Exit code when issues found (use 0 to never fail)',
|
|
43
|
+
default: '1',
|
|
44
|
+
},
|
|
21
45
|
},
|
|
22
46
|
async run({ args }) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
printHeader('Dockerfile Scanner');
|
|
48
|
+
|
|
49
|
+
try {
|
|
50
|
+
const result = await scanDockerfile(args.path, {
|
|
51
|
+
severity: args.severity,
|
|
52
|
+
output: args.output,
|
|
53
|
+
exitCode: args['exit-code'],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (args.webhook && result.json) {
|
|
57
|
+
await sendWebhook(args.webhook, result.json, 'dockerfile');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
process.exit(result.exitCode);
|
|
61
|
+
} catch (error) {
|
|
62
|
+
console.error(`\nError: ${error.message}`);
|
|
63
|
+
process.exit(1);
|
|
36
64
|
}
|
|
37
|
-
|
|
38
|
-
process.exit(result.exitCode);
|
|
39
65
|
},
|
|
40
66
|
}),
|
|
41
67
|
|
|
42
68
|
image: defineCommand({
|
|
43
|
-
meta: {
|
|
69
|
+
meta: {
|
|
70
|
+
name: 'image',
|
|
71
|
+
description: 'Scan a container image for vulnerabilities.\n\nDetects: OS package CVEs, application dependency vulnerabilities, embedded secrets.',
|
|
72
|
+
},
|
|
44
73
|
args: {
|
|
45
|
-
image: {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
74
|
+
image: {
|
|
75
|
+
type: 'positional',
|
|
76
|
+
description: 'Image name (e.g., nginx:latest, myapp:v1.2.3)',
|
|
77
|
+
required: true,
|
|
78
|
+
},
|
|
79
|
+
severity: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
alias: 's',
|
|
82
|
+
description: 'Minimum severity to report (LOW, MEDIUM, HIGH, CRITICAL)',
|
|
83
|
+
default: 'HIGH',
|
|
84
|
+
},
|
|
85
|
+
output: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
alias: 'o',
|
|
88
|
+
description: 'Save report to file (creates .json, .txt, .html)',
|
|
89
|
+
},
|
|
90
|
+
webhook: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
alias: 'w',
|
|
93
|
+
description: 'Send results to webhook URL',
|
|
94
|
+
},
|
|
95
|
+
'exit-code': {
|
|
96
|
+
type: 'string',
|
|
97
|
+
description: 'Exit code when issues found',
|
|
98
|
+
default: '1',
|
|
99
|
+
},
|
|
50
100
|
},
|
|
51
101
|
async run({ args }) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
102
|
+
printHeader('Image Scanner');
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
const result = await scanImage(args.image, {
|
|
106
|
+
severity: args.severity,
|
|
107
|
+
output: args.output,
|
|
108
|
+
exitCode: args['exit-code'],
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (args.webhook && result.json) {
|
|
112
|
+
await sendWebhook(args.webhook, result.json, 'image');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
process.exit(result.exitCode);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error(`\nError: ${error.message}`);
|
|
118
|
+
process.exit(1);
|
|
65
119
|
}
|
|
66
|
-
|
|
67
|
-
process.exit(result.exitCode);
|
|
68
120
|
},
|
|
69
121
|
}),
|
|
70
122
|
|
|
71
123
|
deps: defineCommand({
|
|
72
|
-
meta: {
|
|
124
|
+
meta: {
|
|
125
|
+
name: 'deps',
|
|
126
|
+
description: 'Scan project dependencies for known vulnerabilities (CVEs).\n\nSupports: npm, yarn, pnpm, pip, bundler, composer, go modules.',
|
|
127
|
+
},
|
|
73
128
|
args: {
|
|
74
|
-
path: {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
129
|
+
path: {
|
|
130
|
+
type: 'positional',
|
|
131
|
+
description: 'Path to project directory containing lockfile',
|
|
132
|
+
default: '.',
|
|
133
|
+
},
|
|
134
|
+
severity: {
|
|
135
|
+
type: 'string',
|
|
136
|
+
alias: 's',
|
|
137
|
+
description: 'Minimum severity to report (LOW, MEDIUM, HIGH, CRITICAL)',
|
|
138
|
+
default: 'HIGH',
|
|
139
|
+
},
|
|
140
|
+
output: {
|
|
141
|
+
type: 'string',
|
|
142
|
+
alias: 'o',
|
|
143
|
+
description: 'Save report to file (creates .json, .txt, .html)',
|
|
144
|
+
},
|
|
145
|
+
webhook: {
|
|
146
|
+
type: 'string',
|
|
147
|
+
alias: 'w',
|
|
148
|
+
description: 'Send results to webhook URL',
|
|
149
|
+
},
|
|
150
|
+
'exit-code': {
|
|
151
|
+
type: 'string',
|
|
152
|
+
description: 'Exit code when issues found',
|
|
153
|
+
default: '1',
|
|
154
|
+
},
|
|
155
|
+
'include-dev': {
|
|
156
|
+
type: 'boolean',
|
|
157
|
+
description: 'Include development dependencies in scan',
|
|
158
|
+
default: false,
|
|
159
|
+
},
|
|
80
160
|
},
|
|
81
161
|
async run({ args }) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
162
|
+
printHeader('Dependency Scanner');
|
|
163
|
+
|
|
164
|
+
try {
|
|
165
|
+
const result = await scanFilesystem(args.path, {
|
|
166
|
+
severity: args.severity,
|
|
167
|
+
output: args.output,
|
|
168
|
+
exitCode: args['exit-code'],
|
|
169
|
+
includeDev: args['include-dev'],
|
|
170
|
+
scanType: 'vuln',
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
if (args.webhook && result.json) {
|
|
174
|
+
await sendWebhook(args.webhook, result.json, 'dependencies');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
process.exit(result.exitCode);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error(`\nError: ${error.message}`);
|
|
180
|
+
process.exit(1);
|
|
97
181
|
}
|
|
98
|
-
|
|
99
|
-
process.exit(result.exitCode);
|
|
100
182
|
},
|
|
101
183
|
}),
|
|
102
184
|
|
|
103
185
|
secrets: defineCommand({
|
|
104
|
-
meta: {
|
|
186
|
+
meta: {
|
|
187
|
+
name: 'secrets',
|
|
188
|
+
description: 'Scan code for hardcoded secrets and sensitive data.\n\nDetects: API keys, tokens, passwords, private keys, connection strings.',
|
|
189
|
+
},
|
|
105
190
|
args: {
|
|
106
|
-
path: {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
191
|
+
path: {
|
|
192
|
+
type: 'positional',
|
|
193
|
+
description: 'Path to directory to scan',
|
|
194
|
+
default: '.',
|
|
195
|
+
},
|
|
196
|
+
output: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
alias: 'o',
|
|
199
|
+
description: 'Save report to file (creates .json, .txt, .html)',
|
|
200
|
+
},
|
|
201
|
+
webhook: {
|
|
202
|
+
type: 'string',
|
|
203
|
+
alias: 'w',
|
|
204
|
+
description: 'Send results to webhook URL',
|
|
205
|
+
},
|
|
206
|
+
'exit-code': {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Exit code when secrets found',
|
|
209
|
+
default: '1',
|
|
210
|
+
},
|
|
110
211
|
},
|
|
111
212
|
async run({ args }) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
213
|
+
printHeader('Secrets Scanner');
|
|
214
|
+
|
|
215
|
+
try {
|
|
216
|
+
const result = await scanFilesystem(args.path, {
|
|
217
|
+
output: args.output,
|
|
218
|
+
exitCode: args['exit-code'],
|
|
219
|
+
scanType: 'secret',
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (args.webhook && result.json) {
|
|
223
|
+
await sendWebhook(args.webhook, result.json, 'secrets');
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
process.exit(result.exitCode);
|
|
227
|
+
} catch (error) {
|
|
228
|
+
console.error(`\nError: ${error.message}`);
|
|
229
|
+
process.exit(1);
|
|
125
230
|
}
|
|
126
|
-
|
|
127
|
-
process.exit(result.exitCode);
|
|
128
231
|
},
|
|
129
232
|
}),
|
|
130
233
|
},
|
|
131
234
|
});
|
|
132
235
|
|
|
236
|
+
function printHeader(title) {
|
|
237
|
+
console.log();
|
|
238
|
+
console.log('━'.repeat(50));
|
|
239
|
+
console.log(` TC-Secure ${title}`);
|
|
240
|
+
console.log('━'.repeat(50));
|
|
241
|
+
console.log();
|
|
242
|
+
}
|
|
243
|
+
|
|
133
244
|
runMain(main);
|
package/package.json
CHANGED
package/.env
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
NPM_TOKEN=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
|
package/reports/scan-report.html
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
<!DOCTYPE html>
|
|
3
|
-
<html>
|
|
4
|
-
<head>
|
|
5
|
-
<style>
|
|
6
|
-
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
|
|
7
|
-
.header { background: #1e293b; color: white; padding: 20px; border-radius: 8px 8px 0 0; }
|
|
8
|
-
.content { border: 1px solid #e2e8f0; border-top: none; padding: 20px; border-radius: 0 0 8px 8px; }
|
|
9
|
-
.summary-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin: 20px 0; }
|
|
10
|
-
.stat { text-align: center; padding: 15px; border-radius: 8px; }
|
|
11
|
-
.stat-critical { background: #fef2f2; border: 1px solid #fecaca; }
|
|
12
|
-
.stat-high { background: #fff7ed; border: 1px solid #fed7aa; }
|
|
13
|
-
.stat-medium { background: #fefce8; border: 1px solid #fef08a; }
|
|
14
|
-
.stat-low { background: #eff6ff; border: 1px solid #bfdbfe; }
|
|
15
|
-
.stat-value { font-size: 24px; font-weight: bold; }
|
|
16
|
-
.issue { border-left: 4px solid; padding: 12px; margin: 10px 0; background: #f8fafc; }
|
|
17
|
-
.issue-critical { border-color: #dc2626; }
|
|
18
|
-
.issue-high { border-color: #ea580c; }
|
|
19
|
-
.issue-medium { border-color: #ca8a04; }
|
|
20
|
-
.issue-low { border-color: #2563eb; }
|
|
21
|
-
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 12px; font-weight: 600; color: white; }
|
|
22
|
-
a { color: #2563eb; }
|
|
23
|
-
</style>
|
|
24
|
-
</head>
|
|
25
|
-
<body>
|
|
26
|
-
<div class="header">
|
|
27
|
-
<h1 style="margin: 0;">TC-Secure Scan Report</h1>
|
|
28
|
-
<p style="margin: 5px 0 0 0; opacity: 0.8;">Target: /Users/themba/Teamcoda/teamcoda/tc-secure/pentest/Dockerfile</p>
|
|
29
|
-
<p style="margin: 5px 0 0 0; opacity: 0.8;">Scan Time: 2026-02-02T00:06:36.733Z</p>
|
|
30
|
-
</div>
|
|
31
|
-
<div class="content">
|
|
32
|
-
<h2>Summary</h2>
|
|
33
|
-
<div class="summary-grid">
|
|
34
|
-
<div class="stat stat-critical">
|
|
35
|
-
<div class="stat-value" style="color: #dc2626">0</div>
|
|
36
|
-
<div>Critical</div>
|
|
37
|
-
</div>
|
|
38
|
-
<div class="stat stat-high">
|
|
39
|
-
<div class="stat-value" style="color: #ea580c">0</div>
|
|
40
|
-
<div>High</div>
|
|
41
|
-
</div>
|
|
42
|
-
<div class="stat stat-medium">
|
|
43
|
-
<div class="stat-value" style="color: #ca8a04">0</div>
|
|
44
|
-
<div>Medium</div>
|
|
45
|
-
</div>
|
|
46
|
-
<div class="stat stat-low">
|
|
47
|
-
<div class="stat-value" style="color: #2563eb">1</div>
|
|
48
|
-
<div>Low</div>
|
|
49
|
-
</div>
|
|
50
|
-
</div>
|
|
51
|
-
<h2>Issues (1)</h2>
|
|
52
|
-
<div class="issue issue-low">
|
|
53
|
-
<span class="badge" style="background: #2563eb">LOW</span>
|
|
54
|
-
<strong>DS-0026</strong>
|
|
55
|
-
<p style="margin: 8px 0;">No HEALTHCHECK defined</p>
|
|
56
|
-
|
|
57
|
-
<a href="https://avd.aquasec.com/misconfig/ds-0026" style="font-size: 14px;">View details →</a>
|
|
58
|
-
</div>
|
|
59
|
-
</div>
|
|
60
|
-
</body>
|
|
61
|
-
</html>
|
package/reports/scan-report.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"target": "/Users/themba/Teamcoda/teamcoda/tc-secure/pentest/Dockerfile",
|
|
3
|
-
"scanTime": "2026-02-02T00:06:36.733Z",
|
|
4
|
-
"totalIssues": 1,
|
|
5
|
-
"bySeverity": {
|
|
6
|
-
"CRITICAL": 0,
|
|
7
|
-
"HIGH": 0,
|
|
8
|
-
"MEDIUM": 0,
|
|
9
|
-
"LOW": 1
|
|
10
|
-
},
|
|
11
|
-
"issues": [
|
|
12
|
-
{
|
|
13
|
-
"id": "DS-0026",
|
|
14
|
-
"severity": "LOW",
|
|
15
|
-
"title": "No HEALTHCHECK defined",
|
|
16
|
-
"description": "You should add HEALTHCHECK instruction in your docker container images to perform the health check on running containers.",
|
|
17
|
-
"resolution": "Add HEALTHCHECK instruction in Dockerfile",
|
|
18
|
-
"url": "https://avd.aquasec.com/misconfig/ds-0026"
|
|
19
|
-
}
|
|
20
|
-
]
|
|
21
|
-
}
|
package/reports/scan-report.txt
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
TC-SECURE SCAN REPORT
|
|
3
|
-
=====================
|
|
4
|
-
Target: /Users/themba/Teamcoda/teamcoda/tc-secure/pentest/Dockerfile
|
|
5
|
-
Scan Time: 2026-02-02T00:06:36.733Z
|
|
6
|
-
|
|
7
|
-
SUMMARY
|
|
8
|
-
-------
|
|
9
|
-
Total Issues: 1
|
|
10
|
-
CRITICAL: 0
|
|
11
|
-
HIGH: 0
|
|
12
|
-
MEDIUM: 0
|
|
13
|
-
LOW: 1
|
|
14
|
-
|
|
15
|
-
DETAILS
|
|
16
|
-
-------
|
|
17
|
-
|
|
18
|
-
[LOW] DS-0026
|
|
19
|
-
No HEALTHCHECK defined
|
|
20
|
-
More info: https://avd.aquasec.com/misconfig/ds-0026
|