another test
This commit is contained in:
@@ -3669,11 +3669,18 @@ function handlePeerData(data, topicId, peer) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.warn(`[WARN] Unhandled response type: ${response.type}`);
|
// Check if this is a directory browser response (no type field, but has contents)
|
||||||
|
if (response.success && Array.isArray(response.contents) && response.path !== undefined) {
|
||||||
|
// This is a directory browser response, let the directory handler process it
|
||||||
|
// Don't warn about it
|
||||||
|
} else {
|
||||||
|
console.warn(`[WARN] Unhandled response type: ${response.type}`);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle peer response callback if defined
|
// Handle peer response callback if defined
|
||||||
|
// This allows custom handlers (like directory browser) to process responses
|
||||||
if (typeof window.handlePeerResponse === 'function') {
|
if (typeof window.handlePeerResponse === 'function') {
|
||||||
window.handlePeerResponse(response);
|
window.handlePeerResponse(response);
|
||||||
}
|
}
|
||||||
|
|||||||
+22
-6
@@ -1291,22 +1291,38 @@ swarm.on('connection', (peer) => {
|
|||||||
console.log(`[INFO] Handling 'browseDirectory' command for path: ${parsedData.args?.path || '/'}`);
|
console.log(`[INFO] Handling 'browseDirectory' command for path: ${parsedData.args?.path || '/'}`);
|
||||||
try {
|
try {
|
||||||
const requestedPath = parsedData.args?.path || '/';
|
const requestedPath = parsedData.args?.path || '/';
|
||||||
console.log(`[DEBUG] Requested path: ${requestedPath}`);
|
console.log(`[DEBUG] Requested path: "${requestedPath}"`);
|
||||||
|
|
||||||
// Validate and sanitize path
|
// Validate path
|
||||||
if (!validation.isValidDirectoryPath(requestedPath)) {
|
if (!validation.isValidDirectoryPath(requestedPath)) {
|
||||||
console.error(`[ERROR] Invalid directory path: ${requestedPath}`);
|
console.error(`[ERROR] Invalid directory path: ${requestedPath}`);
|
||||||
throw new Error('Invalid directory path');
|
throw new Error('Invalid directory path');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sanitize path
|
||||||
const safePath = validation.sanitizeDirectoryPath(requestedPath);
|
const safePath = validation.sanitizeDirectoryPath(requestedPath);
|
||||||
console.log(`[DEBUG] Sanitized path: ${safePath}`);
|
console.log(`[DEBUG] Sanitized path: "${safePath}" (from "${requestedPath}")`);
|
||||||
|
|
||||||
|
// Verify the path exists and is a directory
|
||||||
|
try {
|
||||||
|
const stats = fs.statSync(safePath);
|
||||||
|
if (!stats.isDirectory()) {
|
||||||
|
throw new Error('Not a directory: The specified path is not a directory');
|
||||||
|
}
|
||||||
|
} catch (statError) {
|
||||||
|
if (statError.code === 'ENOENT') {
|
||||||
|
throw new Error('Directory not found: The specified path does not exist');
|
||||||
|
} else if (statError.code === 'EACCES') {
|
||||||
|
throw new Error('Permission denied: You do not have permission to access this directory');
|
||||||
|
}
|
||||||
|
throw statError;
|
||||||
|
}
|
||||||
|
|
||||||
// Read directory contents
|
// Read directory contents
|
||||||
const contents = [];
|
const contents = [];
|
||||||
try {
|
try {
|
||||||
const items = fs.readdirSync(safePath, { withFileTypes: true });
|
const items = fs.readdirSync(safePath, { withFileTypes: true });
|
||||||
console.log(`[DEBUG] Found ${items.length} items in directory`);
|
console.log(`[DEBUG] Found ${items.length} items in directory "${safePath}"`);
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
try {
|
try {
|
||||||
@@ -1326,10 +1342,10 @@ swarm.on('connection', (peer) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[DEBUG] Returning ${contents.length} items to client`);
|
console.log(`[DEBUG] Returning ${contents.length} items to client for path: "${safePath}"`);
|
||||||
response = { success: true, contents, path: safePath };
|
response = { success: true, contents, path: safePath };
|
||||||
} catch (readError) {
|
} catch (readError) {
|
||||||
console.error(`[ERROR] Failed to read directory ${safePath}:`, readError);
|
console.error(`[ERROR] Failed to read directory "${safePath}":`, readError);
|
||||||
if (readError.code === 'EACCES') {
|
if (readError.code === 'EACCES') {
|
||||||
throw new Error('Permission denied: You do not have permission to access this directory');
|
throw new Error('Permission denied: You do not have permission to access this directory');
|
||||||
} else if (readError.code === 'ENOENT') {
|
} else if (readError.code === 'ENOENT') {
|
||||||
|
|||||||
@@ -351,20 +351,33 @@ function isValidDirectoryPath(path) {
|
|||||||
* @param {string} path - Directory path
|
* @param {string} path - Directory path
|
||||||
* @returns {string} - Sanitized path
|
* @returns {string} - Sanitized path
|
||||||
*/
|
*/
|
||||||
function sanitizeDirectoryPath(path) {
|
function sanitizeDirectoryPath(inputPath) {
|
||||||
if (!path || typeof path !== 'string') return '/';
|
if (!inputPath || typeof inputPath !== 'string') {
|
||||||
|
console.warn('[WARN] sanitizeDirectoryPath: Invalid input, returning /');
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
// Remove null bytes and control characters
|
// Remove null bytes and control characters
|
||||||
let sanitized = path.replace(/[\x00-\x1F\x7F]/g, '').trim();
|
let sanitized = inputPath.replace(/[\x00-\x1F\x7F]/g, '').trim();
|
||||||
|
|
||||||
|
// If empty after cleaning, return root
|
||||||
|
if (!sanitized) {
|
||||||
|
console.warn('[WARN] sanitizeDirectoryPath: Empty after cleaning, returning /');
|
||||||
|
return '/';
|
||||||
|
}
|
||||||
|
|
||||||
// Resolve to absolute path and prevent traversal
|
// Resolve to absolute path and prevent traversal
|
||||||
try {
|
try {
|
||||||
// Resolve the path to handle relative components safely
|
// If already absolute, use as-is (path.resolve will normalize it)
|
||||||
|
// If relative, resolve from current working directory
|
||||||
sanitized = path.resolve(sanitized);
|
sanitized = path.resolve(sanitized);
|
||||||
|
|
||||||
|
console.log(`[DEBUG] sanitizeDirectoryPath: Resolved "${inputPath}" to "${sanitized}"`);
|
||||||
|
|
||||||
// Ensure it's still absolute after resolution
|
// Ensure it's still absolute after resolution
|
||||||
if (!path.isAbsolute(sanitized)) {
|
if (!path.isAbsolute(sanitized)) {
|
||||||
sanitized = '/';
|
console.warn(`[WARN] sanitizeDirectoryPath: Resolved path is not absolute: "${sanitized}", returning /`);
|
||||||
|
return '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Additional safety: prevent access to sensitive directories
|
// Additional safety: prevent access to sensitive directories
|
||||||
@@ -373,14 +386,17 @@ function sanitizeDirectoryPath(path) {
|
|||||||
for (const sensitive of sensitivePaths) {
|
for (const sensitive of sensitivePaths) {
|
||||||
if (sanitized.startsWith(sensitive) && sanitized !== sensitive) {
|
if (sanitized.startsWith(sensitive) && sanitized !== sensitive) {
|
||||||
// Allow root level but not deeper
|
// Allow root level but not deeper
|
||||||
|
console.warn(`[WARN] sanitizeDirectoryPath: Blocked access to sensitive path: "${sanitized}"`);
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(`[DEBUG] sanitizeDirectoryPath: Final sanitized path: "${sanitized}"`);
|
||||||
|
return sanitized;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.warn(`[WARN] Path sanitization error for "${inputPath}":`, error.message);
|
||||||
return '/';
|
return '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
return sanitized;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
Reference in New Issue
Block a user