ship-safe 6.1.1 → 6.2.0

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.
Files changed (47) hide show
  1. package/README.md +735 -641
  2. package/cli/agents/api-fuzzer.js +345 -345
  3. package/cli/agents/auth-bypass-agent.js +348 -348
  4. package/cli/agents/base-agent.js +272 -272
  5. package/cli/agents/cicd-scanner.js +236 -201
  6. package/cli/agents/config-auditor.js +521 -521
  7. package/cli/agents/deep-analyzer.js +6 -2
  8. package/cli/agents/git-history-scanner.js +170 -170
  9. package/cli/agents/html-reporter.js +568 -568
  10. package/cli/agents/index.js +84 -84
  11. package/cli/agents/injection-tester.js +500 -500
  12. package/cli/agents/llm-redteam.js +251 -251
  13. package/cli/agents/mobile-scanner.js +231 -231
  14. package/cli/agents/orchestrator.js +322 -322
  15. package/cli/agents/pii-compliance-agent.js +301 -301
  16. package/cli/agents/scoring-engine.js +248 -248
  17. package/cli/agents/supabase-rls-agent.js +154 -154
  18. package/cli/agents/supply-chain-agent.js +650 -507
  19. package/cli/bin/ship-safe.js +452 -426
  20. package/cli/commands/agent.js +608 -608
  21. package/cli/commands/audit.js +986 -980
  22. package/cli/commands/baseline.js +193 -193
  23. package/cli/commands/ci.js +342 -342
  24. package/cli/commands/deps.js +516 -516
  25. package/cli/commands/doctor.js +159 -159
  26. package/cli/commands/fix.js +218 -218
  27. package/cli/commands/hooks.js +268 -0
  28. package/cli/commands/init.js +407 -407
  29. package/cli/commands/mcp.js +304 -304
  30. package/cli/commands/red-team.js +7 -1
  31. package/cli/commands/remediate.js +798 -798
  32. package/cli/commands/rotate.js +571 -571
  33. package/cli/commands/scan.js +569 -569
  34. package/cli/commands/score.js +449 -449
  35. package/cli/commands/watch.js +281 -281
  36. package/cli/hooks/patterns.js +313 -0
  37. package/cli/hooks/post-tool-use.js +140 -0
  38. package/cli/hooks/pre-tool-use.js +186 -0
  39. package/cli/index.js +73 -69
  40. package/cli/providers/llm-provider.js +397 -287
  41. package/cli/utils/autofix-rules.js +74 -74
  42. package/cli/utils/cache-manager.js +311 -311
  43. package/cli/utils/output.js +230 -230
  44. package/cli/utils/patterns.js +1121 -1121
  45. package/cli/utils/pdf-generator.js +94 -94
  46. package/package.json +69 -69
  47. package/configs/supabase/rls-templates.sql +0 -242
@@ -1,201 +1,236 @@
1
- /**
2
- * CICDScanner Agent
3
- * ==================
4
- *
5
- * Detect security issues in CI/CD pipeline configurations.
6
- * Based on OWASP Top 10 CI/CD Security Risks.
7
- *
8
- * Scans: GitHub Actions, GitLab CI, Jenkins, CircleCI,
9
- * Bitbucket Pipelines, Azure DevOps.
10
- */
11
-
12
- import path from 'path';
13
- import { BaseAgent } from './base-agent.js';
14
-
15
- const PATTERNS = [
16
- // ── CICD-SEC-4: Poisoned Pipeline Execution ────────────────────────────────
17
- {
18
- rule: 'CICD_PR_TARGET_CHECKOUT',
19
- title: 'CI/CD: pull_request_target with PR Checkout',
20
- regex: /\bpull_request_target\b/g,
21
- severity: 'critical',
22
- cwe: 'CWE-94',
23
- owasp: 'CICD-SEC-4',
24
- confidence: 'medium',
25
- description: 'pull_request_target trigger detected. Runs with base branch privileges and can be exploited if combined with PR checkout.',
26
- fix: 'Use pull_request trigger instead, or never checkout PR branch in pull_request_target',
27
- },
28
- {
29
- rule: 'CICD_WORKFLOW_RUN',
30
- title: 'CI/CD: Unrestricted workflow_run Trigger',
31
- regex: /workflow_run[\s\S]{0,200}types:\s*\[?\s*completed/g,
32
- severity: 'high',
33
- cwe: 'CWE-94',
34
- owasp: 'CICD-SEC-4',
35
- confidence: 'medium',
36
- description: 'workflow_run trigger can execute with elevated permissions from a completed workflow.',
37
- fix: 'Add conditions to check the source workflow and event',
38
- },
39
-
40
- // ── CICD-SEC-2: Inadequate Identity and Access Management ──────────────────
41
- {
42
- rule: 'CICD_EXCESSIVE_PERMISSIONS',
43
- title: 'CI/CD: Write-All Permissions',
44
- regex: /permissions\s*:\s*write-all/g,
45
- severity: 'high',
46
- cwe: 'CWE-250',
47
- owasp: 'CICD-SEC-2',
48
- description: 'Workflow has write-all permissions. Apply least privilege.',
49
- fix: 'Set granular permissions: permissions: { contents: read, pull-requests: write }',
50
- },
51
- {
52
- rule: 'CICD_PERMISSIVE_TOKEN',
53
- title: 'CI/CD: Permissive GITHUB_TOKEN',
54
- regex: /permissions\s*:\s*\n\s*contents\s*:\s*write/g,
55
- severity: 'medium',
56
- cwe: 'CWE-250',
57
- owasp: 'CICD-SEC-2',
58
- confidence: 'low',
59
- description: 'GITHUB_TOKEN has contents: write. Consider if read is sufficient.',
60
- fix: 'Use contents: read unless the workflow needs to push commits',
61
- },
62
-
63
- // ── CICD-SEC-6: Insufficient Credential Hygiene ────────────────────────────
64
- {
65
- rule: 'CICD_SECRET_IN_LOG',
66
- title: 'CI/CD: Secret Potentially Logged',
67
- regex: /echo\s+\$\{\{\s*secrets\./g,
68
- severity: 'critical',
69
- cwe: 'CWE-532',
70
- owasp: 'CICD-SEC-6',
71
- description: 'Secret printed via echo may appear in CI logs. GitHub masks known secrets but not all.',
72
- fix: 'Never echo secrets. Use them only in environment variables or file writes.',
73
- },
74
- {
75
- rule: 'CICD_HARDCODED_SECRET',
76
- title: 'CI/CD: Hardcoded Secret in Workflow',
77
- regex: /(?:api[_-]?key|token|password|secret)\s*[:=]\s*["'][a-zA-Z0-9_\-]{20,}["']/gi,
78
- severity: 'critical',
79
- cwe: 'CWE-798',
80
- owasp: 'CICD-SEC-6',
81
- description: 'Hardcoded secret in CI/CD configuration. Use repository/organization secrets.',
82
- fix: 'Move to GitHub/GitLab secrets: ${{ secrets.MY_SECRET }}',
83
- },
84
-
85
- // ── CICD-SEC-8: Ungoverned Usage of 3rd Party Services ────────────────────
86
- {
87
- rule: 'CICD_UNPINNED_ACTION',
88
- title: 'CI/CD: Unpinned GitHub Action (uses @main/master)',
89
- regex: /uses\s*:\s*[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+@(?:main|master|latest|v\d+)\b/g,
90
- severity: 'high',
91
- cwe: 'CWE-829',
92
- owasp: 'CICD-SEC-8',
93
- description: 'GitHub Action pinned to mutable tag. Pin to a specific commit SHA.',
94
- fix: 'Pin to commit SHA: uses: actions/checkout@abcdef1234567890 # v4.1.0',
95
- },
96
- {
97
- rule: 'CICD_UNVERIFIED_ACTION',
98
- title: 'CI/CD: Unverified Third-Party Action',
99
- regex: /uses\s*:\s*(?!actions\/|github\/|docker\/)[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+@/g,
100
- severity: 'medium',
101
- cwe: 'CWE-829',
102
- owasp: 'CICD-SEC-8',
103
- confidence: 'low',
104
- description: 'Third-party GitHub Action not from verified publisher. Review source code.',
105
- fix: 'Pin to commit SHA, review the action source, or use an official alternative',
106
- },
107
-
108
- // ── CICD-SEC-3: Dependency Chain Abuse ─────────────────────────────────────
109
- {
110
- rule: 'CICD_NO_LOCKFILE_INSTALL',
111
- title: 'CI/CD: Install Without Lockfile',
112
- regex: /npm\s+install(?!\s+--(?:frozen|ci))|yarn\s+(?!--frozen-lockfile)/g,
113
- severity: 'high',
114
- cwe: 'CWE-829',
115
- owasp: 'CICD-SEC-3',
116
- confidence: 'medium',
117
- description: 'CI runs npm install without --frozen-lockfile. Builds are non-deterministic.',
118
- fix: 'Use npm ci (not npm install) or yarn --frozen-lockfile in CI',
119
- },
120
-
121
- // ── CICD-SEC-7: Insecure System Configuration ─────────────────────────────
122
- {
123
- rule: 'CICD_SELF_HOSTED_RUNNER',
124
- title: 'CI/CD: Self-Hosted Runner',
125
- regex: /runs-on\s*:\s*self-hosted/g,
126
- severity: 'medium',
127
- cwe: 'CWE-250',
128
- owasp: 'CICD-SEC-7',
129
- confidence: 'medium',
130
- description: 'Self-hosted runners may persist state between jobs. Use ephemeral runners.',
131
- fix: 'Use ephemeral self-hosted runners that are cleaned after each job',
132
- },
133
-
134
- // ── CICD-SEC-9: Improper Artifact Integrity Validation ────────────────────
135
- {
136
- rule: 'CICD_NO_ARTIFACT_VERIFY',
137
- title: 'CI/CD: Artifact Used Without Verification',
138
- regex: /download-artifact|cache@|restore-keys/g,
139
- severity: 'low',
140
- cwe: 'CWE-345',
141
- owasp: 'CICD-SEC-9',
142
- confidence: 'low',
143
- description: 'Artifacts/caches used without integrity verification. Consider adding checksums.',
144
- fix: 'Verify artifact integrity with checksums or signatures',
145
- },
146
-
147
- // ── General CI/CD Issues ───────────────────────────────────────────────────
148
- {
149
- rule: 'CICD_CURL_PIPE_BASH',
150
- title: 'CI/CD: curl | bash Anti-Pattern',
151
- regex: /curl\s+[^|]*\|\s*(?:sudo\s+)?(?:bash|sh|zsh)/g,
152
- severity: 'critical',
153
- cwe: 'CWE-829',
154
- description: 'Piping curl to shell is dangerous. Download, verify, then execute.',
155
- fix: 'Download file first, verify checksum, then execute: curl -o script.sh && sha256sum -c && bash script.sh',
156
- },
157
- {
158
- rule: 'CICD_SCRIPT_INJECTION',
159
- title: 'CI/CD: Script Injection via Expressions',
160
- regex: /run\s*:\s*[^\n]*\$\{\{\s*(?:github\.event\.(?:issue|comment|pull_request|review)\.(?:title|body|head\.ref|label))/g,
161
- severity: 'critical',
162
- cwe: 'CWE-78',
163
- owasp: 'CICD-SEC-4',
164
- description: 'GitHub expression in run step. Attacker-controlled values can inject shell commands.',
165
- fix: 'Use environment variables: env: TITLE: ${{ github.event.issue.title }} then run: echo "$TITLE"',
166
- },
167
- ];
168
-
169
- export class CICDScanner extends BaseAgent {
170
- constructor() {
171
- super('CICDScanner', 'Detect CI/CD pipeline security issues (OWASP CI/CD Top 10)', 'cicd');
172
- }
173
-
174
- async analyze(context) {
175
- const { rootPath, files } = context;
176
-
177
- const ciFiles = files.filter(f => {
178
- const relPath = path.relative(rootPath, f).replace(/\\/g, '/');
179
- const basename = path.basename(f);
180
- return (
181
- relPath.startsWith('.github/workflows/') ||
182
- basename === '.gitlab-ci.yml' ||
183
- basename === 'Jenkinsfile' ||
184
- relPath.startsWith('.circleci/') ||
185
- basename === 'bitbucket-pipelines.yml' ||
186
- basename === 'azure-pipelines.yml' ||
187
- basename === '.travis.yml'
188
- );
189
- });
190
-
191
- if (ciFiles.length === 0) return [];
192
-
193
- let findings = [];
194
- for (const file of ciFiles) {
195
- findings = findings.concat(this.scanFileWithPatterns(file, PATTERNS));
196
- }
197
- return findings;
198
- }
199
- }
200
-
201
- export default CICDScanner;
1
+ /**
2
+ * CICDScanner Agent
3
+ * ==================
4
+ *
5
+ * Detect security issues in CI/CD pipeline configurations.
6
+ * Based on OWASP Top 10 CI/CD Security Risks.
7
+ *
8
+ * Scans: GitHub Actions, GitLab CI, Jenkins, CircleCI,
9
+ * Bitbucket Pipelines, Azure DevOps.
10
+ */
11
+
12
+ import path from 'path';
13
+ import { BaseAgent } from './base-agent.js';
14
+
15
+ const PATTERNS = [
16
+ // ── CICD-SEC-4: Poisoned Pipeline Execution ────────────────────────────────
17
+ {
18
+ rule: 'CICD_PR_TARGET_CHECKOUT',
19
+ title: 'CI/CD: pull_request_target with PR Checkout',
20
+ regex: /\bpull_request_target\b/g,
21
+ severity: 'critical',
22
+ cwe: 'CWE-94',
23
+ owasp: 'CICD-SEC-4',
24
+ confidence: 'medium',
25
+ description: 'pull_request_target trigger detected. Runs with base branch privileges and can be exploited if combined with PR checkout.',
26
+ fix: 'Use pull_request trigger instead, or never checkout PR branch in pull_request_target',
27
+ },
28
+ {
29
+ rule: 'CICD_WORKFLOW_RUN',
30
+ title: 'CI/CD: Unrestricted workflow_run Trigger',
31
+ regex: /workflow_run[\s\S]{0,200}types:\s*\[?\s*completed/g,
32
+ severity: 'high',
33
+ cwe: 'CWE-94',
34
+ owasp: 'CICD-SEC-4',
35
+ confidence: 'medium',
36
+ description: 'workflow_run trigger can execute with elevated permissions from a completed workflow.',
37
+ fix: 'Add conditions to check the source workflow and event',
38
+ },
39
+
40
+ // ── CICD-SEC-2: Inadequate Identity and Access Management ──────────────────
41
+ {
42
+ rule: 'CICD_EXCESSIVE_PERMISSIONS',
43
+ title: 'CI/CD: Write-All Permissions',
44
+ regex: /permissions\s*:\s*write-all/g,
45
+ severity: 'high',
46
+ cwe: 'CWE-250',
47
+ owasp: 'CICD-SEC-2',
48
+ description: 'Workflow has write-all permissions. Apply least privilege.',
49
+ fix: 'Set granular permissions: permissions: { contents: read, pull-requests: write }',
50
+ },
51
+ {
52
+ rule: 'CICD_PERMISSIVE_TOKEN',
53
+ title: 'CI/CD: Permissive GITHUB_TOKEN',
54
+ regex: /permissions\s*:\s*\n\s*contents\s*:\s*write/g,
55
+ severity: 'medium',
56
+ cwe: 'CWE-250',
57
+ owasp: 'CICD-SEC-2',
58
+ confidence: 'low',
59
+ description: 'GITHUB_TOKEN has contents: write. Consider if read is sufficient.',
60
+ fix: 'Use contents: read unless the workflow needs to push commits',
61
+ },
62
+
63
+ // ── CICD-SEC-6: Insufficient Credential Hygiene ────────────────────────────
64
+ {
65
+ rule: 'CICD_SECRET_IN_LOG',
66
+ title: 'CI/CD: Secret Potentially Logged',
67
+ regex: /echo\s+\$\{\{\s*secrets\./g,
68
+ severity: 'critical',
69
+ cwe: 'CWE-532',
70
+ owasp: 'CICD-SEC-6',
71
+ description: 'Secret printed via echo may appear in CI logs. GitHub masks known secrets but not all.',
72
+ fix: 'Never echo secrets. Use them only in environment variables or file writes.',
73
+ },
74
+ {
75
+ rule: 'CICD_HARDCODED_SECRET',
76
+ title: 'CI/CD: Hardcoded Secret in Workflow',
77
+ regex: /(?:api[_-]?key|token|password|secret)\s*[:=]\s*["'][a-zA-Z0-9_\-]{20,}["']/gi,
78
+ severity: 'critical',
79
+ cwe: 'CWE-798',
80
+ owasp: 'CICD-SEC-6',
81
+ description: 'Hardcoded secret in CI/CD configuration. Use repository/organization secrets.',
82
+ fix: 'Move to GitHub/GitLab secrets: ${{ secrets.MY_SECRET }}',
83
+ },
84
+
85
+ // ── CICD-SEC-8: Ungoverned Usage of 3rd Party Services ────────────────────
86
+ {
87
+ rule: 'CICD_UNPINNED_ACTION',
88
+ title: 'CI/CD: Unpinned GitHub Action (mutable tag)',
89
+ regex: /uses\s*:\s*[\w.-]+\/[\w.-]+@(?![\da-f]{40}\b)[\w./-]+/g,
90
+ severity: 'high',
91
+ cwe: 'CWE-829',
92
+ owasp: 'CICD-SEC-8',
93
+ description: 'GitHub Action not pinned to a full commit SHA. Mutable tags (@main, @master, @v1, @v1.2.3) can be force-pushed to malicious commits the technique used in the 2026 Trivy/TeamPCP attack that compromised 10,000+ pipelines.',
94
+ fix: 'Pin to full 40-char commit SHA: uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2',
95
+ },
96
+ {
97
+ rule: 'CICD_UNVERIFIED_ACTION',
98
+ title: 'CI/CD: Unverified Third-Party Action',
99
+ regex: /uses\s*:\s*(?!actions\/|github\/|docker\/)[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+@/g,
100
+ severity: 'medium',
101
+ cwe: 'CWE-829',
102
+ owasp: 'CICD-SEC-8',
103
+ confidence: 'low',
104
+ description: 'Third-party GitHub Action not from verified publisher. Review source code.',
105
+ fix: 'Pin to commit SHA, review the action source, or use an official alternative',
106
+ },
107
+
108
+ // ── CICD-SEC-3: Dependency Chain Abuse ─────────────────────────────────────
109
+ {
110
+ rule: 'CICD_NO_LOCKFILE_INSTALL',
111
+ title: 'CI/CD: Install Without Lockfile',
112
+ regex: /npm\s+install(?!\s+--(?:frozen|ci))|yarn\s+(?!--frozen-lockfile)/g,
113
+ severity: 'high',
114
+ cwe: 'CWE-829',
115
+ owasp: 'CICD-SEC-3',
116
+ confidence: 'medium',
117
+ description: 'CI runs npm install without --frozen-lockfile. Builds are non-deterministic.',
118
+ fix: 'Use npm ci (not npm install) or yarn --frozen-lockfile in CI',
119
+ },
120
+
121
+ // ── CICD-SEC-7: Insecure System Configuration ─────────────────────────────
122
+ {
123
+ rule: 'CICD_SELF_HOSTED_RUNNER',
124
+ title: 'CI/CD: Self-Hosted Runner',
125
+ regex: /runs-on\s*:\s*self-hosted/g,
126
+ severity: 'medium',
127
+ cwe: 'CWE-250',
128
+ owasp: 'CICD-SEC-7',
129
+ confidence: 'medium',
130
+ description: 'Self-hosted runners may persist state between jobs. Use ephemeral runners.',
131
+ fix: 'Use ephemeral self-hosted runners that are cleaned after each job',
132
+ },
133
+
134
+ // ── CICD-SEC-9: Improper Artifact Integrity Validation ────────────────────
135
+ {
136
+ rule: 'CICD_NO_ARTIFACT_VERIFY',
137
+ title: 'CI/CD: Artifact Used Without Verification',
138
+ regex: /download-artifact|cache@|restore-keys/g,
139
+ severity: 'low',
140
+ cwe: 'CWE-345',
141
+ owasp: 'CICD-SEC-9',
142
+ confidence: 'low',
143
+ description: 'Artifacts/caches used without integrity verification. Consider adding checksums.',
144
+ fix: 'Verify artifact integrity with checksums or signatures',
145
+ },
146
+
147
+ // ── CICD-SEC-6: Credential Exfiltration via Network ───────────────────────
148
+ {
149
+ rule: 'CICD_ENV_EXFILTRATION',
150
+ title: 'CI/CD: Potential Secret/Env Exfiltration',
151
+ regex: /(?:curl|wget|Invoke-WebRequest|Invoke-RestMethod)\b[^\n]*\$\{\{\s*(?:secrets\.|env\.)[^\}]+\}\}/g,
152
+ severity: 'critical',
153
+ cwe: 'CWE-200',
154
+ owasp: 'CICD-SEC-6',
155
+ description: 'Network call with a GitHub expression referencing secrets or env vars. This is the exfiltration technique used in the 2026 Trivy/CanisterWorm attack — stolen credentials were encrypted and POSTed to an attacker-controlled endpoint.',
156
+ fix: 'Never pass secrets directly to curl/wget arguments. Use environment variables and verify the destination URL.',
157
+ },
158
+
159
+ // ── CICD-SEC-2: OIDC Trust Misconfiguration ────────────────────────────────
160
+ {
161
+ rule: 'CICD_OIDC_BROAD_SUBJECT',
162
+ title: 'CI/CD: Overly Broad OIDC Subject Claim',
163
+ regex: /subject(?:_claim)?\s*[:=]\s*["']repo:[^"']*[*][^"']*["']/gi,
164
+ severity: 'critical',
165
+ cwe: 'CWE-284',
166
+ owasp: 'CICD-SEC-2',
167
+ description: 'OIDC subject claim uses a wildcard. Any repository or branch matching the pattern can assume this cloud role. In 2026, UNC6426 used a wildcard OIDC trust to escalate from a stolen GitHub PAT to AWS administrator in 72 hours.',
168
+ fix: 'Restrict the subject claim to a specific repo and branch: repo:owner/repo:ref:refs/heads/main',
169
+ },
170
+ {
171
+ rule: 'CICD_OIDC_MISSING_SUBJECT',
172
+ title: 'CI/CD: OIDC Token Request Without Subject Restriction',
173
+ regex: /id-token\s*:\s*write/g,
174
+ severity: 'medium',
175
+ cwe: 'CWE-284',
176
+ owasp: 'CICD-SEC-2',
177
+ confidence: 'low',
178
+ description: 'Workflow requests OIDC token (id-token: write). Verify the cloud trust policy restricts the subject claim to specific repos/branches to prevent privilege escalation.',
179
+ fix: 'Ensure the cloud IAM trust policy sets a specific sub condition, not a wildcard.',
180
+ },
181
+
182
+ // ── General CI/CD Issues ───────────────────────────────────────────────────
183
+ {
184
+ rule: 'CICD_CURL_PIPE_BASH',
185
+ title: 'CI/CD: curl | bash Anti-Pattern',
186
+ regex: /curl\s+[^|]*\|\s*(?:sudo\s+)?(?:bash|sh|zsh)/g,
187
+ severity: 'critical',
188
+ cwe: 'CWE-829',
189
+ description: 'Piping curl to shell is dangerous. Download, verify, then execute.',
190
+ fix: 'Download file first, verify checksum, then execute: curl -o script.sh && sha256sum -c && bash script.sh',
191
+ },
192
+ {
193
+ rule: 'CICD_SCRIPT_INJECTION',
194
+ title: 'CI/CD: Script Injection via Expressions',
195
+ regex: /run\s*:\s*[^\n]*\$\{\{\s*(?:github\.event\.(?:issue|comment|pull_request|review)\.(?:title|body|head\.ref|label))/g,
196
+ severity: 'critical',
197
+ cwe: 'CWE-78',
198
+ owasp: 'CICD-SEC-4',
199
+ description: 'GitHub expression in run step. Attacker-controlled values can inject shell commands.',
200
+ fix: 'Use environment variables: env: TITLE: ${{ github.event.issue.title }} then run: echo "$TITLE"',
201
+ },
202
+ ];
203
+
204
+ export class CICDScanner extends BaseAgent {
205
+ constructor() {
206
+ super('CICDScanner', 'Detect CI/CD pipeline security issues (OWASP CI/CD Top 10)', 'cicd');
207
+ }
208
+
209
+ async analyze(context) {
210
+ const { rootPath, files } = context;
211
+
212
+ const ciFiles = files.filter(f => {
213
+ const relPath = path.relative(rootPath, f).replace(/\\/g, '/');
214
+ const basename = path.basename(f);
215
+ return (
216
+ relPath.startsWith('.github/workflows/') ||
217
+ basename === '.gitlab-ci.yml' ||
218
+ basename === 'Jenkinsfile' ||
219
+ relPath.startsWith('.circleci/') ||
220
+ basename === 'bitbucket-pipelines.yml' ||
221
+ basename === 'azure-pipelines.yml' ||
222
+ basename === '.travis.yml'
223
+ );
224
+ });
225
+
226
+ if (ciFiles.length === 0) return [];
227
+
228
+ let findings = [];
229
+ for (const file of ciFiles) {
230
+ findings = findings.concat(this.scanFileWithPatterns(file, PATTERNS));
231
+ }
232
+ return findings;
233
+ }
234
+ }
235
+
236
+ export default CICDScanner;