secure-review-extension 1.0.3 → 1.0.4

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/package.json CHANGED
@@ -2,7 +2,7 @@
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.3",
5
+ "version": "1.0.4",
6
6
  "publisher": "your-publisher-id",
7
7
  "icon": "media/shield.png",
8
8
  "license": "MIT",
@@ -43,6 +43,27 @@ const ALLOWED_EXTENSIONS = new Set([
43
43
  ".xml"
44
44
  ]);
45
45
 
46
+ const LOCKFILE_NAMES = new Set([
47
+ "package-lock.json",
48
+ "yarn.lock",
49
+ "pnpm-lock.yaml",
50
+ "Cargo.lock",
51
+ "poetry.lock"
52
+ ]);
53
+
54
+ const ENV_LIKE_NAMES = new Set([
55
+ ".env",
56
+ ".env.local",
57
+ ".env.development",
58
+ ".env.production",
59
+ ".env.test"
60
+ ]);
61
+
62
+ const ENV_ALLOWED_RULES = new Set([
63
+ "hardcoded-secret",
64
+ "aws-access-key"
65
+ ]);
66
+
46
67
  async function scanWorkspace(config) {
47
68
  const workspaceProfile = await buildWorkspaceProfile(config);
48
69
  return scanProfile(workspaceProfile, config);
@@ -104,8 +125,13 @@ function scanContent(filePath, content, workspaceRoot) {
104
125
  const lines = content.split(/\r?\n/);
105
126
  const findings = [];
106
127
  const relativePath = toRelativePath(filePath, workspaceRoot);
128
+ const baseName = path.basename(filePath);
107
129
 
108
130
  for (const rule of STATIC_RULES) {
131
+ if (!shouldApplyRuleToFile(rule, filePath, baseName)) {
132
+ continue;
133
+ }
134
+
109
135
  const regex = new RegExp(rule.regex);
110
136
  let match;
111
137
 
@@ -147,6 +173,26 @@ function scanContent(filePath, content, workspaceRoot) {
147
173
  return findings;
148
174
  }
149
175
 
176
+ function shouldApplyRuleToFile(rule, filePath, baseName) {
177
+ if (isLockfile(baseName)) {
178
+ return false;
179
+ }
180
+
181
+ if (isEnvLikeFile(filePath, baseName)) {
182
+ return ENV_ALLOWED_RULES.has(rule.id);
183
+ }
184
+
185
+ return true;
186
+ }
187
+
188
+ function isLockfile(baseName) {
189
+ return LOCKFILE_NAMES.has(baseName);
190
+ }
191
+
192
+ function isEnvLikeFile(filePath, baseName) {
193
+ return ENV_LIKE_NAMES.has(baseName) || /\.env(\.|$)/i.test(filePath);
194
+ }
195
+
150
196
  function correlateTestCoverage(findings, relativePaths) {
151
197
  return findings.filter((finding) => {
152
198
  if (finding.code !== "missing-tests-heuristic") {
@@ -219,6 +219,10 @@ async function runEslint(workspaceProfile, config) {
219
219
  const excludes = scannerExcludeNames(workspaceProfile).flatMap((entry) => ["--ignore-pattern", entry]);
220
220
  const result = await execFileAsync("eslint", ["-f", "json", ...excludes, "."], scannerOptions(workspaceProfile, config));
221
221
 
222
+ if (eslintConfigMissing(result)) {
223
+ return [];
224
+ }
225
+
222
226
  if (result.error && !result.stdout) {
223
227
  throw result.error;
224
228
  }
@@ -260,6 +264,12 @@ async function runEslint(workspaceProfile, config) {
260
264
  }));
261
265
  }
262
266
 
267
+ function eslintConfigMissing(result) {
268
+ const text = `${result?.stdout || ""}\n${result?.stderr || ""}`;
269
+ return /eslint couldn't find an eslint\.config\.(js|mjs|cjs) file/i.test(text)
270
+ || /could not find config file/i.test(text);
271
+ }
272
+
263
273
  async function runNpmAudit(workspaceProfile, config) {
264
274
  if (!fs.existsSync(path.join(workspaceProfile.workspaceRoot, "package.json"))) {
265
275
  return [];