uascript
Version:
Javascript in Ukrainian
72 lines (71 loc) • 2.51 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ShellCommand = void 0;
const fs = require('fs/promises');
const path = require('path');
class ShellCommand {
validatePath(inputPath, basePath) {
const normalized = path.resolve(inputPath);
if (basePath) {
const base = path.resolve(basePath);
const relative = path.relative(base, normalized);
if (relative.startsWith('..') || path.isAbsolute(relative)) {
throw new Error(`Path traversal detected: ${inputPath} is outside ${basePath}`);
}
}
if (normalized.includes('\0') || normalized.includes('\n')) {
throw new Error(`Invalid characters in path: ${inputPath}`);
}
return normalized;
}
async mkdir(dirPath, deep = false, basePath) {
const normalizedPath = this.validatePath(dirPath, basePath);
try {
await fs.mkdir(normalizedPath, { recursive: deep });
return normalizedPath;
}
catch (error) {
if (error.code === 'EEXIST') {
return normalizedPath;
}
throw new Error(`Failed to create directory: ${error.message}`);
}
}
async rmrf(dirPath, basePath) {
const normalizedPath = this.validatePath(dirPath, basePath);
const forbiddenPaths = [
'/',
'/usr',
'/etc',
'/bin',
'/sbin',
'/var',
'/sys',
'/proc',
'/dev'
];
for (const forbidden of forbiddenPaths) {
if (normalizedPath === forbidden || normalizedPath.startsWith(forbidden + '/')) {
throw new Error(`Cannot remove system directory: ${dirPath}`);
}
}
try {
await fs.rm(normalizedPath, { recursive: true, force: true });
return normalizedPath;
}
catch (error) {
throw new Error(`Failed to remove directory: ${error.message}`);
}
}
async ls(dirPath, basePath) {
const normalizedPath = this.validatePath(dirPath, basePath);
try {
const entries = await fs.readdir(normalizedPath, { withFileTypes: true });
return entries.map((entry) => entry.name);
}
catch (error) {
throw new Error(`Failed to list directory: ${error.message}`);
}
}
}
exports.ShellCommand = ShellCommand;