aura-security 1.0.1 → 1.0.2

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.
@@ -66,7 +66,18 @@ const FALSE_POSITIVE_DIRS = [
66
66
  '/thirdparty/',
67
67
  '/external/',
68
68
  '/dummy/',
69
- '/fake/'
69
+ '/fake/',
70
+ '/data/',
71
+ '/scripts/data/',
72
+ '/seeds/',
73
+ '/seed/',
74
+ '/migrations/',
75
+ '/migration/',
76
+ '/index_constituents/',
77
+ '/token-list/',
78
+ '/tokenlist/',
79
+ '/verified-tokens/',
80
+ '/validated-tokens/'
70
81
  ];
71
82
  // File name patterns that indicate test/example data (not real secrets)
72
83
  const TEST_FILE_PATTERNS = [
@@ -108,6 +119,8 @@ const SKIP_RULES_IN_FILE_TYPES = {
108
119
  '.md': ['generic-api-key', 'curl-auth-header'],
109
120
  '.rst': ['generic-api-key', 'curl-auth-header'],
110
121
  '.txt': ['generic-api-key'],
122
+ // JSON files often contain token lists, address registries, config data - not real secrets
123
+ '.json': ['generic-api-key', 'aws-access-token', 'private-key'],
111
124
  };
112
125
  // Run gitleaks for secrets detection
113
126
  function runGitleaks(targetPath) {
@@ -153,8 +166,17 @@ function runGitleaks(targetPath) {
153
166
  const fileExt = extname(fileName).toLowerCase();
154
167
  const skipRulesForExt = SKIP_RULES_IN_FILE_TYPES[fileExt] || [];
155
168
  const isRuleSkippedForFileType = skipRulesForExt.includes(ruleId);
169
+ // Filter out JSON data files that contain token lists / address registries
170
+ // (Solana base58 addresses get flagged as API keys by gitleaks)
171
+ const isJsonDataFile = fileExt === '.json' && (/token[-_]?list/i.test(filePath) ||
172
+ /address(es)?[-_]?(list|registry)/i.test(filePath) ||
173
+ /constituents/i.test(filePath) ||
174
+ /verified[-_]?tokens/i.test(filePath) ||
175
+ /validated[-_]?tokens/i.test(filePath) ||
176
+ /mint(s)?[-_]?(list|registry)/i.test(filePath) ||
177
+ /registry\.json$/i.test(filePath));
156
178
  // Skip if any false positive indicator matches
157
- if (isExcludedFile || isInFalsePositiveDir || isTestFile || isFalsePositiveRule || isRuleSkippedForFileType) {
179
+ if (isExcludedFile || isInFalsePositiveDir || isTestFile || isFalsePositiveRule || isRuleSkippedForFileType || isJsonDataFile) {
158
180
  filteredCount++;
159
181
  continue;
160
182
  }
@@ -166,13 +188,34 @@ function runGitleaks(targetPath) {
166
188
  severity: finding.Entropy > 4.5 ? 'critical' : 'high'
167
189
  });
168
190
  }
191
+ // Post-processing: if a single JSON file has 10+ findings, it's almost certainly
192
+ // a data/registry file (token lists, address mappings) not real leaked secrets
193
+ const fileCounts = new Map();
194
+ for (const f of findings) {
195
+ if (f.file.toLowerCase().endsWith('.json')) {
196
+ fileCounts.set(f.file, (fileCounts.get(f.file) || 0) + 1);
197
+ }
198
+ }
199
+ const bulkJsonFiles = new Set();
200
+ for (const [file, count] of fileCounts) {
201
+ if (count >= 10) {
202
+ bulkJsonFiles.add(file);
203
+ filteredCount += count;
204
+ console.log(`[SCANNER] Filtered ${count} findings from ${basename(file)} (bulk data file)`);
205
+ }
206
+ }
207
+ if (bulkJsonFiles.size > 0) {
208
+ const beforeCount = findings.length;
209
+ findings.splice(0, findings.length, ...findings.filter(f => !bulkJsonFiles.has(f.file)));
210
+ console.log(`[SCANNER] Removed ${beforeCount - findings.length} bulk JSON false positives`);
211
+ }
169
212
  // Cleanup
170
213
  try {
171
214
  rmSync(reportPath);
172
215
  }
173
216
  catch { }
174
217
  if (filteredCount > 0) {
175
- console.log(`[SCANNER] Filtered ${filteredCount} false positives (test files, examples, lock files)`);
218
+ console.log(`[SCANNER] Filtered ${filteredCount} false positives (test files, examples, lock files, data files)`);
176
219
  }
177
220
  }
178
221
  console.log(`[SCANNER] gitleaks found ${findings.length} secrets`);
@@ -777,10 +820,20 @@ const SECRET_PATTERNS = [
777
820
  // OpenAI API Key
778
821
  { name: 'OpenAI Key', regex: /sk-[A-Za-z0-9]{32,}/g, severity: 'high' },
779
822
  ];
780
- // Files/patterns to SKIP for secret scanning (test files, examples, etc.)
823
+ // Files/patterns to SKIP for secret scanning (test files, examples, lock files, data files)
781
824
  const SKIP_SECRET_SCAN_PATTERNS = [
825
+ // Test/example files
782
826
  /example/i, /sample/i, /test/i, /mock/i, /fixture/i, /\.test\./i, /\.spec\./i,
783
- /\.d\.ts$/, /\.map$/, /\.min\./
827
+ // Build artifacts
828
+ /\.d\.ts$/, /\.map$/, /\.min\./,
829
+ // Lock files (contain hashes that trigger false positives, never contain real secrets)
830
+ /package-lock\.json$/i, /pnpm-lock\.yaml$/i, /yarn\.lock$/i, /Cargo\.lock$/i, /composer\.lock$/i, /Gemfile\.lock$/i,
831
+ // Template/example env files (placeholders, not real secrets)
832
+ /\.example$/i, /\.template$/i, /\.sample$/i,
833
+ // Data directories (contain public addresses, not secrets)
834
+ /\/data\//i, /\/fixtures?\//i, /\/seeds?\//i, /\/migrations?\//i,
835
+ // Index/constituent data files (stock symbols, token lists etc.)
836
+ /index_constituents/i, /token-?list/i, /verified-tokens/i, /validated-tokens/i,
784
837
  ];
785
838
  // Files to scan for secrets
786
839
  const FILES_TO_SCAN = [
@@ -1408,9 +1461,26 @@ export class LocalScanner {
1408
1461
  if (stats.size > 1024 * 1024)
1409
1462
  return findings;
1410
1463
  const content = readFileSync(filePath, 'utf-8');
1464
+ // Skip JSON files that are clearly data (token lists, address registries, etc.)
1465
+ // These contain public blockchain addresses that regex misidentifies as secrets
1466
+ if (fileName.endsWith('.json')) {
1467
+ // If a JSON file has "tokens", "addresses", "mints", "symbols" keys, it's data
1468
+ if (/["'](tokens|addresses|mints|symbols|constituents|verified|validated)["']\s*:/i.test(content)) {
1469
+ return findings;
1470
+ }
1471
+ // If JSON file has more than 100 similar-looking base58 values, it's a token/address list
1472
+ const base58Matches = content.match(/["'][1-9A-HJ-NP-Za-km-z]{32,44}["']/g);
1473
+ if (base58Matches && base58Matches.length > 50) {
1474
+ return findings;
1475
+ }
1476
+ }
1411
1477
  const lines = content.split('\n');
1412
1478
  for (let i = 0; i < lines.length; i++) {
1413
1479
  const line = lines[i];
1480
+ // Skip lines that are clearly placeholder/example values
1481
+ if (/your[_-]?(?:api[_-]?key|token|secret)|REPLACE[_-]?ME|TODO|CHANGEME|xxxx|placeholder/i.test(line)) {
1482
+ continue;
1483
+ }
1414
1484
  for (const pattern of SECRET_PATTERNS) {
1415
1485
  pattern.regex.lastIndex = 0;
1416
1486
  const match = pattern.regex.exec(line);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aura-security",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "AI-powered security scanner with 9-agent swarm. Detect secrets, vulnerabilities, attack paths. CLI, API, or cloud dashboard at app.aurasecurity.io",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",