Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions extension/secureflow/packages/secureflow-cli/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ ENV NODE_ENV=production
ENV TARGETS_FILE=/app/tools/mgmt/targets.txt
ENV MAX_PLUGINS=50

# Create volume mount points for results and targets file
VOLUME ["/app/tools/mgmt/results", "/app/tools/mgmt/targets.txt"]

# Set default working directory for the script
WORKDIR /app

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ services:
context: .
dockerfile: Dockerfile
container_name: secureflow-plugin-analyzer
volumes:
# Mount the targets.txt file (read-only)
- ./tools/mgmt/targets.txt:/app/tools/mgmt/targets.txt:ro
# Mount results directory for output (read-write)
- ./results:/app/tools/mgmt/results:rw
# Mount settings directory for API key configuration
- secureflow-settings:/home/secureflow/.secureflow
environment:
- MAX_PLUGINS=50
- NODE_ENV=production
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ You are a highly experienced security engineer conducting a thorough code review
6. ALWAYS use tools to navigate through the code to understand the complete context of the vulnerability.
- Even though the project structure is provided, use list files tool to navigate through the code to understand the complete context of the vulnerability.
- Use file request tool to request for files if needed for complete analysis iteratively.
- Always start with list files tool to navigate through the code to understand the complete context of the vulnerability.

Strictly don't report below category of vulnerabilities from Analysis:
- Theoretical vulnerabilities without practical impact
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
------
2. Tool: list files in directory (equivalent to 'ls' command)
Description: This method helps to list files in a directory
2. Tool: Directory Listing (List Files and Subdirectories)
Description: Explore directory contents to discover files and subdirectories for security analysis
Purpose: Use this tool to navigate the project structure and identify files that need security review

Format:
<list_file_request path="./relative/path/to/directory" reason="short reason for requesting this directory" />
<list_file_request path="./relative/path/to/directory" reason="brief explanation of why you need to explore this directory" />

When to use this tool:
- Start security analysis by exploring the project root directory first
- Navigate into subdirectories to understand the project structure
- Discover configuration files, source code files, and security-relevant directories
- Find entry points, authentication modules, database connections, and API endpoints
- Explore directories mentioned in build files or configuration

Best practices:
1. Always start with the root directory (path="./") to get an overview
2. Use relative paths from the project root (e.g., "./src", "./config", "./api")
3. Explore directories systematically - start broad, then go deeper
4. Focus on security-relevant directories like src/, config/, auth/, api/, admin/
5. Limit to 3-5 directory requests per iteration to avoid overwhelming context
6. Don't request the same directory multiple times
7. Skip hidden directories (starting with .) unless they contain configuration files
8. Prioritize directories that likely contain business logic and security controls

Rules for file requests:
1. Use relative paths from the project root
2. Provide a short reason for each request
3. Files outside project scope will be ignored
4. Request only directory listed in 'Files in the project' section
5. Limit to 5 directories per request
6. Do not request same directory multiple times
7. Skip directories that were not found previously
8. Skip non-source directories
9. Follow project structure strictly
Example usage sequence:
1. <list_file_request path="./" reason="Get project overview and identify main directories" />
2. <list_file_request path="./src" reason="Explore source code structure" />
3. <list_file_request path="./config" reason="Check configuration files for security settings" />
----
Original file line number Diff line number Diff line change
Expand Up @@ -181,11 +181,24 @@ class AISecurityAnalyzer {
if (result.status === 'success') {
context += `\n=== DIRECTORY: ${result.path} ===\n`;
context += `Reason: ${result.reason}\n`;
context += `Files and directories found (${result.fileCount} items):\n`;
result.files.forEach(file => {
const icon = file.type === 'directory' ? '📁' : '📄';
context += `${icon} ${file.name} (${file.type})\n`;
});
context += `Total items: ${result.totalCount} (${result.directoryCount} directories, ${result.fileCount} files)\n`;

// List directories first
if (result.directories && result.directories.length > 0) {
context += `\nDirectories:\n`;
result.directories.forEach(dir => {
context += `📁 ${dir.name} (path: ${dir.relativePath})\n`;
});
}

// Then list files
if (result.files && result.files.length > 0) {
context += `\nFiles:\n`;
result.files.forEach(file => {
context += `📄 ${file.name} (path: ${file.relativePath})\n`;
});
}

context += `=== END DIRECTORY: ${result.path} ===\n`;
} else {
context += `❌ Directory listing failed for ${result.path}: ${result.reason}\n`;
Expand All @@ -210,7 +223,7 @@ class AISecurityAnalyzer {
context += `\n[DIRECTORY LISTING RESULTS]\n`;
listResults.forEach(result => {
if (result.status === 'success') {
context += `✅ ${result.path}: Successfully listed (${result.fileCount} items)\n`;
context += `✅ ${result.path}: Successfully listed (${result.totalCount} total items: ${result.directoryCount} directories, ${result.fileCount} files)\n`;
} else {
context += `❌ Directory listing failed for ${result.path}: ${result.reason}. Don't request it again\n`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,19 @@ class FileRequestHandler {
}

// List directory contents
const files = await this._listDirectoryContents(fullPath);
const contents = await this._listDirectoryContents(fullPath);

return {
status: 'success',
path: requestedPath,
fullPath,
files,
files: contents.files,
directories: contents.directories,
all: contents.all,
reason,
fileCount: files.length
fileCount: contents.files.length,
directoryCount: contents.directories.length,
totalCount: contents.all.length
};

} catch (error) {
Expand All @@ -263,48 +267,63 @@ class FileRequestHandler {
}

/**
* List directory contents with filtering
* List directory contents with filtering, including both files and directories with full paths
*/
async _listDirectoryContents(dirPath) {
const { readdir } = require('fs').promises;

try {
const items = await readdir(dirPath, { withFileTypes: true });
const files = [];
const result = {
files: [],
directories: [],
all: []
};

for (const item of items) {
// Skip hidden files and directories
if (item.name.startsWith('.') && item.name !== '.env' && item.name !== '.gitignore') {
// Skip hidden files and directories (except important config files)
if (item.name.startsWith('.') &&
item.name !== '.env' &&
item.name !== '.gitignore' &&
item.name !== '.config' &&
item.name !== '.npmrc' &&
item.name !== '.dockerignore') {
continue;
}

const itemPath = path.join(dirPath, item.name);
const relativePath = path.relative(this.projectPath, itemPath);
const fullPath = path.resolve(itemPath);

const itemInfo = {
name: item.name,
type: item.isDirectory() ? 'directory' : 'file',
relativePath: relativePath.startsWith('.') ? relativePath : `./${relativePath}`,
fullPath: fullPath
};

if (item.isDirectory()) {
files.push({
name: item.name,
type: 'directory',
relativePath: relativePath
});
result.directories.push(itemInfo);
} else if (item.isFile()) {
files.push({
name: item.name,
type: 'file',
relativePath: relativePath
});
result.files.push(itemInfo);
}

result.all.push(itemInfo);
}

// Sort by type (directories first) then by name
files.sort((a, b) => {
const sortFn = (a, b) => {
if (a.type !== b.type) {
return a.type === 'directory' ? -1 : 1;
}
return a.name.localeCompare(b.name);
});
};

result.files.sort(sortFn);
result.directories.sort(sortFn);
result.all.sort(sortFn);

return files;
return result;
} catch (error) {
throw new Error(`Failed to read directory: ${error.message}`);
}
Expand Down