telegram-ssh-bot 2.0.0 → 2.2.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.
Files changed (184) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +103 -22
  3. package/deploy/.env.example +86 -0
  4. package/dist/config/index.d.ts +68 -0
  5. package/dist/config/index.d.ts.map +1 -0
  6. package/dist/config/index.js +315 -0
  7. package/dist/config/index.js.map +1 -0
  8. package/dist/config/schema.d.ts +6 -0
  9. package/dist/config/schema.d.ts.map +1 -0
  10. package/dist/config/schema.js +50 -0
  11. package/dist/config/schema.js.map +1 -0
  12. package/dist/core/Bot.d.ts +91 -0
  13. package/dist/core/Bot.d.ts.map +1 -0
  14. package/dist/core/Bot.js +263 -0
  15. package/dist/core/Bot.js.map +1 -0
  16. package/dist/core/ConnectionPool.d.ts +125 -0
  17. package/dist/core/ConnectionPool.d.ts.map +1 -0
  18. package/dist/core/ConnectionPool.js +397 -0
  19. package/dist/core/ConnectionPool.js.map +1 -0
  20. package/dist/core/SSHClient.d.ts +112 -0
  21. package/dist/core/SSHClient.d.ts.map +1 -0
  22. package/dist/core/SSHClient.js +367 -0
  23. package/dist/core/SSHClient.js.map +1 -0
  24. package/dist/core/ServerManager.d.ts +80 -0
  25. package/dist/core/ServerManager.d.ts.map +1 -0
  26. package/dist/core/ServerManager.js +207 -0
  27. package/dist/core/ServerManager.js.map +1 -0
  28. package/dist/core/index.d.ts +8 -0
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +8 -0
  31. package/dist/core/index.js.map +1 -0
  32. package/dist/errors/AuthError.d.ts +30 -0
  33. package/dist/errors/AuthError.d.ts.map +1 -0
  34. package/dist/errors/AuthError.js +35 -0
  35. package/dist/errors/AuthError.js.map +1 -0
  36. package/dist/errors/BaseError.d.ts +17 -0
  37. package/dist/errors/BaseError.d.ts.map +1 -0
  38. package/dist/errors/BaseError.js +34 -0
  39. package/dist/errors/BaseError.js.map +1 -0
  40. package/dist/errors/ConfigurationError.d.ts +24 -0
  41. package/dist/errors/ConfigurationError.d.ts.map +1 -0
  42. package/dist/errors/ConfigurationError.js +24 -0
  43. package/dist/errors/ConfigurationError.js.map +1 -0
  44. package/dist/errors/PoolError.d.ts +21 -0
  45. package/dist/errors/PoolError.d.ts.map +1 -0
  46. package/dist/errors/PoolError.js +30 -0
  47. package/dist/errors/PoolError.js.map +1 -0
  48. package/dist/errors/SSHError.d.ts +24 -0
  49. package/dist/errors/SSHError.d.ts.map +1 -0
  50. package/dist/errors/SSHError.js +38 -0
  51. package/dist/errors/SSHError.js.map +1 -0
  52. package/dist/errors/StorageError.d.ts +24 -0
  53. package/dist/errors/StorageError.d.ts.map +1 -0
  54. package/dist/errors/StorageError.js +35 -0
  55. package/dist/errors/StorageError.js.map +1 -0
  56. package/dist/errors/ValidationError.d.ts +29 -0
  57. package/dist/errors/ValidationError.d.ts.map +1 -0
  58. package/dist/errors/ValidationError.js +35 -0
  59. package/dist/errors/ValidationError.js.map +1 -0
  60. package/dist/errors/index.d.ts +11 -0
  61. package/dist/errors/index.d.ts.map +1 -0
  62. package/dist/errors/index.js +18 -0
  63. package/dist/errors/index.js.map +1 -0
  64. package/dist/handlers/BaseHandler.d.ts +50 -0
  65. package/dist/handlers/BaseHandler.d.ts.map +1 -0
  66. package/dist/handlers/BaseHandler.js +87 -0
  67. package/dist/handlers/BaseHandler.js.map +1 -0
  68. package/dist/handlers/CommandHandler.d.ts +23 -0
  69. package/dist/handlers/CommandHandler.d.ts.map +1 -0
  70. package/dist/handlers/CommandHandler.js +99 -0
  71. package/dist/handlers/CommandHandler.js.map +1 -0
  72. package/dist/handlers/HealthHandler.d.ts +25 -0
  73. package/dist/handlers/HealthHandler.d.ts.map +1 -0
  74. package/dist/handlers/HealthHandler.js +51 -0
  75. package/dist/handlers/HealthHandler.js.map +1 -0
  76. package/dist/handlers/HelpHandler.d.ts +32 -0
  77. package/dist/handlers/HelpHandler.d.ts.map +1 -0
  78. package/dist/handlers/HelpHandler.js +76 -0
  79. package/dist/handlers/HelpHandler.js.map +1 -0
  80. package/dist/handlers/ServerHandler.d.ts +72 -0
  81. package/dist/handlers/ServerHandler.d.ts.map +1 -0
  82. package/dist/handlers/ServerHandler.js +272 -0
  83. package/dist/handlers/ServerHandler.js.map +1 -0
  84. package/dist/handlers/index.d.ts +9 -0
  85. package/dist/handlers/index.d.ts.map +1 -0
  86. package/dist/handlers/index.js +9 -0
  87. package/dist/handlers/index.js.map +1 -0
  88. package/dist/index.d.ts +10 -0
  89. package/dist/index.d.ts.map +1 -0
  90. package/dist/index.js +348 -0
  91. package/dist/index.js.map +1 -0
  92. package/dist/middleware/AuthMiddleware.d.ts +28 -0
  93. package/dist/middleware/AuthMiddleware.d.ts.map +1 -0
  94. package/dist/middleware/AuthMiddleware.js +49 -0
  95. package/dist/middleware/AuthMiddleware.js.map +1 -0
  96. package/dist/middleware/RateLimitMiddleware.d.ts +23 -0
  97. package/dist/middleware/RateLimitMiddleware.d.ts.map +1 -0
  98. package/dist/middleware/RateLimitMiddleware.js +34 -0
  99. package/dist/middleware/RateLimitMiddleware.js.map +1 -0
  100. package/dist/middleware/index.d.ts +6 -0
  101. package/dist/middleware/index.d.ts.map +1 -0
  102. package/dist/middleware/index.js +6 -0
  103. package/dist/middleware/index.js.map +1 -0
  104. package/dist/services/BackupService.d.ts +119 -0
  105. package/dist/services/BackupService.d.ts.map +1 -0
  106. package/dist/services/BackupService.js +313 -0
  107. package/dist/services/BackupService.js.map +1 -0
  108. package/dist/services/CryptoService.d.ts +37 -0
  109. package/dist/services/CryptoService.d.ts.map +1 -0
  110. package/dist/services/CryptoService.js +108 -0
  111. package/dist/services/CryptoService.js.map +1 -0
  112. package/dist/services/HealthService.d.ts +126 -0
  113. package/dist/services/HealthService.d.ts.map +1 -0
  114. package/dist/services/HealthService.js +213 -0
  115. package/dist/services/HealthService.js.map +1 -0
  116. package/dist/services/LoggingService.d.ts +115 -0
  117. package/dist/services/LoggingService.d.ts.map +1 -0
  118. package/dist/services/LoggingService.js +334 -0
  119. package/dist/services/LoggingService.js.map +1 -0
  120. package/dist/services/MonitoringService.d.ts +119 -0
  121. package/dist/services/MonitoringService.d.ts.map +1 -0
  122. package/dist/services/MonitoringService.js +267 -0
  123. package/dist/services/MonitoringService.js.map +1 -0
  124. package/dist/services/NotificationService.d.ts +132 -0
  125. package/dist/services/NotificationService.d.ts.map +1 -0
  126. package/dist/services/NotificationService.js +297 -0
  127. package/dist/services/NotificationService.js.map +1 -0
  128. package/dist/services/RateLimiter.d.ts +51 -0
  129. package/dist/services/RateLimiter.d.ts.map +1 -0
  130. package/dist/services/RateLimiter.js +141 -0
  131. package/dist/services/RateLimiter.js.map +1 -0
  132. package/dist/services/ValidationService.d.ts +49 -0
  133. package/dist/services/ValidationService.d.ts.map +1 -0
  134. package/dist/services/ValidationService.js +158 -0
  135. package/dist/services/ValidationService.js.map +1 -0
  136. package/dist/services/index.d.ts +12 -0
  137. package/dist/services/index.d.ts.map +1 -0
  138. package/dist/services/index.js +12 -0
  139. package/dist/services/index.js.map +1 -0
  140. package/dist/types/Bot.d.ts +63 -0
  141. package/dist/types/Bot.d.ts.map +1 -0
  142. package/dist/types/Bot.js +5 -0
  143. package/dist/types/Bot.js.map +1 -0
  144. package/dist/types/Config.d.ts +57 -0
  145. package/dist/types/Config.d.ts.map +1 -0
  146. package/dist/types/Config.js +5 -0
  147. package/dist/types/Config.js.map +1 -0
  148. package/dist/types/Errors.d.ts +37 -0
  149. package/dist/types/Errors.d.ts.map +1 -0
  150. package/dist/types/Errors.js +34 -0
  151. package/dist/types/Errors.js.map +1 -0
  152. package/dist/types/SSH.d.ts +56 -0
  153. package/dist/types/SSH.d.ts.map +1 -0
  154. package/dist/types/SSH.js +6 -0
  155. package/dist/types/SSH.js.map +1 -0
  156. package/dist/types/Server.d.ts +39 -0
  157. package/dist/types/Server.d.ts.map +1 -0
  158. package/dist/types/Server.js +5 -0
  159. package/dist/types/Server.js.map +1 -0
  160. package/dist/types/index.d.ts +10 -0
  161. package/dist/types/index.d.ts.map +1 -0
  162. package/dist/types/index.js +6 -0
  163. package/dist/types/index.js.map +1 -0
  164. package/dist/utils/commandUtils.d.ts +25 -0
  165. package/dist/utils/commandUtils.d.ts.map +1 -0
  166. package/dist/utils/commandUtils.js +94 -0
  167. package/dist/utils/commandUtils.js.map +1 -0
  168. package/dist/utils/fileUtils.d.ts +40 -0
  169. package/dist/utils/fileUtils.d.ts.map +1 -0
  170. package/dist/utils/fileUtils.js +114 -0
  171. package/dist/utils/fileUtils.js.map +1 -0
  172. package/dist/utils/index.d.ts +7 -0
  173. package/dist/utils/index.d.ts.map +1 -0
  174. package/dist/utils/index.js +7 -0
  175. package/dist/utils/index.js.map +1 -0
  176. package/dist/utils/pathUtils.d.ts +40 -0
  177. package/dist/utils/pathUtils.d.ts.map +1 -0
  178. package/dist/utils/pathUtils.js +140 -0
  179. package/dist/utils/pathUtils.js.map +1 -0
  180. package/package.json +31 -5
  181. package/scripts/build.sh +20 -0
  182. package/scripts/postinstall.js +87 -0
  183. package/scripts/release.sh +22 -0
  184. package/scripts/setup-env.js +237 -0
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Command sanitization utility
3
+ * Provides safe command execution by sanitizing and validating commands
4
+ */
5
+ /**
6
+ * Dangerous patterns that should be blocked or warned about
7
+ */
8
+ const DANGEROUS_PATTERNS = [
9
+ { pattern: /;\s*rm\s+-rf/i, description: "rm -rf chain" },
10
+ { pattern: /\|\s*rm\s+/i, description: "pipe to rm" },
11
+ { pattern: />\s*\/dev\//i, description: "device redirection" },
12
+ { pattern: /\$\([^)]+\)/, description: "command substitution" },
13
+ { pattern: /`[^`]+`/, description: "backtick execution" },
14
+ { pattern: /\$\{[^}]+\}/, description: "variable expansion" },
15
+ { pattern: /&&\s*rm/i, description: "chained rm" },
16
+ { pattern: /\|\|\s*rm/i, description: "or-chained rm" },
17
+ { pattern: />\s*\//i, description: "root file write" },
18
+ { pattern: /<\s*\//i, description: "root file read" },
19
+ { pattern: /sudo\s+/i, description: "sudo commands" },
20
+ { pattern: /chmod\s+777/i, description: "dangerous permissions" },
21
+ { pattern: /chown\s+.*:.*\s+\//i, description: "ownership changes" },
22
+ ];
23
+ /**
24
+ * Shell metacharacters that need escaping
25
+ */
26
+ const SHELL_METACHARACTERS = /[;&|`$\\]/g;
27
+ /**
28
+ * Sanitize a command for safe execution
29
+ */
30
+ export function sanitizeCommand(command) {
31
+ const warnings = [];
32
+ let sanitized = command.trim();
33
+ // Check for dangerous patterns
34
+ for (const { pattern, description } of DANGEROUS_PATTERNS) {
35
+ if (pattern.test(sanitized)) {
36
+ warnings.push(`Dangerous pattern detected: ${description}`);
37
+ }
38
+ }
39
+ // Remove null bytes
40
+ sanitized = sanitized.replace(/\0/g, "");
41
+ // Escape shell metacharacters for SSH
42
+ sanitized = sanitized.replace(SHELL_METACHARACTERS, "\\$&");
43
+ return {
44
+ original: command,
45
+ sanitized,
46
+ warnings,
47
+ isSafe: warnings.length === 0,
48
+ };
49
+ }
50
+ /**
51
+ * Validate a command for execution
52
+ */
53
+ export function validateCommand(command) {
54
+ if (!command || command.trim().length === 0) {
55
+ return { valid: false, error: "Command cannot be empty" };
56
+ }
57
+ if (command.length > 10000) {
58
+ return {
59
+ valid: false,
60
+ error: "Command is too long (max 10000 characters)",
61
+ };
62
+ }
63
+ const sanitized = sanitizeCommand(command);
64
+ // Block commands with dangerous patterns
65
+ if (sanitized.warnings.length > 0) {
66
+ return {
67
+ valid: false,
68
+ error: `Command contains dangerous patterns: ${sanitized.warnings.join(", ")}`,
69
+ };
70
+ }
71
+ return { valid: true, data: sanitized };
72
+ }
73
+ /**
74
+ * Parse command arguments safely
75
+ */
76
+ export function parseCommandArgs(input) {
77
+ const trimmed = input.trim();
78
+ const spaceIndex = trimmed.indexOf(" ");
79
+ if (spaceIndex === -1) {
80
+ return { command: trimmed, args: "" };
81
+ }
82
+ return {
83
+ command: trimmed.slice(0, spaceIndex),
84
+ args: trimmed.slice(spaceIndex + 1).trim(),
85
+ };
86
+ }
87
+ /**
88
+ * Escape a string for safe use in shell
89
+ */
90
+ export function escapeShellArg(arg) {
91
+ // Use single quotes and escape any existing single quotes
92
+ return `'${arg.replace(/'/g, "'\\''")}'`;
93
+ }
94
+ //# sourceMappingURL=commandUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandUtils.js","sourceRoot":"","sources":["../../src/utils/commandUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Async file operations utility
3
+ */
4
+ /**
5
+ * Check if a file exists
6
+ */
7
+ export declare function fileExists(filePath: string): Promise<boolean>;
8
+ /**
9
+ * Ensure a directory exists, create if it doesn't
10
+ */
11
+ export declare function ensureDir(dirPath: string): Promise<void>;
12
+ /**
13
+ * Read a file as string
14
+ */
15
+ export declare function readFile(filePath: string): Promise<string>;
16
+ /**
17
+ * Read a file as JSON
18
+ */
19
+ export declare function readJsonFile<T>(filePath: string): Promise<T>;
20
+ /**
21
+ * Write string to a file
22
+ */
23
+ export declare function writeFile(filePath: string, content: string): Promise<void>;
24
+ /**
25
+ * Write object as JSON to a file
26
+ */
27
+ export declare function writeJsonFile<T>(filePath: string, data: T, pretty?: boolean): Promise<void>;
28
+ /**
29
+ * Delete a file
30
+ */
31
+ export declare function deleteFile(filePath: string): Promise<void>;
32
+ /**
33
+ * Get file stats
34
+ */
35
+ export declare function getFileStats(filePath: string): Promise<{
36
+ size: number;
37
+ createdAt: Date;
38
+ modifiedAt: Date;
39
+ }>;
40
+ //# sourceMappingURL=fileUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUtils.d.ts","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAUH;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9D;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAUlE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,CAAC,EACP,MAAM,GAAE,OAAc,GACrB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYhE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,CAAC;CAClB,CAAC,CAiBD"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Async file operations utility
3
+ */
4
+ import { promises as fs } from "fs";
5
+ import * as path from "path";
6
+ import { FileNotFoundError, FileReadError, FileWriteError, } from "../errors/index.js";
7
+ /**
8
+ * Check if a file exists
9
+ */
10
+ export async function fileExists(filePath) {
11
+ try {
12
+ await fs.access(filePath);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * Ensure a directory exists, create if it doesn't
21
+ */
22
+ export async function ensureDir(dirPath) {
23
+ try {
24
+ await fs.mkdir(dirPath, { recursive: true });
25
+ }
26
+ catch (error) {
27
+ throw new FileWriteError(dirPath, error instanceof Error ? error : new Error(String(error)));
28
+ }
29
+ }
30
+ /**
31
+ * Read a file as string
32
+ */
33
+ export async function readFile(filePath) {
34
+ try {
35
+ const content = await fs.readFile(filePath, "utf-8");
36
+ return content;
37
+ }
38
+ catch (error) {
39
+ if (error.code === "ENOENT") {
40
+ throw new FileNotFoundError(filePath);
41
+ }
42
+ throw new FileReadError(filePath, error instanceof Error ? error : new Error(String(error)));
43
+ }
44
+ }
45
+ /**
46
+ * Read a file as JSON
47
+ */
48
+ export async function readJsonFile(filePath) {
49
+ const content = await readFile(filePath);
50
+ try {
51
+ return JSON.parse(content);
52
+ }
53
+ catch (error) {
54
+ throw new FileReadError(filePath, error instanceof Error ? error : new Error(String(error)));
55
+ }
56
+ }
57
+ /**
58
+ * Write string to a file
59
+ */
60
+ export async function writeFile(filePath, content) {
61
+ try {
62
+ // Ensure parent directory exists
63
+ const dir = path.dirname(filePath);
64
+ await ensureDir(dir);
65
+ await fs.writeFile(filePath, content, "utf-8");
66
+ }
67
+ catch (error) {
68
+ if (error instanceof FileNotFoundError || error instanceof FileWriteError) {
69
+ throw error;
70
+ }
71
+ throw new FileWriteError(filePath, error instanceof Error ? error : new Error(String(error)));
72
+ }
73
+ }
74
+ /**
75
+ * Write object as JSON to a file
76
+ */
77
+ export async function writeJsonFile(filePath, data, pretty = true) {
78
+ const content = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
79
+ await writeFile(filePath, content);
80
+ }
81
+ /**
82
+ * Delete a file
83
+ */
84
+ export async function deleteFile(filePath) {
85
+ try {
86
+ await fs.unlink(filePath);
87
+ }
88
+ catch (error) {
89
+ if (error.code === "ENOENT") {
90
+ throw new FileNotFoundError(filePath);
91
+ }
92
+ throw new FileWriteError(filePath, error instanceof Error ? error : new Error(String(error)));
93
+ }
94
+ }
95
+ /**
96
+ * Get file stats
97
+ */
98
+ export async function getFileStats(filePath) {
99
+ try {
100
+ const stats = await fs.stat(filePath);
101
+ return {
102
+ size: stats.size,
103
+ createdAt: stats.birthtime,
104
+ modifiedAt: stats.mtime,
105
+ };
106
+ }
107
+ catch (error) {
108
+ if (error.code === "ENOENT") {
109
+ throw new FileNotFoundError(filePath);
110
+ }
111
+ throw new FileReadError(filePath, error instanceof Error ? error : new Error(String(error)));
112
+ }
113
+ }
114
+ //# sourceMappingURL=fileUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileUtils.js","sourceRoot":"","sources":["../../src/utils/fileUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Utility modules index - exports all utilities
3
+ */
4
+ export * from "./commandUtils.js";
5
+ export * from "./fileUtils.js";
6
+ export * from "./pathUtils.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Utility modules index - exports all utilities
3
+ */
4
+ export * from "./commandUtils.js";
5
+ export * from "./fileUtils.js";
6
+ export * from "./pathUtils.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Path validation utility
3
+ * Provides safe path handling and traversal prevention
4
+ */
5
+ import type { ValidationResult } from "../types/index.js";
6
+ /**
7
+ * Validate a path for safe file operations
8
+ */
9
+ export declare function validatePath(inputPath: string, basePath?: string): ValidationResult<string>;
10
+ /**
11
+ * Validate a host address
12
+ */
13
+ export declare function validateHost(host: string): ValidationResult<string>;
14
+ /**
15
+ * Validate a port number
16
+ */
17
+ export declare function validatePort(port: number): ValidationResult<number>;
18
+ /**
19
+ * Parse and validate a port from string
20
+ */
21
+ export declare function parsePort(portStr: string): ValidationResult<number>;
22
+ /**
23
+ * Get the directory name from a path
24
+ */
25
+ export declare function getDirName(filePath: string): string;
26
+ /**
27
+ * Get the base name from a path
28
+ */
29
+ export declare function getBaseName(filePath: string): string;
30
+ /**
31
+ * Join path segments safely
32
+ */
33
+ export declare function joinPaths(...segments: string[]): string;
34
+ /**
35
+ * Expand tilde (~) in path to home directory
36
+ * @param inputPath - Path that may contain tilde
37
+ * @returns Path with tilde expanded to home directory
38
+ */
39
+ export declare function expandTilde(inputPath: string): string;
40
+ //# sourceMappingURL=pathUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathUtils.d.ts","sourceRoot":"","sources":["../../src/utils/pathUtils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AA2B1D;;GAEG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAChB,gBAAgB,CAAC,MAAM,CAAC,CAgC1B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAgCnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAUnE;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAQnE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CASrD"}
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Path validation utility
3
+ * Provides safe path handling and traversal prevention
4
+ */
5
+ import * as path from "path";
6
+ /**
7
+ * Allowed base paths for file operations
8
+ */
9
+ const ALLOWED_PATHS = [
10
+ "/home",
11
+ "/var/log",
12
+ "/var/www",
13
+ "/etc/nginx",
14
+ "/etc/systemd",
15
+ "/opt",
16
+ "/tmp",
17
+ ];
18
+ /**
19
+ * Forbidden paths that should never be accessed
20
+ */
21
+ const FORBIDDEN_PATHS = [
22
+ "/etc/shadow",
23
+ "/etc/passwd",
24
+ "/root/.ssh",
25
+ "/etc/ssh",
26
+ "/proc",
27
+ "/sys",
28
+ ];
29
+ /**
30
+ * Validate a path for safe file operations
31
+ */
32
+ export function validatePath(inputPath, basePath) {
33
+ // Resolve the path
34
+ const resolved = path.resolve(basePath || "/", inputPath);
35
+ const normalized = path.normalize(resolved);
36
+ // Check for path traversal attempts
37
+ if (inputPath.includes("..")) {
38
+ return { valid: false, error: "Path traversal detected" };
39
+ }
40
+ // Check for null bytes
41
+ if (inputPath.includes("\0")) {
42
+ return { valid: false, error: "Invalid null byte in path" };
43
+ }
44
+ // Check forbidden paths
45
+ for (const forbidden of FORBIDDEN_PATHS) {
46
+ if (normalized.startsWith(forbidden)) {
47
+ return { valid: false, error: "Access to path is forbidden" };
48
+ }
49
+ }
50
+ // Check allowed paths (if whitelist mode)
51
+ const isAllowed = ALLOWED_PATHS.some((allowed) => normalized.startsWith(allowed));
52
+ if (!isAllowed) {
53
+ return { valid: false, error: "Path is not in allowed list" };
54
+ }
55
+ return { valid: true, data: normalized };
56
+ }
57
+ /**
58
+ * Validate a host address
59
+ */
60
+ export function validateHost(host) {
61
+ if (!host || host.trim().length === 0) {
62
+ return { valid: false, error: "Host cannot be empty" };
63
+ }
64
+ const trimmed = host.trim();
65
+ // Check for valid hostname or IP format
66
+ const hostnameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/;
67
+ const ipv4Regex = /^(\d{1,3}\.){3}\d{1,3}$/;
68
+ const ipv6Regex = /^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;
69
+ const isValidHost = hostnameRegex.test(trimmed) ||
70
+ ipv4Regex.test(trimmed) ||
71
+ ipv6Regex.test(trimmed);
72
+ if (!isValidHost) {
73
+ return { valid: false, error: "Invalid host format" };
74
+ }
75
+ // Validate IPv4 octets if it's an IPv4 address
76
+ if (ipv4Regex.test(trimmed)) {
77
+ const octets = trimmed.split(".").map(Number);
78
+ const validOctets = octets.every((octet) => octet >= 0 && octet <= 255);
79
+ if (!validOctets) {
80
+ return { valid: false, error: "Invalid IPv4 address" };
81
+ }
82
+ }
83
+ return { valid: true, data: trimmed };
84
+ }
85
+ /**
86
+ * Validate a port number
87
+ */
88
+ export function validatePort(port) {
89
+ if (!Number.isInteger(port)) {
90
+ return { valid: false, error: "Port must be an integer" };
91
+ }
92
+ if (port < 1 || port > 65535) {
93
+ return { valid: false, error: "Port must be between 1 and 65535" };
94
+ }
95
+ return { valid: true, data: port };
96
+ }
97
+ /**
98
+ * Parse and validate a port from string
99
+ */
100
+ export function parsePort(portStr) {
101
+ const parsed = parseInt(portStr, 10);
102
+ if (isNaN(parsed)) {
103
+ return { valid: false, error: "Invalid port number" };
104
+ }
105
+ return validatePort(parsed);
106
+ }
107
+ /**
108
+ * Get the directory name from a path
109
+ */
110
+ export function getDirName(filePath) {
111
+ return path.dirname(filePath);
112
+ }
113
+ /**
114
+ * Get the base name from a path
115
+ */
116
+ export function getBaseName(filePath) {
117
+ return path.basename(filePath);
118
+ }
119
+ /**
120
+ * Join path segments safely
121
+ */
122
+ export function joinPaths(...segments) {
123
+ return path.join(...segments);
124
+ }
125
+ /**
126
+ * Expand tilde (~) in path to home directory
127
+ * @param inputPath - Path that may contain tilde
128
+ * @returns Path with tilde expanded to home directory
129
+ */
130
+ export function expandTilde(inputPath) {
131
+ if (inputPath.startsWith("~/")) {
132
+ const home = process.env.HOME ?? "/root";
133
+ return path.join(home, inputPath.slice(2));
134
+ }
135
+ if (inputPath === "~") {
136
+ return process.env.HOME ?? "/root";
137
+ }
138
+ return inputPath;
139
+ }
140
+ //# sourceMappingURL=pathUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathUtils.js","sourceRoot":"","sources":["../../src/utils/pathUtils.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,25 +1,51 @@
1
1
  {
2
2
  "name": "telegram-ssh-bot",
3
- "version": "2.0.0",
3
+ "version": "2.2.0",
4
+ "description": "A Telegram bot for secure SSH server management and remote command execution",
4
5
  "type": "module",
5
6
  "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "author": "farhanzzg",
15
+ "license": "MIT",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/farhanzzg/telegram-ssh.git"
19
+ },
20
+ "bugs": {
21
+ "url": "https://github.com/farhanzzg/telegram-ssh/issues"
22
+ },
23
+ "homepage": "https://github.com/farhanzzg/telegram-ssh#readme",
6
24
  "bin": {
7
25
  "telegram-ssh-bot": "./dist/index.js"
8
26
  },
9
27
  "files": [
10
28
  "dist/**/*",
11
- "README.md",
12
- "LICENSE"
29
+ "scripts/**/*",
30
+ "deploy/.env.example",
31
+ "README.md"
13
32
  ],
14
33
  "engines": {
15
34
  "node": ">=18.0.0"
16
35
  },
17
36
  "keywords": [
18
37
  "telegram",
38
+ "telegram-bot",
19
39
  "ssh",
40
+ "ssh-client",
20
41
  "bot",
21
42
  "remote",
22
- "server-management"
43
+ "server-management",
44
+ "server-administration",
45
+ "devops",
46
+ "remote-access",
47
+ "command-execution",
48
+ "terminal"
23
49
  ],
24
50
  "pkg": {
25
51
  "scripts": "dist/**/*.js",
@@ -54,7 +80,7 @@
54
80
  "start": "node dist/index.js",
55
81
  "dev": "tsc --watch",
56
82
  "clean": "rm -rf dist",
57
- "postinstall": "node -e \"console.log('Telegram SSH Bot installed. Run: telegram-ssh-bot')\"",
83
+ "postinstall": "node scripts/postinstall.js",
58
84
  "build:binary": "npm run build && pkg .",
59
85
  "build:binary:linux": "npm run build && pkg . --targets node18-linux-x64",
60
86
  "build:binary:macos": "npm run build && pkg . --targets node18-macos-x64",
@@ -0,0 +1,20 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "Building Telegram SSH Bot..."
5
+
6
+ # Clean previous builds
7
+ rm -rf dist build
8
+
9
+ # Compile TypeScript
10
+ echo "Compiling TypeScript..."
11
+ npm run build
12
+
13
+ # Create build directory
14
+ mkdir -p build
15
+
16
+ # Build binaries for current platform
17
+ echo "Creating binary executable..."
18
+ npx pkg . --targets node18-linux-x64 --output build/telegram-ssh-bot
19
+
20
+ echo "Build complete! Binary available at: build/telegram-ssh-bot"
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install script for npm/pnpm global installation
4
+ * Sets up the .env configuration file if it doesn't exist
5
+ */
6
+
7
+ import { envFileExists, main } from "./setup-env.js";
8
+
9
+ /**
10
+ * Check if this is a global installation
11
+ * @returns {boolean} True if running as a global install
12
+ */
13
+ function isGlobalInstall() {
14
+ // Check various npm config indicators for global install
15
+ const npmConfigGlobal = process.env.npm_config_global;
16
+ const npmPackageConfig = process.env.npm_package_config;
17
+
18
+ // npm_config_global is 'true' when installed with -g flag
19
+ if (npmConfigGlobal === "true") {
20
+ return true;
21
+ }
22
+
23
+ // Check if we're in a global node_modules directory
24
+ // This is a heuristic that works for most cases
25
+ const cwd = process.cwd();
26
+ if (
27
+ cwd.includes("node_modules") &&
28
+ (cwd.includes("/usr/local") ||
29
+ cwd.includes("/usr/lib") ||
30
+ cwd.includes("/lib/node_modules") ||
31
+ cwd.includes(".npm-global") ||
32
+ cwd.includes(".pnpm-global"))
33
+ ) {
34
+ return true;
35
+ }
36
+
37
+ // Check for pnpm global install
38
+ if (
39
+ process.env.npm_config_user_agent &&
40
+ process.env.npm_config_user_agent.includes("pnpm")
41
+ ) {
42
+ // pnpm sets different paths for global installs
43
+ if (cwd.includes("pnpm-global") || cwd.includes(".pnpm-global")) {
44
+ return true;
45
+ }
46
+ }
47
+
48
+ return false;
49
+ }
50
+
51
+ /**
52
+ * Run the postinstall script
53
+ */
54
+ function runPostinstall() {
55
+ // Only run for global installations
56
+ if (!isGlobalInstall()) {
57
+ console.log("Local installation detected. Skipping .env setup.");
58
+ console.log(
59
+ "For global installation, the .env file would be created at ~/.config/telegram-ssh-bot/.env",
60
+ );
61
+ return;
62
+ }
63
+
64
+ console.log("Global installation detected. Setting up configuration...");
65
+
66
+ // Check if .env already exists
67
+ if (envFileExists()) {
68
+ console.log("Configuration file already exists. Skipping setup.");
69
+ console.log("Configuration location: ~/.config/telegram-ssh-bot/.env");
70
+ return;
71
+ }
72
+
73
+ // Run the main setup function
74
+ const result = main({ generateKey: true, silent: false });
75
+
76
+ if (result.success) {
77
+ console.log("\nConfiguration setup complete!");
78
+ console.log(
79
+ 'Run "telegram-ssh-bot" to start the bot after configuring your credentials.',
80
+ );
81
+ } else {
82
+ console.error("Configuration setup failed:", result.message);
83
+ }
84
+ }
85
+
86
+ // Run the postinstall script
87
+ runPostinstall();