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