typescript-virtual-container 1.5.2 → 1.5.4

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 (364) hide show
  1. package/README.md +43 -23
  2. package/dist/.tsbuildinfo +1 -0
  3. package/dist/SSHMimic/executor.js +23 -5
  4. package/dist/commands/basename.d.ts +13 -0
  5. package/dist/commands/basename.js +45 -0
  6. package/dist/commands/file.d.ts +8 -0
  7. package/dist/commands/file.js +57 -0
  8. package/dist/commands/fun.d.ts +32 -0
  9. package/dist/commands/fun.js +172 -0
  10. package/dist/commands/ifconfig.d.ts +7 -0
  11. package/dist/commands/ifconfig.js +52 -0
  12. package/dist/commands/last.d.ts +13 -0
  13. package/dist/commands/last.js +68 -0
  14. package/dist/commands/manuals-bundle.js +598 -6
  15. package/dist/commands/registry.js +24 -2
  16. package/dist/commands/runtime.js +159 -106
  17. package/dist/commands/sh.js +5 -0
  18. package/dist/commands/tput.d.ts +13 -0
  19. package/dist/commands/tput.js +76 -0
  20. package/dist/commands/w.d.ts +7 -0
  21. package/dist/commands/w.js +38 -0
  22. package/dist/utils/expand.d.ts +12 -0
  23. package/dist/utils/expand.js +84 -0
  24. package/package.json +9 -3
  25. package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
  26. package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -31
  27. package/.github/dependabot.yml +0 -27
  28. package/.github/pull_request_template.md +0 -21
  29. package/.github/workflows/create-pull-request.yml +0 -85
  30. package/.github/workflows/publish.yml +0 -25
  31. package/.github/workflows/test-battery.yml +0 -102
  32. package/.vscode/settings.json +0 -20
  33. package/CODE_OF_CONDUCT.md +0 -39
  34. package/CONTRIBUTING.md +0 -59
  35. package/HONEYPOT.md +0 -358
  36. package/SECURITY.md +0 -33
  37. package/benchmark-results.txt +0 -40
  38. package/benchmark-virtualshell.ts +0 -88
  39. package/biome.json +0 -37
  40. package/build.js +0 -22
  41. package/builds/fortune-nyx-v1.5.1-directbash-k6.1.0.mjs +0 -1768
  42. package/builds/fortune-nyx-v1.5.1-ssh-nosftp.js +0 -1768
  43. package/builds/fortune-nyx-v1.5.1-ssh.cjs +0 -1769
  44. package/builds/fortune-nyx-v1.5.1-web.min.js +0 -17022
  45. package/bun.lock +0 -244
  46. package/docs/.nojekyll +0 -1
  47. package/docs/app.js +0 -1755
  48. package/docs/assets/hierarchy.js +0 -1
  49. package/docs/assets/highlight.css +0 -162
  50. package/docs/assets/icons.js +0 -18
  51. package/docs/assets/icons.svg +0 -1
  52. package/docs/assets/main.js +0 -60
  53. package/docs/assets/navigation.js +0 -1
  54. package/docs/assets/search.js +0 -1
  55. package/docs/assets/style.css +0 -1633
  56. package/docs/classes/HoneyPot.html +0 -31
  57. package/docs/classes/IdleManager.html +0 -162
  58. package/docs/classes/SshClient.html +0 -66
  59. package/docs/classes/VirtualFileSystem.html +0 -279
  60. package/docs/classes/VirtualPackageManager.html +0 -63
  61. package/docs/classes/VirtualSftpServer.html +0 -169
  62. package/docs/classes/VirtualShell.html +0 -285
  63. package/docs/classes/VirtualSshServer.html +0 -182
  64. package/docs/classes/VirtualUserManager.html +0 -276
  65. package/docs/demo.html +0 -82
  66. package/docs/functions/assertDiff.html +0 -6
  67. package/docs/functions/diffSnapshots.html +0 -7
  68. package/docs/functions/formatDiff.html +0 -6
  69. package/docs/functions/getArg.html +0 -13
  70. package/docs/functions/getFlag.html +0 -15
  71. package/docs/functions/ifFlag.html +0 -11
  72. package/docs/hierarchy.html +0 -1
  73. package/docs/index.html +0 -1869
  74. package/docs/interfaces/AuditLogEntry.html +0 -6
  75. package/docs/interfaces/CommandContext.html +0 -22
  76. package/docs/interfaces/CommandResult.html +0 -26
  77. package/docs/interfaces/ExecStream.html +0 -11
  78. package/docs/interfaces/HoneyPotStats.html +0 -16
  79. package/docs/interfaces/IdleManagerOptions.html +0 -7
  80. package/docs/interfaces/InstalledPackage.html +0 -20
  81. package/docs/interfaces/NanoEditorSession.html +0 -8
  82. package/docs/interfaces/PackageDefinition.html +0 -30
  83. package/docs/interfaces/PackageFile.html +0 -8
  84. package/docs/interfaces/PasswordChallenge.html +0 -16
  85. package/docs/interfaces/RemoveOptions.html +0 -4
  86. package/docs/interfaces/ShellEnv.html +0 -6
  87. package/docs/interfaces/ShellModule.html +0 -14
  88. package/docs/interfaces/ShellProperties.html +0 -14
  89. package/docs/interfaces/ShellStream.html +0 -11
  90. package/docs/interfaces/SudoChallenge.html +0 -24
  91. package/docs/interfaces/VfsBaseNode.html +0 -12
  92. package/docs/interfaces/VfsDiff.html +0 -10
  93. package/docs/interfaces/VfsDiffEntry.html +0 -6
  94. package/docs/interfaces/VfsDiffModified.html +0 -10
  95. package/docs/interfaces/VfsDirectoryNode.html +0 -15
  96. package/docs/interfaces/VfsFileNode.html +0 -17
  97. package/docs/interfaces/VfsOptions.html +0 -26
  98. package/docs/interfaces/VfsSnapshot.html +0 -3
  99. package/docs/interfaces/VfsSnapshotBaseNode.html +0 -8
  100. package/docs/interfaces/VfsSnapshotDirectoryNode.html +0 -10
  101. package/docs/interfaces/VfsSnapshotFileNode.html +0 -12
  102. package/docs/interfaces/VirtualActiveSession.html +0 -12
  103. package/docs/interfaces/VirtualSftpServerOptions.html +0 -7
  104. package/docs/interfaces/VirtualShellVfsLike.html +0 -15
  105. package/docs/interfaces/VirtualShellVfsOptions.html +0 -3
  106. package/docs/interfaces/WriteFileOptions.html +0 -6
  107. package/docs/media/LICENSE +0 -21
  108. package/docs/modules.html +0 -1
  109. package/docs/types/ArgParseOptions.html +0 -4
  110. package/docs/types/CommandMode.html +0 -2
  111. package/docs/types/CommandOutcome.html +0 -2
  112. package/docs/types/IdleState.html +0 -1
  113. package/docs/types/VfsNodeStats.html +0 -2
  114. package/docs/types/VfsNodeType.html +0 -2
  115. package/docs/types/VfsPersistenceMode.html +0 -5
  116. package/docs/types/VfsSnapshotNode.html +0 -2
  117. package/examples/README.md +0 -288
  118. package/examples/app.js +0 -1755
  119. package/examples/app.ts +0 -299
  120. package/examples/build.js +0 -27
  121. package/examples/demo.html +0 -33
  122. package/examples/honeypot-audit.ts +0 -180
  123. package/examples/honeypot-export.ts +0 -253
  124. package/examples/honeypot-quickstart.ts +0 -110
  125. package/examples/index.html +0 -82
  126. package/examples/server.js +0 -55
  127. package/polyfills/buffer.js +0 -117
  128. package/polyfills/node_child_process/index.js +0 -2
  129. package/polyfills/node_crypto/index.js +0 -167
  130. package/polyfills/node_events/index.js +0 -9
  131. package/polyfills/node_fs/index.js +0 -202
  132. package/polyfills/node_fs/promises.js +0 -4
  133. package/polyfills/node_os/index.js +0 -9
  134. package/polyfills/node_path/index.js +0 -28
  135. package/polyfills/node_vm/index.js +0 -7
  136. package/polyfills/node_zlib/index.js +0 -3
  137. package/polyfills/process.js +0 -14
  138. package/polyfills/ssh2/index.js +0 -75
  139. package/scripts/build-all.mjs +0 -226
  140. package/scripts/build-names.mjs +0 -43
  141. package/scripts/generate-manuals-bundle.mjs +0 -49
  142. package/scripts/postinstall.js +0 -42
  143. package/scripts/publish-package.sh +0 -70
  144. package/src/Honeypot/index.ts +0 -457
  145. package/src/SSHClient/index.ts +0 -270
  146. package/src/SSHMimic/exec.ts +0 -49
  147. package/src/SSHMimic/executor.ts +0 -251
  148. package/src/SSHMimic/hostKey.ts +0 -21
  149. package/src/SSHMimic/index.ts +0 -337
  150. package/src/SSHMimic/loginBanner.ts +0 -36
  151. package/src/SSHMimic/loginFormat.ts +0 -10
  152. package/src/SSHMimic/prompt.ts +0 -14
  153. package/src/SSHMimic/sftp.ts +0 -883
  154. package/src/VirtualFileSystem/binaryPack.ts +0 -258
  155. package/src/VirtualFileSystem/index.ts +0 -1193
  156. package/src/VirtualFileSystem/internalTypes.ts +0 -43
  157. package/src/VirtualFileSystem/journal.ts +0 -171
  158. package/src/VirtualFileSystem/path.ts +0 -74
  159. package/src/VirtualPackageManager/index.ts +0 -1006
  160. package/src/VirtualShell/idleManager.ts +0 -137
  161. package/src/VirtualShell/index.ts +0 -475
  162. package/src/VirtualShell/shell.ts +0 -700
  163. package/src/VirtualShell/shellParser.ts +0 -285
  164. package/src/VirtualUserManager/index.ts +0 -758
  165. package/src/bun.d.ts +0 -1
  166. package/src/commands/adduser.ts +0 -103
  167. package/src/commands/alias.ts +0 -69
  168. package/src/commands/apt.ts +0 -233
  169. package/src/commands/awk.ts +0 -168
  170. package/src/commands/base64.ts +0 -29
  171. package/src/commands/cat.ts +0 -52
  172. package/src/commands/cd.ts +0 -25
  173. package/src/commands/chmod.ts +0 -85
  174. package/src/commands/clear.ts +0 -15
  175. package/src/commands/command-helpers.ts +0 -286
  176. package/src/commands/cp.ts +0 -83
  177. package/src/commands/curl.ts +0 -147
  178. package/src/commands/cut.ts +0 -36
  179. package/src/commands/date.ts +0 -30
  180. package/src/commands/declare.ts +0 -49
  181. package/src/commands/deluser.ts +0 -98
  182. package/src/commands/df.ts +0 -23
  183. package/src/commands/diff.ts +0 -43
  184. package/src/commands/dpkg.ts +0 -180
  185. package/src/commands/du.ts +0 -56
  186. package/src/commands/echo.ts +0 -58
  187. package/src/commands/env.ts +0 -23
  188. package/src/commands/exit.ts +0 -18
  189. package/src/commands/export.ts +0 -34
  190. package/src/commands/find.ts +0 -68
  191. package/src/commands/free.ts +0 -47
  192. package/src/commands/grep.ts +0 -116
  193. package/src/commands/groups.ts +0 -19
  194. package/src/commands/gzip.ts +0 -88
  195. package/src/commands/head.ts +0 -52
  196. package/src/commands/help.ts +0 -152
  197. package/src/commands/helpers.ts +0 -234
  198. package/src/commands/history.ts +0 -34
  199. package/src/commands/hostname.ts +0 -14
  200. package/src/commands/htop.ts +0 -20
  201. package/src/commands/id.ts +0 -19
  202. package/src/commands/index.ts +0 -9
  203. package/src/commands/kill.ts +0 -19
  204. package/src/commands/ln.ts +0 -71
  205. package/src/commands/ls.ts +0 -243
  206. package/src/commands/lsb-release.ts +0 -63
  207. package/src/commands/man.ts +0 -31
  208. package/src/commands/manuals/adduser.txt +0 -11
  209. package/src/commands/manuals/apt-cache.txt +0 -12
  210. package/src/commands/manuals/apt.txt +0 -20
  211. package/src/commands/manuals/awk.txt +0 -13
  212. package/src/commands/manuals/cat.txt +0 -14
  213. package/src/commands/manuals/cd.txt +0 -16
  214. package/src/commands/manuals/chmod.txt +0 -16
  215. package/src/commands/manuals/clear.txt +0 -10
  216. package/src/commands/manuals/cp.txt +0 -10
  217. package/src/commands/manuals/curl.txt +0 -20
  218. package/src/commands/manuals/date.txt +0 -14
  219. package/src/commands/manuals/declare.txt +0 -12
  220. package/src/commands/manuals/deluser.txt +0 -10
  221. package/src/commands/manuals/df.txt +0 -10
  222. package/src/commands/manuals/dpkg-query.txt +0 -11
  223. package/src/commands/manuals/dpkg.txt +0 -14
  224. package/src/commands/manuals/du.txt +0 -11
  225. package/src/commands/manuals/echo.txt +0 -11
  226. package/src/commands/manuals/false.txt +0 -10
  227. package/src/commands/manuals/find.txt +0 -11
  228. package/src/commands/manuals/free.txt +0 -12
  229. package/src/commands/manuals/grep.txt +0 -13
  230. package/src/commands/manuals/groups.txt +0 -10
  231. package/src/commands/manuals/gzip.txt +0 -11
  232. package/src/commands/manuals/head.txt +0 -10
  233. package/src/commands/manuals/help.txt +0 -11
  234. package/src/commands/manuals/history.txt +0 -11
  235. package/src/commands/manuals/hostname.txt +0 -10
  236. package/src/commands/manuals/id.txt +0 -10
  237. package/src/commands/manuals/kill.txt +0 -13
  238. package/src/commands/manuals/ls.txt +0 -20
  239. package/src/commands/manuals/lsb_release.txt +0 -14
  240. package/src/commands/manuals/mkdir.txt +0 -10
  241. package/src/commands/manuals/mv.txt +0 -10
  242. package/src/commands/manuals/nano.txt +0 -11
  243. package/src/commands/manuals/neofetch.txt +0 -10
  244. package/src/commands/manuals/node.txt +0 -13
  245. package/src/commands/manuals/npm.txt +0 -13
  246. package/src/commands/manuals/npx.txt +0 -13
  247. package/src/commands/manuals/passwd.txt +0 -11
  248. package/src/commands/manuals/ping.txt +0 -10
  249. package/src/commands/manuals/printf.txt +0 -11
  250. package/src/commands/manuals/ps.txt +0 -10
  251. package/src/commands/manuals/pwd.txt +0 -10
  252. package/src/commands/manuals/python3.txt +0 -13
  253. package/src/commands/manuals/readlink.txt +0 -10
  254. package/src/commands/manuals/return.txt +0 -10
  255. package/src/commands/manuals/rm.txt +0 -10
  256. package/src/commands/manuals/sed.txt +0 -11
  257. package/src/commands/manuals/set.txt +0 -11
  258. package/src/commands/manuals/shift.txt +0 -10
  259. package/src/commands/manuals/sleep.txt +0 -10
  260. package/src/commands/manuals/sort.txt +0 -12
  261. package/src/commands/manuals/source.txt +0 -11
  262. package/src/commands/manuals/ssh.txt +0 -11
  263. package/src/commands/manuals/stat.txt +0 -10
  264. package/src/commands/manuals/su.txt +0 -13
  265. package/src/commands/manuals/sudo.txt +0 -11
  266. package/src/commands/manuals/tail.txt +0 -10
  267. package/src/commands/manuals/tar.txt +0 -19
  268. package/src/commands/manuals/tee.txt +0 -10
  269. package/src/commands/manuals/test.txt +0 -11
  270. package/src/commands/manuals/touch.txt +0 -11
  271. package/src/commands/manuals/tr.txt +0 -10
  272. package/src/commands/manuals/trap.txt +0 -10
  273. package/src/commands/manuals/true.txt +0 -10
  274. package/src/commands/manuals/type.txt +0 -10
  275. package/src/commands/manuals/uname.txt +0 -12
  276. package/src/commands/manuals/uniq.txt +0 -12
  277. package/src/commands/manuals/unset.txt +0 -10
  278. package/src/commands/manuals/uptime.txt +0 -11
  279. package/src/commands/manuals/wc.txt +0 -12
  280. package/src/commands/manuals/wget.txt +0 -12
  281. package/src/commands/manuals/which.txt +0 -10
  282. package/src/commands/manuals/whoami.txt +0 -10
  283. package/src/commands/manuals/xargs.txt +0 -10
  284. package/src/commands/manuals-bundle.ts +0 -898
  285. package/src/commands/mkdir.ts +0 -31
  286. package/src/commands/mv.ts +0 -50
  287. package/src/commands/nano.ts +0 -38
  288. package/src/commands/neofetch.ts +0 -53
  289. package/src/commands/node.ts +0 -341
  290. package/src/commands/npm.ts +0 -132
  291. package/src/commands/passwd.ts +0 -50
  292. package/src/commands/ping.ts +0 -32
  293. package/src/commands/printf.ts +0 -129
  294. package/src/commands/ps.ts +0 -58
  295. package/src/commands/pwd.ts +0 -9
  296. package/src/commands/python.ts +0 -2229
  297. package/src/commands/read.ts +0 -46
  298. package/src/commands/registry.ts +0 -249
  299. package/src/commands/rm.ts +0 -42
  300. package/src/commands/runtime.ts +0 -378
  301. package/src/commands/sed.ts +0 -68
  302. package/src/commands/seq.ts +0 -43
  303. package/src/commands/set.ts +0 -29
  304. package/src/commands/sh.ts +0 -467
  305. package/src/commands/shift.ts +0 -63
  306. package/src/commands/sleep.ts +0 -20
  307. package/src/commands/sort.ts +0 -46
  308. package/src/commands/source.ts +0 -52
  309. package/src/commands/stat.ts +0 -61
  310. package/src/commands/su.ts +0 -72
  311. package/src/commands/sudo.ts +0 -76
  312. package/src/commands/tail.ts +0 -53
  313. package/src/commands/tar.ts +0 -102
  314. package/src/commands/tee.ts +0 -36
  315. package/src/commands/test.ts +0 -137
  316. package/src/commands/touch.ts +0 -28
  317. package/src/commands/tr.ts +0 -70
  318. package/src/commands/tree.ts +0 -20
  319. package/src/commands/true.ts +0 -27
  320. package/src/commands/type.ts +0 -48
  321. package/src/commands/uname.ts +0 -29
  322. package/src/commands/uniq.ts +0 -39
  323. package/src/commands/unset.ts +0 -17
  324. package/src/commands/uptime.ts +0 -54
  325. package/src/commands/wc.ts +0 -55
  326. package/src/commands/wget.ts +0 -148
  327. package/src/commands/which.ts +0 -37
  328. package/src/commands/who.ts +0 -25
  329. package/src/commands/whoami.ts +0 -14
  330. package/src/commands/xargs.ts +0 -31
  331. package/src/index.ts +0 -67
  332. package/src/modules/linuxRootfs.ts +0 -1961
  333. package/src/modules/neofetch.ts +0 -358
  334. package/src/modules/shellInteractive.ts +0 -57
  335. package/src/modules/shellRuntime.ts +0 -76
  336. package/src/self-standalone.ts +0 -542
  337. package/src/standalone-wo-sftp.ts +0 -38
  338. package/src/standalone.ts +0 -72
  339. package/src/types/commands.ts +0 -146
  340. package/src/types/pipeline.ts +0 -52
  341. package/src/types/streams.ts +0 -32
  342. package/src/types/tar-stream.d.ts +0 -38
  343. package/src/types/vfs.ts +0 -98
  344. package/src/utils/expand.ts +0 -491
  345. package/src/utils/perfLogger.ts +0 -72
  346. package/src/utils/tokenize.ts +0 -98
  347. package/src/utils/vfsDiff.ts +0 -275
  348. package/tests/command-helpers.test.ts +0 -116
  349. package/tests/commands-admin-net.test.ts +0 -441
  350. package/tests/commands-advanced.test.ts +0 -456
  351. package/tests/commands-core.test.ts +0 -562
  352. package/tests/commands-missing.test.ts +0 -570
  353. package/tests/commands-specific-units.test.ts +0 -327
  354. package/tests/commands-text-sys.test.ts +0 -445
  355. package/tests/expand.test.ts +0 -170
  356. package/tests/helpers.test.ts +0 -97
  357. package/tests/new-features.test.ts +0 -1036
  358. package/tests/parser-executor.test.ts +0 -37
  359. package/tests/sftp.test.ts +0 -323
  360. package/tests/ssh-exec.test.ts +0 -45
  361. package/tests/test-helper.ts +0 -79
  362. package/tests/users.test.ts +0 -86
  363. package/tsconfig.json +0 -49
  364. 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.2-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
- });