timonel 2.1.1 → 2.3.0

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.
@@ -0,0 +1,117 @@
1
+ import * as path from 'path';
2
+ /**
3
+ * Security utilities for input validation and sanitization
4
+ * Focused on CLI tool security concerns: path traversal, injection prevention
5
+ */
6
+ export class SecurityUtils {
7
+ /**
8
+ * Validates and sanitizes file paths to prevent path traversal attacks
9
+ * @param inputPath - The path to validate
10
+ * @param allowedBasePath - The base path that the input should be within
11
+ * @returns Sanitized path if valid
12
+ * @throws Error if path is invalid or contains traversal sequences
13
+ */
14
+ static validatePath(inputPath, allowedBasePath) {
15
+ if (!inputPath || typeof inputPath !== 'string') {
16
+ throw new Error('Invalid path: path must be a non-empty string');
17
+ }
18
+ // Check for path traversal sequences
19
+ if (inputPath.includes('../') ||
20
+ inputPath.includes('..\\') ||
21
+ inputPath.includes('%2e%2e%2f') ||
22
+ inputPath.includes('%2e%2e%5c')) {
23
+ throw new Error('Invalid path: path traversal sequences detected');
24
+ }
25
+ // Resolve and normalize paths
26
+ const resolvedInput = path.resolve(inputPath);
27
+ const resolvedBase = path.resolve(allowedBasePath);
28
+ // Ensure the resolved path is within the allowed base path
29
+ if (!resolvedInput.startsWith(resolvedBase + path.sep) && resolvedInput !== resolvedBase) {
30
+ throw new Error(`Invalid path: path must be within ${resolvedBase}`);
31
+ }
32
+ return resolvedInput;
33
+ }
34
+ /**
35
+ * Sanitizes log messages to prevent log injection attacks
36
+ * @param message - The message to sanitize
37
+ * @returns Sanitized message with control characters removed
38
+ */
39
+ static sanitizeLogMessage(message) {
40
+ if (typeof message !== 'string') {
41
+ return String(message);
42
+ }
43
+ // Remove control characters (ASCII 0-31 and 127) and normalize line endings
44
+ return (message
45
+ // eslint-disable-next-line no-control-regex -- Intentionally removing control characters for security
46
+ .replace(/[\x00-\x1F\x7F]/g, '') // Remove control characters
47
+ .replace(/\r\n/g, ' ') // Replace CRLF with space
48
+ .replace(/[\r\n]/g, ' ') // Replace remaining CR/LF with space
49
+ .trim());
50
+ }
51
+ /**
52
+ * Sanitizes environment names to prevent path traversal (CWE-22)
53
+ * @param env - Environment name to sanitize
54
+ * @returns Sanitized environment name
55
+ * @throws Error if environment name is invalid
56
+ */
57
+ static sanitizeEnvironmentName(env) {
58
+ if (!env || typeof env !== 'string') {
59
+ throw new Error('Environment name must be a non-empty string');
60
+ }
61
+ // Allow only alphanumeric, hyphens, and underscores
62
+ const sanitized = env.replace(/[^a-zA-Z0-9-_]/g, '');
63
+ if (sanitized !== env) {
64
+ throw new Error(`Invalid environment name: ${this.sanitizeLogMessage(env)}`);
65
+ }
66
+ if (sanitized.length === 0 || sanitized.length > 63) {
67
+ throw new Error('Environment name must be 1-63 characters long');
68
+ }
69
+ return sanitized;
70
+ }
71
+ /**
72
+ * Validates TypeScript file extensions for dynamic imports
73
+ * @param filePath - The file path to validate
74
+ * @returns True if the file has a valid TypeScript extension
75
+ */
76
+ static isValidTypeScriptFile(filePath) {
77
+ const allowedExtensions = ['.ts', '.tsx'];
78
+ const ext = path.extname(filePath);
79
+ return allowedExtensions.includes(ext);
80
+ }
81
+ /**
82
+ * Validates Helm template path syntax
83
+ * @param templatePath - The template path to validate
84
+ * @returns True if the path is valid for Helm templates
85
+ */
86
+ static isValidHelmTemplatePath(templatePath) {
87
+ if (!templatePath || typeof templatePath !== 'string') {
88
+ return false;
89
+ }
90
+ // Basic validation for dot notation and no special characters that could break Helm
91
+ const helmPathRegex = /^[a-zA-Z][a-zA-Z0-9._-]*$/;
92
+ return helmPathRegex.test(templatePath);
93
+ }
94
+ /**
95
+ * Validates chart names according to Helm conventions
96
+ * @param chartName - Chart name to validate
97
+ * @returns True if chart name follows Helm naming rules
98
+ */
99
+ static isValidChartName(chartName) {
100
+ if (!chartName || typeof chartName !== 'string') {
101
+ return false;
102
+ }
103
+ // Helm chart name validation (RFC 1123 subdomain) - safe regex
104
+ // eslint-disable-next-line security/detect-unsafe-regex -- Simple character class regex is safe
105
+ const chartNameRegex = /^[a-z0-9]([-a-z0-9]*[a-z0-9])?$/;
106
+ return chartNameRegex.test(chartName) && chartName.length <= 63;
107
+ }
108
+ /**
109
+ * Validates subchart names according to Helm conventions
110
+ * @param subchartName - Subchart name to validate
111
+ * @returns True if subchart name is valid
112
+ */
113
+ static isValidSubchartName(subchartName) {
114
+ return this.isValidChartName(subchartName);
115
+ }
116
+ }
117
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/lib/security.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "timonel",
3
3
  "type": "module",
4
- "version": "2.1.1",
4
+ "version": "2.3.0",
5
5
  "description": "Timonel: programmatic Helm chart generator using cdk8s (TypeScript)",
6
6
  "bin": {
7
7
  "timonel": "dist/cli.js",