Skip to content

Commit 466906f

Browse files
authored
fix(core): prevent workspace deletion in cleanOutput method (Fixes #57) (#60)
1 parent 00ba74e commit 466906f

2 files changed

Lines changed: 43 additions & 9 deletions

File tree

packages/core/src/lib/base-generator.spec.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,12 @@ describe('BaseGenerator', () => {
6464
});
6565
});
6666

67-
it('should handle root directory paths', () => {
68-
const relOutputPath = '/';
67+
it('should handle valid nested paths', () => {
68+
const relOutputPath = 'src/generated/api';
6969

7070
generator.testCleanOutput(mockContext, relOutputPath);
7171

72-
expect(rmSync).toHaveBeenCalledWith('/workspace/', {
72+
expect(rmSync).toHaveBeenCalledWith('/workspace/src/generated/api', {
7373
recursive: true,
7474
force: true,
7575
});
@@ -116,15 +116,44 @@ describe('BaseGenerator', () => {
116116
);
117117
});
118118

119-
it('should handle empty path', () => {
119+
it('should throw error for empty path', () => {
120120
const relOutputPath = '';
121121

122-
generator.testCleanOutput(mockContext, relOutputPath);
122+
expect(() => {
123+
generator.testCleanOutput(mockContext, relOutputPath);
124+
}).toThrow('Cannot clean empty or root output path for safety reasons');
123125

124-
expect(rmSync).toHaveBeenCalledWith('/workspace', {
125-
recursive: true,
126-
force: true,
127-
});
126+
expect(rmSync).not.toHaveBeenCalled();
127+
});
128+
129+
it('should throw error for whitespace-only path', () => {
130+
const relOutputPath = ' ';
131+
132+
expect(() => {
133+
generator.testCleanOutput(mockContext, relOutputPath);
134+
}).toThrow('Cannot clean empty or root output path for safety reasons');
135+
136+
expect(rmSync).not.toHaveBeenCalled();
137+
});
138+
139+
it('should throw error for root path', () => {
140+
const relOutputPath = '/';
141+
142+
expect(() => {
143+
generator.testCleanOutput(mockContext, relOutputPath);
144+
}).toThrow('Cannot clean empty or root output path for safety reasons');
145+
146+
expect(rmSync).not.toHaveBeenCalled();
147+
});
148+
149+
it('should throw error for current directory path', () => {
150+
const relOutputPath = '.';
151+
152+
expect(() => {
153+
generator.testCleanOutput(mockContext, relOutputPath);
154+
}).toThrow('Cannot clean empty or root output path for safety reasons');
155+
156+
expect(rmSync).not.toHaveBeenCalled();
128157
});
129158
});
130159
});

packages/core/src/lib/base-generator.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import { GeneratorContext } from './interfaces';
44

55
export abstract class BaseGenerator {
66
protected cleanOutput(ctx: GeneratorContext, relOutputPath: string) {
7+
// Validate input path is not empty or dangerous
8+
if (!relOutputPath || relOutputPath.trim() === '' || relOutputPath === '/' || relOutputPath === '.') {
9+
throw new Error('Cannot clean empty or root output path for safety reasons');
10+
}
11+
712
const full = join(ctx.root, relOutputPath);
813
rmSync(full, { recursive: true, force: true });
914
}

0 commit comments

Comments
 (0)