ferret-scan 1.0.6 → 1.0.7
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.
|
@@ -19,6 +19,6 @@ interface DiscoveryResult {
|
|
|
19
19
|
/**
|
|
20
20
|
* Main file discovery function
|
|
21
21
|
*/
|
|
22
|
-
export declare function discoverFiles(paths: string[], options: DiscoveryOptions): DiscoveryResult
|
|
22
|
+
export declare function discoverFiles(paths: string[], options: DiscoveryOptions): Promise<DiscoveryResult>;
|
|
23
23
|
export default discoverFiles;
|
|
24
24
|
//# sourceMappingURL=FileDiscovery.d.ts.map
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Scans directories for skills, agents, hooks, MCP configs, rules files, and other AI CLI files
|
|
4
4
|
* Supports: Claude Code, Cursor, Windsurf, Continue, Aider, Cline, and generic AI configs
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
6
|
+
import { readdir, stat, access } from 'node:fs/promises';
|
|
7
|
+
import { constants } from 'node:fs';
|
|
7
8
|
import { resolve, extname, basename, relative } from 'node:path';
|
|
8
9
|
import { createIgnoreFilter, shouldIgnore } from '../utils/ignore.js';
|
|
9
10
|
import logger from '../utils/logger.js';
|
|
@@ -136,10 +137,10 @@ function isAnalyzableFile(filePath) {
|
|
|
136
137
|
/**
|
|
137
138
|
* Recursively discover files in a directory
|
|
138
139
|
*/
|
|
139
|
-
function discoverFilesInDirectory(dir, baseDir, ig, options, result) {
|
|
140
|
+
async function discoverFilesInDirectory(dir, baseDir, ig, options, result) {
|
|
140
141
|
let entries;
|
|
141
142
|
try {
|
|
142
|
-
entries =
|
|
143
|
+
entries = await readdir(dir);
|
|
143
144
|
}
|
|
144
145
|
catch (error) {
|
|
145
146
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -158,7 +159,7 @@ function discoverFilesInDirectory(dir, baseDir, ig, options, result) {
|
|
|
158
159
|
}
|
|
159
160
|
let stats;
|
|
160
161
|
try {
|
|
161
|
-
stats =
|
|
162
|
+
stats = await stat(fullPath);
|
|
162
163
|
}
|
|
163
164
|
catch (error) {
|
|
164
165
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -167,7 +168,7 @@ function discoverFilesInDirectory(dir, baseDir, ig, options, result) {
|
|
|
167
168
|
}
|
|
168
169
|
if (stats.isDirectory()) {
|
|
169
170
|
// Recurse into directory
|
|
170
|
-
discoverFilesInDirectory(fullPath, baseDir, ig, options, result);
|
|
171
|
+
await discoverFilesInDirectory(fullPath, baseDir, ig, options, result);
|
|
171
172
|
}
|
|
172
173
|
else if (stats.isFile()) {
|
|
173
174
|
// Check if file should be analyzed
|
|
@@ -199,17 +200,29 @@ function discoverFilesInDirectory(dir, baseDir, ig, options, result) {
|
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Check if path exists
|
|
205
|
+
*/
|
|
206
|
+
async function pathExists(filePath) {
|
|
207
|
+
try {
|
|
208
|
+
await access(filePath, constants.F_OK);
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
202
215
|
/**
|
|
203
216
|
* Discover a single file
|
|
204
217
|
*/
|
|
205
|
-
function discoverSingleFile(filePath, options, result) {
|
|
206
|
-
if (!
|
|
218
|
+
async function discoverSingleFile(filePath, options, result) {
|
|
219
|
+
if (!(await pathExists(filePath))) {
|
|
207
220
|
result.errors.push({ path: filePath, error: 'File does not exist' });
|
|
208
221
|
return;
|
|
209
222
|
}
|
|
210
223
|
let stats;
|
|
211
224
|
try {
|
|
212
|
-
stats =
|
|
225
|
+
stats = await stat(filePath);
|
|
213
226
|
}
|
|
214
227
|
catch (error) {
|
|
215
228
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -242,7 +255,7 @@ function discoverSingleFile(filePath, options, result) {
|
|
|
242
255
|
/**
|
|
243
256
|
* Main file discovery function
|
|
244
257
|
*/
|
|
245
|
-
export function discoverFiles(paths, options) {
|
|
258
|
+
export async function discoverFiles(paths, options) {
|
|
246
259
|
const result = {
|
|
247
260
|
files: [],
|
|
248
261
|
skipped: 0,
|
|
@@ -254,18 +267,18 @@ export function discoverFiles(paths, options) {
|
|
|
254
267
|
}
|
|
255
268
|
for (const inputPath of paths) {
|
|
256
269
|
const resolvedPath = resolve(inputPath);
|
|
257
|
-
if (!
|
|
270
|
+
if (!(await pathExists(resolvedPath))) {
|
|
258
271
|
logger.warn(`Path does not exist: ${resolvedPath}`);
|
|
259
272
|
result.errors.push({ path: resolvedPath, error: 'Path does not exist' });
|
|
260
273
|
continue;
|
|
261
274
|
}
|
|
262
|
-
const stats =
|
|
275
|
+
const stats = await stat(resolvedPath);
|
|
263
276
|
if (stats.isDirectory()) {
|
|
264
277
|
const ig = createIgnoreFilter(resolvedPath, options.ignore);
|
|
265
|
-
discoverFilesInDirectory(resolvedPath, resolvedPath, ig, options, result);
|
|
278
|
+
await discoverFilesInDirectory(resolvedPath, resolvedPath, ig, options, result);
|
|
266
279
|
}
|
|
267
280
|
else if (stats.isFile()) {
|
|
268
|
-
discoverSingleFile(resolvedPath, options, result);
|
|
281
|
+
await discoverSingleFile(resolvedPath, options, result);
|
|
269
282
|
}
|
|
270
283
|
}
|
|
271
284
|
// Sort files by component type, then by path
|
package/dist/scanner/Scanner.js
CHANGED
|
@@ -188,7 +188,7 @@ export async function scan(config) {
|
|
|
188
188
|
if (showProgress) {
|
|
189
189
|
spinner = ora('Discovering files...').start();
|
|
190
190
|
}
|
|
191
|
-
const discovery = discoverFiles(config.paths, {
|
|
191
|
+
const discovery = await discoverFiles(config.paths, {
|
|
192
192
|
maxFileSize: config.maxFileSize,
|
|
193
193
|
ignore: config.ignore,
|
|
194
194
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ferret-scan",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Security scanner for AI CLI configurations - detect prompt injections, credential leaks, and malicious patterns in AI agent configs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|