typescript-virtual-container 1.5.3 → 1.5.5

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 (371) hide show
  1. package/README.md +44 -532
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/SSHMimic/executor.js +23 -5
  4. package/dist/VirtualPackageManager/index.js +10 -0
  5. package/dist/VirtualShell/shell.js +158 -11
  6. package/dist/commands/basename.d.ts +13 -0
  7. package/dist/commands/basename.js +45 -0
  8. package/dist/commands/bc.d.ts +2 -0
  9. package/dist/commands/bc.js +28 -0
  10. package/dist/commands/file.d.ts +8 -0
  11. package/dist/commands/file.js +57 -0
  12. package/dist/commands/fun.d.ts +32 -0
  13. package/dist/commands/fun.js +172 -0
  14. package/dist/commands/ip.d.ts +7 -0
  15. package/dist/commands/ip.js +52 -0
  16. package/dist/commands/jobs.d.ts +4 -0
  17. package/dist/commands/jobs.js +27 -0
  18. package/dist/commands/last.d.ts +13 -0
  19. package/dist/commands/last.js +68 -0
  20. package/dist/commands/manuals-bundle.js +598 -6
  21. package/dist/commands/registry.js +30 -2
  22. package/dist/commands/runtime.js +24 -3
  23. package/dist/commands/set.js +20 -0
  24. package/dist/commands/sh.js +74 -1
  25. package/dist/commands/tput.d.ts +13 -0
  26. package/dist/commands/tput.js +76 -0
  27. package/dist/commands/w.d.ts +7 -0
  28. package/dist/commands/w.js +38 -0
  29. package/dist/utils/expand.d.ts +12 -0
  30. package/dist/utils/expand.js +87 -1
  31. package/package.json +9 -3
  32. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
  33. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -31
  34. package/.github/dependabot.yml +0 -27
  35. package/.github/pull_request_template.md +0 -21
  36. package/.github/workflows/create-pull-request.yml +0 -85
  37. package/.github/workflows/publish.yml +0 -25
  38. package/.github/workflows/test-battery.yml +0 -102
  39. package/.vscode/settings.json +0 -20
  40. package/CODE_OF_CONDUCT.md +0 -39
  41. package/CONTRIBUTING.md +0 -59
  42. package/HONEYPOT.md +0 -358
  43. package/SECURITY.md +0 -33
  44. package/benchmark-results.txt +0 -40
  45. package/benchmark-virtualshell.ts +0 -88
  46. package/biome.json +0 -37
  47. package/build.js +0 -22
  48. package/builds/fortune-nyx-v1.5.3-directbash-k6.1.0.mjs +0 -1764
  49. package/builds/fortune-nyx-v1.5.3-ssh-nosftp.js +0 -1764
  50. package/builds/fortune-nyx-v1.5.3-ssh.cjs +0 -1765
  51. package/builds/fortune-nyx-v1.5.3-web.min.js +0 -17036
  52. package/bun.lock +0 -244
  53. package/docs/.nojekyll +0 -1
  54. package/docs/app.js +0 -1751
  55. package/docs/assets/hierarchy.js +0 -1
  56. package/docs/assets/highlight.css +0 -162
  57. package/docs/assets/icons.js +0 -18
  58. package/docs/assets/icons.svg +0 -1
  59. package/docs/assets/main.js +0 -60
  60. package/docs/assets/navigation.js +0 -1
  61. package/docs/assets/search.js +0 -1
  62. package/docs/assets/style.css +0 -1633
  63. package/docs/classes/HoneyPot.html +0 -31
  64. package/docs/classes/IdleManager.html +0 -162
  65. package/docs/classes/SshClient.html +0 -66
  66. package/docs/classes/VirtualFileSystem.html +0 -279
  67. package/docs/classes/VirtualPackageManager.html +0 -63
  68. package/docs/classes/VirtualSftpServer.html +0 -169
  69. package/docs/classes/VirtualShell.html +0 -285
  70. package/docs/classes/VirtualSshServer.html +0 -182
  71. package/docs/classes/VirtualUserManager.html +0 -276
  72. package/docs/demo.html +0 -82
  73. package/docs/functions/assertDiff.html +0 -6
  74. package/docs/functions/diffSnapshots.html +0 -7
  75. package/docs/functions/formatDiff.html +0 -6
  76. package/docs/functions/getArg.html +0 -13
  77. package/docs/functions/getFlag.html +0 -15
  78. package/docs/functions/ifFlag.html +0 -11
  79. package/docs/hierarchy.html +0 -1
  80. package/docs/index.html +0 -1869
  81. package/docs/interfaces/AuditLogEntry.html +0 -6
  82. package/docs/interfaces/CommandContext.html +0 -22
  83. package/docs/interfaces/CommandResult.html +0 -26
  84. package/docs/interfaces/ExecStream.html +0 -11
  85. package/docs/interfaces/HoneyPotStats.html +0 -16
  86. package/docs/interfaces/IdleManagerOptions.html +0 -7
  87. package/docs/interfaces/InstalledPackage.html +0 -20
  88. package/docs/interfaces/NanoEditorSession.html +0 -8
  89. package/docs/interfaces/PackageDefinition.html +0 -30
  90. package/docs/interfaces/PackageFile.html +0 -8
  91. package/docs/interfaces/PasswordChallenge.html +0 -16
  92. package/docs/interfaces/RemoveOptions.html +0 -4
  93. package/docs/interfaces/ShellEnv.html +0 -6
  94. package/docs/interfaces/ShellModule.html +0 -14
  95. package/docs/interfaces/ShellProperties.html +0 -14
  96. package/docs/interfaces/ShellStream.html +0 -11
  97. package/docs/interfaces/SudoChallenge.html +0 -24
  98. package/docs/interfaces/VfsBaseNode.html +0 -12
  99. package/docs/interfaces/VfsDiff.html +0 -10
  100. package/docs/interfaces/VfsDiffEntry.html +0 -6
  101. package/docs/interfaces/VfsDiffModified.html +0 -10
  102. package/docs/interfaces/VfsDirectoryNode.html +0 -15
  103. package/docs/interfaces/VfsFileNode.html +0 -17
  104. package/docs/interfaces/VfsOptions.html +0 -26
  105. package/docs/interfaces/VfsSnapshot.html +0 -3
  106. package/docs/interfaces/VfsSnapshotBaseNode.html +0 -8
  107. package/docs/interfaces/VfsSnapshotDirectoryNode.html +0 -10
  108. package/docs/interfaces/VfsSnapshotFileNode.html +0 -12
  109. package/docs/interfaces/VirtualActiveSession.html +0 -12
  110. package/docs/interfaces/VirtualSftpServerOptions.html +0 -7
  111. package/docs/interfaces/VirtualShellVfsLike.html +0 -15
  112. package/docs/interfaces/VirtualShellVfsOptions.html +0 -3
  113. package/docs/interfaces/WriteFileOptions.html +0 -6
  114. package/docs/media/LICENSE +0 -21
  115. package/docs/modules.html +0 -1
  116. package/docs/types/ArgParseOptions.html +0 -4
  117. package/docs/types/CommandMode.html +0 -2
  118. package/docs/types/CommandOutcome.html +0 -2
  119. package/docs/types/IdleState.html +0 -1
  120. package/docs/types/VfsNodeStats.html +0 -2
  121. package/docs/types/VfsNodeType.html +0 -2
  122. package/docs/types/VfsPersistenceMode.html +0 -5
  123. package/docs/types/VfsSnapshotNode.html +0 -2
  124. package/examples/README.md +0 -288
  125. package/examples/app.js +0 -1751
  126. package/examples/app.ts +0 -299
  127. package/examples/build.js +0 -27
  128. package/examples/demo.html +0 -33
  129. package/examples/honeypot-audit.ts +0 -180
  130. package/examples/honeypot-export.ts +0 -253
  131. package/examples/honeypot-quickstart.ts +0 -110
  132. package/examples/index.html +0 -82
  133. package/examples/server.js +0 -55
  134. package/polyfills/buffer.js +0 -117
  135. package/polyfills/node_child_process/index.js +0 -2
  136. package/polyfills/node_crypto/index.js +0 -167
  137. package/polyfills/node_events/index.js +0 -9
  138. package/polyfills/node_fs/index.js +0 -202
  139. package/polyfills/node_fs/promises.js +0 -4
  140. package/polyfills/node_os/index.js +0 -9
  141. package/polyfills/node_path/index.js +0 -28
  142. package/polyfills/node_vm/index.js +0 -7
  143. package/polyfills/node_zlib/index.js +0 -3
  144. package/polyfills/process.js +0 -14
  145. package/polyfills/ssh2/index.js +0 -75
  146. package/scripts/build-all.mjs +0 -226
  147. package/scripts/build-names.mjs +0 -43
  148. package/scripts/generate-manuals-bundle.mjs +0 -49
  149. package/scripts/postinstall.js +0 -42
  150. package/scripts/publish-package.sh +0 -70
  151. package/src/Honeypot/index.ts +0 -457
  152. package/src/SSHClient/index.ts +0 -270
  153. package/src/SSHMimic/exec.ts +0 -49
  154. package/src/SSHMimic/executor.ts +0 -251
  155. package/src/SSHMimic/hostKey.ts +0 -21
  156. package/src/SSHMimic/index.ts +0 -337
  157. package/src/SSHMimic/loginBanner.ts +0 -36
  158. package/src/SSHMimic/loginFormat.ts +0 -10
  159. package/src/SSHMimic/prompt.ts +0 -14
  160. package/src/SSHMimic/sftp.ts +0 -883
  161. package/src/VirtualFileSystem/binaryPack.ts +0 -258
  162. package/src/VirtualFileSystem/index.ts +0 -1193
  163. package/src/VirtualFileSystem/internalTypes.ts +0 -43
  164. package/src/VirtualFileSystem/journal.ts +0 -171
  165. package/src/VirtualFileSystem/path.ts +0 -74
  166. package/src/VirtualPackageManager/index.ts +0 -996
  167. package/src/VirtualShell/idleManager.ts +0 -137
  168. package/src/VirtualShell/index.ts +0 -475
  169. package/src/VirtualShell/shell.ts +0 -700
  170. package/src/VirtualShell/shellParser.ts +0 -285
  171. package/src/VirtualUserManager/index.ts +0 -758
  172. package/src/bun.d.ts +0 -1
  173. package/src/commands/adduser.ts +0 -103
  174. package/src/commands/alias.ts +0 -69
  175. package/src/commands/apt.ts +0 -233
  176. package/src/commands/awk.ts +0 -168
  177. package/src/commands/base64.ts +0 -29
  178. package/src/commands/cat.ts +0 -52
  179. package/src/commands/cd.ts +0 -25
  180. package/src/commands/chmod.ts +0 -85
  181. package/src/commands/clear.ts +0 -15
  182. package/src/commands/command-helpers.ts +0 -286
  183. package/src/commands/cp.ts +0 -83
  184. package/src/commands/curl.ts +0 -147
  185. package/src/commands/cut.ts +0 -36
  186. package/src/commands/date.ts +0 -30
  187. package/src/commands/declare.ts +0 -49
  188. package/src/commands/deluser.ts +0 -98
  189. package/src/commands/df.ts +0 -23
  190. package/src/commands/diff.ts +0 -43
  191. package/src/commands/dpkg.ts +0 -180
  192. package/src/commands/du.ts +0 -56
  193. package/src/commands/echo.ts +0 -58
  194. package/src/commands/env.ts +0 -23
  195. package/src/commands/exit.ts +0 -18
  196. package/src/commands/export.ts +0 -34
  197. package/src/commands/find.ts +0 -68
  198. package/src/commands/free.ts +0 -47
  199. package/src/commands/grep.ts +0 -116
  200. package/src/commands/groups.ts +0 -19
  201. package/src/commands/gzip.ts +0 -88
  202. package/src/commands/head.ts +0 -52
  203. package/src/commands/help.ts +0 -152
  204. package/src/commands/helpers.ts +0 -234
  205. package/src/commands/history.ts +0 -34
  206. package/src/commands/hostname.ts +0 -14
  207. package/src/commands/htop.ts +0 -20
  208. package/src/commands/id.ts +0 -19
  209. package/src/commands/index.ts +0 -9
  210. package/src/commands/kill.ts +0 -19
  211. package/src/commands/ln.ts +0 -71
  212. package/src/commands/ls.ts +0 -243
  213. package/src/commands/lsb-release.ts +0 -63
  214. package/src/commands/man.ts +0 -31
  215. package/src/commands/manuals/adduser.txt +0 -11
  216. package/src/commands/manuals/apt-cache.txt +0 -12
  217. package/src/commands/manuals/apt.txt +0 -20
  218. package/src/commands/manuals/awk.txt +0 -13
  219. package/src/commands/manuals/cat.txt +0 -14
  220. package/src/commands/manuals/cd.txt +0 -16
  221. package/src/commands/manuals/chmod.txt +0 -16
  222. package/src/commands/manuals/clear.txt +0 -10
  223. package/src/commands/manuals/cp.txt +0 -10
  224. package/src/commands/manuals/curl.txt +0 -20
  225. package/src/commands/manuals/date.txt +0 -14
  226. package/src/commands/manuals/declare.txt +0 -12
  227. package/src/commands/manuals/deluser.txt +0 -10
  228. package/src/commands/manuals/df.txt +0 -10
  229. package/src/commands/manuals/dpkg-query.txt +0 -11
  230. package/src/commands/manuals/dpkg.txt +0 -14
  231. package/src/commands/manuals/du.txt +0 -11
  232. package/src/commands/manuals/echo.txt +0 -11
  233. package/src/commands/manuals/false.txt +0 -10
  234. package/src/commands/manuals/find.txt +0 -11
  235. package/src/commands/manuals/free.txt +0 -12
  236. package/src/commands/manuals/grep.txt +0 -13
  237. package/src/commands/manuals/groups.txt +0 -10
  238. package/src/commands/manuals/gzip.txt +0 -11
  239. package/src/commands/manuals/head.txt +0 -10
  240. package/src/commands/manuals/help.txt +0 -11
  241. package/src/commands/manuals/history.txt +0 -11
  242. package/src/commands/manuals/hostname.txt +0 -10
  243. package/src/commands/manuals/id.txt +0 -10
  244. package/src/commands/manuals/kill.txt +0 -13
  245. package/src/commands/manuals/ls.txt +0 -20
  246. package/src/commands/manuals/lsb_release.txt +0 -14
  247. package/src/commands/manuals/mkdir.txt +0 -10
  248. package/src/commands/manuals/mv.txt +0 -10
  249. package/src/commands/manuals/nano.txt +0 -11
  250. package/src/commands/manuals/neofetch.txt +0 -10
  251. package/src/commands/manuals/node.txt +0 -13
  252. package/src/commands/manuals/npm.txt +0 -13
  253. package/src/commands/manuals/npx.txt +0 -13
  254. package/src/commands/manuals/passwd.txt +0 -11
  255. package/src/commands/manuals/ping.txt +0 -10
  256. package/src/commands/manuals/printf.txt +0 -11
  257. package/src/commands/manuals/ps.txt +0 -10
  258. package/src/commands/manuals/pwd.txt +0 -10
  259. package/src/commands/manuals/python3.txt +0 -13
  260. package/src/commands/manuals/readlink.txt +0 -10
  261. package/src/commands/manuals/return.txt +0 -10
  262. package/src/commands/manuals/rm.txt +0 -10
  263. package/src/commands/manuals/sed.txt +0 -11
  264. package/src/commands/manuals/set.txt +0 -11
  265. package/src/commands/manuals/shift.txt +0 -10
  266. package/src/commands/manuals/sleep.txt +0 -10
  267. package/src/commands/manuals/sort.txt +0 -12
  268. package/src/commands/manuals/source.txt +0 -11
  269. package/src/commands/manuals/ssh.txt +0 -11
  270. package/src/commands/manuals/stat.txt +0 -10
  271. package/src/commands/manuals/su.txt +0 -13
  272. package/src/commands/manuals/sudo.txt +0 -11
  273. package/src/commands/manuals/tail.txt +0 -10
  274. package/src/commands/manuals/tar.txt +0 -19
  275. package/src/commands/manuals/tee.txt +0 -10
  276. package/src/commands/manuals/test.txt +0 -11
  277. package/src/commands/manuals/touch.txt +0 -11
  278. package/src/commands/manuals/tr.txt +0 -10
  279. package/src/commands/manuals/trap.txt +0 -10
  280. package/src/commands/manuals/true.txt +0 -10
  281. package/src/commands/manuals/type.txt +0 -10
  282. package/src/commands/manuals/uname.txt +0 -12
  283. package/src/commands/manuals/uniq.txt +0 -12
  284. package/src/commands/manuals/unset.txt +0 -10
  285. package/src/commands/manuals/uptime.txt +0 -11
  286. package/src/commands/manuals/wc.txt +0 -12
  287. package/src/commands/manuals/wget.txt +0 -12
  288. package/src/commands/manuals/which.txt +0 -10
  289. package/src/commands/manuals/whoami.txt +0 -10
  290. package/src/commands/manuals/xargs.txt +0 -10
  291. package/src/commands/manuals-bundle.ts +0 -898
  292. package/src/commands/mkdir.ts +0 -31
  293. package/src/commands/mv.ts +0 -50
  294. package/src/commands/nano.ts +0 -38
  295. package/src/commands/neofetch.ts +0 -53
  296. package/src/commands/node.ts +0 -341
  297. package/src/commands/npm.ts +0 -132
  298. package/src/commands/passwd.ts +0 -50
  299. package/src/commands/ping.ts +0 -32
  300. package/src/commands/printf.ts +0 -129
  301. package/src/commands/ps.ts +0 -58
  302. package/src/commands/pwd.ts +0 -9
  303. package/src/commands/python.ts +0 -2229
  304. package/src/commands/read.ts +0 -46
  305. package/src/commands/registry.ts +0 -249
  306. package/src/commands/rm.ts +0 -42
  307. package/src/commands/runtime.ts +0 -421
  308. package/src/commands/sed.ts +0 -68
  309. package/src/commands/seq.ts +0 -43
  310. package/src/commands/set.ts +0 -29
  311. package/src/commands/sh.ts +0 -467
  312. package/src/commands/shift.ts +0 -63
  313. package/src/commands/sleep.ts +0 -20
  314. package/src/commands/sort.ts +0 -46
  315. package/src/commands/source.ts +0 -52
  316. package/src/commands/stat.ts +0 -61
  317. package/src/commands/su.ts +0 -72
  318. package/src/commands/sudo.ts +0 -76
  319. package/src/commands/tail.ts +0 -53
  320. package/src/commands/tar.ts +0 -102
  321. package/src/commands/tee.ts +0 -36
  322. package/src/commands/test.ts +0 -137
  323. package/src/commands/touch.ts +0 -28
  324. package/src/commands/tr.ts +0 -70
  325. package/src/commands/tree.ts +0 -20
  326. package/src/commands/true.ts +0 -27
  327. package/src/commands/type.ts +0 -48
  328. package/src/commands/uname.ts +0 -29
  329. package/src/commands/uniq.ts +0 -39
  330. package/src/commands/unset.ts +0 -17
  331. package/src/commands/uptime.ts +0 -54
  332. package/src/commands/wc.ts +0 -55
  333. package/src/commands/wget.ts +0 -148
  334. package/src/commands/which.ts +0 -37
  335. package/src/commands/who.ts +0 -25
  336. package/src/commands/whoami.ts +0 -14
  337. package/src/commands/xargs.ts +0 -31
  338. package/src/index.ts +0 -67
  339. package/src/modules/linuxRootfs.ts +0 -1961
  340. package/src/modules/neofetch.ts +0 -358
  341. package/src/modules/shellInteractive.ts +0 -57
  342. package/src/modules/shellRuntime.ts +0 -76
  343. package/src/self-standalone.ts +0 -542
  344. package/src/standalone-wo-sftp.ts +0 -38
  345. package/src/standalone.ts +0 -72
  346. package/src/types/commands.ts +0 -146
  347. package/src/types/pipeline.ts +0 -52
  348. package/src/types/streams.ts +0 -32
  349. package/src/types/tar-stream.d.ts +0 -38
  350. package/src/types/vfs.ts +0 -98
  351. package/src/utils/expand.ts +0 -491
  352. package/src/utils/perfLogger.ts +0 -72
  353. package/src/utils/tokenize.ts +0 -98
  354. package/src/utils/vfsDiff.ts +0 -275
  355. package/tests/command-helpers.test.ts +0 -116
  356. package/tests/commands-admin-net.test.ts +0 -441
  357. package/tests/commands-advanced.test.ts +0 -456
  358. package/tests/commands-core.test.ts +0 -562
  359. package/tests/commands-missing.test.ts +0 -570
  360. package/tests/commands-specific-units.test.ts +0 -327
  361. package/tests/commands-text-sys.test.ts +0 -445
  362. package/tests/expand.test.ts +0 -170
  363. package/tests/helpers.test.ts +0 -97
  364. package/tests/new-features.test.ts +0 -1036
  365. package/tests/parser-executor.test.ts +0 -37
  366. package/tests/sftp.test.ts +0 -323
  367. package/tests/ssh-exec.test.ts +0 -45
  368. package/tests/test-helper.ts +0 -79
  369. package/tests/users.test.ts +0 -86
  370. package/tsconfig.json +0 -49
  371. package/typedoc.json +0 -47
package/examples/app.ts DELETED
@@ -1,299 +0,0 @@
1
- /** biome-ignore-all lint/suspicious/noControlCharactersInRegex: need to parse ANSI */
2
- import { getCommandNames } from '../src/commands/registry.js';
3
- import { makeDefaultEnv, runCommand, userHome } from '../src/commands/runtime.js';
4
- import { VirtualShell } from '../src/index.js';
5
- import { resolvePath } from '../src/modules/shellRuntime.js';
6
- import { type LoginBannerState, buildLoginBanner } from '../src/SSHMimic/loginBanner.js';
7
- import { buildPrompt } from '../src/SSHMimic/prompt.js';
8
- import type { CommandResult } from '../src/types/commands.js';
9
-
10
- const HOSTNAME = 'my-vm';
11
- const MAX_HISTORY = 500;
12
-
13
- const terminal = document.getElementById('terminal') as HTMLElement;
14
- const out = document.getElementById('output') as HTMLElement;
15
- const cmd = document.getElementById('cmd') as HTMLInputElement;
16
-
17
- function scrollToBottom(): void {
18
- terminal.scrollTop = terminal.scrollHeight;
19
- }
20
-
21
- cmd.focus();
22
- document.addEventListener('click', () => {
23
- if (!window.getSelection()?.toString()) cmd.focus();
24
- });
25
-
26
- // ANSI to HTML
27
- const FG_COLORS: Record<number, string> = {
28
- 30: '#000', 31: '#c00', 32: '#0c0', 33: '#cc0',
29
- 34: '#00c', 35: '#c0c', 36: '#0cc', 37: '#ccc',
30
- 90: '#555', 91: '#f55', 92: '#5f5', 93: '#ff5',
31
- 94: '#55f', 95: '#f5f', 96: '#5ff', 97: '#fff',
32
- };
33
- const BG_COLORS: Record<number, string> = {
34
- 40: '#000', 41: '#c00', 42: '#0c0', 43: '#cc0',
35
- 44: '#00c', 45: '#c0c', 46: '#0cc', 47: '#ccc',
36
- };
37
-
38
- function ansiToHtml(s: string): string {
39
- let html = '';
40
- let bold = false, fg = '', bg = '';
41
- for (const part of s.split(/(\x1b\[[0-9;]*m)/)) {
42
- const m = part.match(/^\x1b\[([0-9;]*)m$/);
43
- if (m) {
44
- for (const code of m[1].split(';').map(Number)) {
45
- if (code === 0) { bold = false; fg = ''; bg = ''; }
46
- else if (code === 1) bold = true;
47
- else if (FG_COLORS[code]) fg = FG_COLORS[code];
48
- else if (BG_COLORS[code]) bg = BG_COLORS[code];
49
- }
50
- } else if (part) {
51
- const style = [
52
- fg ? `color:${fg}` : '',
53
- bg ? `background:${bg}` : '',
54
- bold ? 'font-weight:bold' : '',
55
- ].filter(Boolean).join(';');
56
- const escaped = part.replace(/&/g, '&amp;').replace(/</g, '&lt;');
57
- html += style ? `<span style="${style}">${escaped}</span>` : escaped;
58
- }
59
- }
60
- return html;
61
- }
62
-
63
- // All output goes into a single <span> appended to #output.
64
- // #output is pre-wrap so \n = newline, no extra divs needed.
65
- function print(s: string): void {
66
- const span = document.createElement('span');
67
- span.innerHTML = ansiToHtml(s);
68
- if (inputLineEl) {
69
- out.insertBefore(span, inputLineEl);
70
- } else {
71
- out.appendChild(span);
72
- }
73
- scrollToBottom();
74
- }
75
-
76
- // Live input line — sits at bottom of #output as an inline element
77
- let inputLineEl: HTMLSpanElement | null = null;
78
-
79
- function printPrompt(): void {
80
- if (inputLineEl) { inputLineEl.remove(); inputLineEl = null; }
81
- cmd.value = '';
82
-
83
- inputLineEl = document.createElement('span');
84
- inputLineEl.className = 'input-line';
85
-
86
- const promptSpan = document.createElement('span');
87
- const cwdLabel = cwd === userHome(authUser) ? '~' : (cwd.split('/').at(-1) || '/');
88
- promptSpan.innerHTML = ansiToHtml(buildPrompt(authUser, HOSTNAME, cwdLabel));
89
-
90
- const textSpan = document.createElement('span');
91
- textSpan.className = 'typed';
92
-
93
- const cursor = document.createElement('span');
94
- cursor.className = 'cursor';
95
- cursor.textContent = '\u00a0';
96
-
97
- inputLineEl.appendChild(promptSpan);
98
- inputLineEl.appendChild(textSpan);
99
- inputLineEl.appendChild(cursor);
100
- out.appendChild(inputLineEl);
101
- scrollToBottom();
102
- }
103
-
104
- cmd.addEventListener('input', () => {
105
- if (!inputLineEl) return;
106
- (inputLineEl.querySelector('.typed') as HTMLSpanElement).textContent = cmd.value;
107
- scrollToBottom();
108
- });
109
-
110
- // Wait for IndexedDB fs shim memCache
111
- // biome-ignore lint/suspicious/noExplicitAny: globalThis shim
112
- await (globalThis as any).__fsReady__;
113
-
114
- const shell = new VirtualShell(HOSTNAME, undefined, {
115
- mode: 'fs',
116
- snapshotPath: '/vfs-data',
117
- flushIntervalMs: 10_000,
118
- });
119
-
120
- const vfs = shell.vfs;
121
-
122
- await vfs.restoreMirror();
123
-
124
- const isFirstRun = !vfs.exists('/bin');
125
- if (isFirstRun) {
126
- await shell.ensureInitialized();
127
- if (!vfs.exists('/root')) vfs.mkdir('/root', 0o700);
128
- vfs.writeFile('/root/README.txt', `Welcome to ${HOSTNAME}\n`);
129
- await vfs.flushMirror();
130
- }
131
-
132
- window.addEventListener('beforeunload', () => { vfs.flushMirror(); });
133
-
134
- // Session state
135
- let authUser = 'root';
136
- let cwd = userHome(authUser);
137
- const shellEnv = makeDefaultEnv(authUser, HOSTNAME);
138
- shellEnv.vars.PWD = cwd;
139
-
140
- function applyResult(result: CommandResult): void {
141
- if (result.switchUser) {
142
- authUser = result.switchUser;
143
- cwd = result.nextCwd ?? userHome(authUser);
144
- shellEnv.vars.USER = authUser;
145
- shellEnv.vars.LOGNAME = authUser;
146
- shellEnv.vars.HOME = userHome(authUser);
147
- shellEnv.vars.PWD = cwd;
148
- } else if (result.nextCwd) {
149
- cwd = result.nextCwd;
150
- shellEnv.vars.PWD = cwd;
151
- }
152
- }
153
-
154
- // History
155
- function historyPath(): string { return `${userHome(authUser)}/.bash_history`; }
156
-
157
- function loadHistory(): string[] {
158
- try {
159
- if (!vfs.exists(historyPath())) return [];
160
- return (vfs.readFile(historyPath()) as string)
161
- .split('\n').map((l: string) => l.trim()).filter((l: string) => l.length > 0);
162
- } catch { return []; }
163
- }
164
-
165
- function saveHistory(): void {
166
- vfs.writeFile(historyPath(), history.length > 0 ? `${history.join('\n')}\n` : '');
167
- }
168
-
169
- let history: string[] = loadHistory();
170
- let historyIdx = -1;
171
-
172
- // Login banner + lastlog
173
- function readLastLogin(): LoginBannerState | null {
174
- try {
175
- if (!vfs.exists('/root/.lastlog')) return null;
176
- return JSON.parse(vfs.readFile('/root/.lastlog'));
177
- } catch { return null; }
178
- }
179
-
180
- function writeLastLogin(): void {
181
- vfs.writeFile('/root/.lastlog', JSON.stringify({ at: new Date().toISOString(), from: 'browser' }));
182
- }
183
-
184
- print(buildLoginBanner(HOSTNAME, shell.properties, readLastLogin()));
185
- writeLastLogin();
186
- await vfs.flushMirror();
187
- printPrompt();
188
-
189
-
190
- // Tab completion
191
- function listPathCompletions(prefix: string): string[] {
192
- const slashIndex = prefix.lastIndexOf('/');
193
- const dirPart = slashIndex >= 0 ? prefix.slice(0, slashIndex + 1) : '';
194
- const namePart = slashIndex >= 0 ? prefix.slice(slashIndex + 1) : prefix;
195
- const basePath = resolvePath(cwd, dirPart || '.');
196
- try {
197
- return vfs.list(basePath)
198
- .filter((e: string) => !e.startsWith('.') && e.startsWith(namePart))
199
- .map((e: string) => {
200
- const fullPath = `${basePath}/${e}`.replace(/\/+/g, '/');
201
- const st = vfs.stat(fullPath);
202
- return `${dirPart}${e}${st.type === 'directory' ? '/' : ''}`;
203
- })
204
- .sort();
205
- } catch { return []; }
206
- }
207
-
208
- const commandNames = Array.from(new Set(getCommandNames())).sort();
209
-
210
- function getCompletions(line: string): [string[], string] {
211
- const token = line.split(/\s+/).at(-1) ?? '';
212
- const isFirstToken = line.trimStart() === token;
213
- const cmdHits = isFirstToken ? commandNames.filter(n => n.startsWith(token)) : [];
214
- const pathHits = listPathCompletions(token);
215
- const hits = Array.from(new Set([...cmdHits, ...pathHits])).sort();
216
- return [hits, token];
217
- }
218
-
219
- // Input handler
220
- cmd.addEventListener('keydown', async (e: KeyboardEvent) => {
221
- if (e.key === 'Tab') {
222
- e.preventDefault();
223
- const line = cmd.value;
224
- const [hits, token] = getCompletions(line);
225
- if (hits.length === 0) return;
226
- if (hits.length === 1) {
227
- // Unique match — complete inline
228
- cmd.value = line.slice(0, line.length - token.length) + hits[0];
229
- if (inputLineEl) (inputLineEl.querySelector('.typed') as HTMLSpanElement).textContent = cmd.value;
230
- } else {
231
- // Multiple matches — print them below current line, re-prompt
232
- const prevLine = inputLineEl;
233
- inputLineEl = null;
234
- prevLine?.querySelector('.cursor')?.remove();
235
- out.appendChild(document.createTextNode('\n'));
236
- print(`${hits.join(' ')}
237
- `);
238
- printPrompt();
239
- cmd.value = line;
240
- if (inputLineEl) ((inputLineEl as HTMLSpanElement).querySelector('.typed') as HTMLSpanElement).textContent = cmd.value;
241
- }
242
- return;
243
- }
244
-
245
- if (e.key === 'ArrowUp') {
246
- e.preventDefault();
247
- if (historyIdx < history.length - 1) {
248
- historyIdx++;
249
- cmd.value = history[history.length - 1 - historyIdx];
250
- if (inputLineEl) (inputLineEl.querySelector('.typed') as HTMLSpanElement).textContent = cmd.value;
251
- }
252
- return;
253
- }
254
-
255
- if (e.key === 'ArrowDown') {
256
- e.preventDefault();
257
- if (historyIdx > 0) { historyIdx--; cmd.value = history[history.length - 1 - historyIdx]; }
258
- else { historyIdx = -1; cmd.value = ''; }
259
- if (inputLineEl) (inputLineEl.querySelector('.typed') as HTMLSpanElement).textContent = cmd.value;
260
- return;
261
- }
262
-
263
- if (e.key !== 'Enter') return;
264
-
265
- const value = cmd.value.trim();
266
- historyIdx = -1;
267
-
268
- // Freeze input line: remove cursor span, null the ref (keeps prompt+typed in DOM)
269
- if (inputLineEl) {
270
- inputLineEl.querySelector('.cursor')?.remove();
271
- inputLineEl = null;
272
- }
273
-
274
- // Newline after the frozen line
275
- out.appendChild(document.createTextNode('\n'));
276
-
277
- if (value) {
278
- history.push(value);
279
- if (history.length > MAX_HISTORY) history = history.slice(history.length - MAX_HISTORY);
280
- saveHistory();
281
- }
282
-
283
- try {
284
- const result = await runCommand(value, authUser, HOSTNAME, 'shell', cwd, shell, undefined, shellEnv);
285
-
286
- if (result.clearScreen) out.innerHTML = '';
287
- if (result.stdout) print(`${result.stdout.trim()}\n`);
288
- if (result.stderr) print(`${result.stderr.trim()}\n`);
289
-
290
- applyResult(result);
291
- await vfs.flushMirror();
292
-
293
- if (result.closeSession) { print('\nSession closed.\n'); return; }
294
- } catch (err) {
295
- print(`${String(err)}\n`);
296
- }
297
-
298
- printPrompt();
299
- });
package/examples/build.js DELETED
@@ -1,27 +0,0 @@
1
- import esbuild from 'esbuild';
2
-
3
- const ctx = await esbuild.context({
4
- entryPoints: ['app.ts'],
5
- bundle: true,
6
- format: 'esm',
7
- outfile: `app.js`,
8
- platform: 'browser',
9
- alias: {
10
- 'node:events': '../polyfills/node_events/index.js',
11
- 'node:path': '../polyfills/node_path/index.js',
12
- 'node:os': '../polyfills/node_os/index.js',
13
- 'node:fs': '../polyfills/node_fs/index.js',
14
- 'node:fs/promises': '../polyfills/node_fs/promises.js',
15
- 'node:crypto': '../polyfills/node_crypto/index.js',
16
- 'node:child_process': '../polyfills/node_child_process/index.js',
17
- 'node:zlib': '../polyfills/node_zlib/index.js',
18
- 'node:vm': '../polyfills/node_vm/index.js',
19
- 'ssh2': '../polyfills/ssh2/index.js',
20
- },
21
- minify: true,
22
- treeShaking: true,
23
- inject: ['../polyfills/process.js', '../polyfills/buffer.js'],
24
- });
25
-
26
- await ctx.watch();
27
- console.log('watching...');
@@ -1,33 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Virtual Env JS</title>
7
- <script type="module">
8
- import { VirtualShell, VirtualFileSystem } from '../builds/fortune-nyx-v1.5.3-web.min.js';
9
-
10
- const now1 = new Date();
11
- const ready = await globalThis.__fsReady__;
12
- window.ready = ready; // Expose for debugging
13
- const now2 = new Date();
14
- console.log(`IndexedDB VFS ready in ${now2 - now1}ms`);
15
- const shell = new VirtualShell('my-vm', undefined, {
16
- mode: 'fs',
17
- snapshotPath: '/vfs-data',
18
- flushIntervalMs: 10_000,
19
- });
20
-
21
- window.addEventListener('beforeunload', () => {
22
- shell.vfs.flushMirror();
23
- });
24
-
25
- window.shell = shell; // Expose shell for debugging
26
- const result = await shell.executeCommand("ls -l", "root", "/root");
27
- await shell.vfs.flushMirror()
28
- console.log(shell.vfs.getMode());
29
- </script>
30
- </head>
31
- <body>
32
- </body>
33
- </html>
@@ -1,180 +0,0 @@
1
- /**
2
- * HoneyPot Auditing Example
3
- *
4
- * Demonstrates how to use the HoneyPot utility to track all activity
5
- * in a virtual environment, collect statistics, and detect anomalies.
6
- *
7
- * Run with: bun run examples/honeypot-audit.ts
8
- */
9
-
10
- import {
11
- HoneyPot,
12
- SshClient,
13
- VirtualShell,
14
- VirtualSshServer,
15
- } from "../src/index";
16
-
17
- async function demonstrateHoneypot() {
18
- console.log("🍯 HoneyPot Auditing Example\n");
19
-
20
- // Initialize the virtual environment
21
- const shell = new VirtualShell("security-lab");
22
- const ssh = new VirtualSshServer({ port: 2222, shell });
23
- await ssh.start();
24
-
25
- const users = shell.getUsers()!;
26
- const vfs = shell.getVfs()!;
27
-
28
- // Create HoneyPot instance with 1000-entry log limit
29
- const honeypot = new HoneyPot(1000);
30
-
31
- // Attach HoneyPot to all components
32
- honeypot.attach(shell, vfs, users, ssh);
33
-
34
- console.log("✅ HoneyPot attached to all components\n");
35
-
36
- // ------ Scenario 1: Normal user activity ------
37
- console.log("--- Scenario 1: Normal User Activity ---\n");
38
-
39
- await users.addUser("alice", "alice_pass123");
40
- await users.addUser("bob", "bob_pass456");
41
-
42
- const alice = new SshClient(shell, "alice");
43
- await alice.mkdir("/home/alice/work", true);
44
- await alice.writeFile("/home/alice/work/notes.txt", "Project notes");
45
- await alice.ls("/home/alice/work");
46
- await alice.cat("/home/alice/work/notes.txt");
47
-
48
- console.log("✓ Alice performed normal operations\n");
49
-
50
- // ------ Scenario 2: Bob attempts suspicious operations ------
51
- console.log("--- Scenario 2: Suspicious Attempt ---\n");
52
-
53
- const bob = new SshClient(shell, "bob");
54
- // These will fail but are tracked
55
- await bob.readFile("/etc/shadow");
56
- await bob.readFile("/etc/passwd");
57
- await bob.readFile("/root/.ssh/id_rsa");
58
-
59
- console.log("✓ Bob attempted unauthorized file access\n");
60
-
61
- // ------ Activity Summary ------
62
- console.log("--- Activity Summary ---\n");
63
-
64
- const stats = honeypot.getStats();
65
- console.log("📊 Audit Statistics:");
66
- console.log(` • Auth attempts: ${stats.authAttempts}`);
67
- console.log(` • Auth successes: ${stats.authSuccesses}`);
68
- console.log(` • Auth failures: ${stats.authFailures}`);
69
- console.log(` • Commands executed: ${stats.commands}`);
70
- console.log(` • File reads: ${stats.fileReads}`);
71
- console.log(` • File writes: ${stats.fileWrites}`);
72
- console.log(` • Users created: ${stats.userCreated}`);
73
- console.log(` • Sessions started: ${stats.sessionStarts}\n`);
74
-
75
- // ------ Recent Events ------
76
- console.log("--- Most Recent Events ---\n");
77
-
78
- const recent = honeypot.getRecent(10);
79
- console.log(`📋 Last ${recent.length} events:\n`);
80
- recent.forEach((entry) => {
81
- console.log(` [${entry.timestamp}]`);
82
- console.log(` Source: ${entry.source}`);
83
- console.log(` Event: ${entry.type}`);
84
- console.log(` Details: ${JSON.stringify(entry.details)}\n`);
85
- });
86
-
87
- // ------ Filtered Audit Log ------
88
- console.log("--- Filtered Audit Log ---\n");
89
-
90
- const authFailures = honeypot.getAuditLog("auth:failure");
91
- console.log(`🚨 Auth Failures (${authFailures.length} total):\n`);
92
- if (authFailures.length > 0) {
93
- authFailures.forEach((entry) => {
94
- console.log(
95
- ` • User "${entry.details.username}" from ${entry.details.remoteAddress}`,
96
- );
97
- });
98
- } else {
99
- console.log(" • None detected");
100
- }
101
- console.log();
102
-
103
- // ------ SSH-specific events ------
104
- console.log("--- SSH-Specific Events ---\n");
105
-
106
- const sshEvents = honeypot.getAuditLog(undefined, "SshMimic");
107
- console.log(`🔗 SSH events (${sshEvents.length} total):\n`);
108
- sshEvents.forEach((entry) => {
109
- console.log(` • ${entry.type}: ${JSON.stringify(entry.details)}`);
110
- });
111
- console.log();
112
-
113
- // ------ File System Activity ------
114
- console.log("--- File System Activity ---\n");
115
-
116
- const fileWrites = honeypot.getAuditLog("file:write", "VirtualFileSystem");
117
- const fileReads = honeypot.getAuditLog("file:read", "VirtualFileSystem");
118
-
119
- console.log(`📁 File Operations:`);
120
- console.log(` • File writes: ${fileWrites.length}`);
121
- fileWrites.forEach((entry) => {
122
- console.log(` - ${entry.details.path} (${entry.details.size} bytes)`);
123
- });
124
- console.log(` • File reads: ${fileReads.length}`);
125
- fileReads.forEach((entry) => {
126
- console.log(` - ${entry.details.path} (${entry.details.size} bytes)`);
127
- });
128
- console.log();
129
-
130
- // ------ Anomaly Detection ------
131
- console.log("--- Security Analysis ---\n");
132
-
133
- const anomalies = honeypot.detectAnomalies();
134
- if (anomalies.length > 0) {
135
- console.log("⚠️ Anomalies Detected:\n");
136
- anomalies.forEach((anomaly) => {
137
- const severity = {
138
- low: "ℹ️ ",
139
- medium: "⚠️ ",
140
- high: "🚨",
141
- }[anomaly.severity];
142
- console.log(` ${severity} [${anomaly.type}]`);
143
- console.log(` ${anomaly.message}\n`);
144
- });
145
- } else {
146
- console.log("✅ No anomalies detected\n");
147
- }
148
-
149
- // ------ Export Audit Log ------
150
- console.log("--- Full Audit Export ---\n");
151
-
152
- const allAuditEntries = honeypot.getAuditLog();
153
- console.log(`📊 Total audit entries: ${allAuditEntries.length}`);
154
- console.log(`💾 Audit log is ready for export/storage\n`);
155
-
156
- // Example export to JSON
157
- const exportData = {
158
- timestamp: new Date().toISOString(),
159
- environment: "security-lab",
160
- stats,
161
- auditLog: allAuditEntries.slice(-50), // Last 50 entries
162
- anomalies,
163
- };
164
-
165
- console.log("📄 Sample export structure:");
166
- console.log(`${JSON.stringify(exportData, null, 2).substring(0, 300)}...\n`);
167
-
168
- // Cleanup
169
- ssh.stop();
170
-
171
- console.log(
172
- "✅ Example completed! HoneyPot auditing demonstration finished.\n",
173
- );
174
- }
175
-
176
- // Run the example
177
- demonstrateHoneypot().catch((error) => {
178
- console.error("❌ Error:", error);
179
- process.exit(1);
180
- });