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.
- package/README.md +43 -23
- package/dist/.tsbuildinfo +1 -0
- package/dist/SSHMimic/executor.js +23 -5
- package/dist/commands/basename.d.ts +13 -0
- package/dist/commands/basename.js +45 -0
- package/dist/commands/file.d.ts +8 -0
- package/dist/commands/file.js +57 -0
- package/dist/commands/fun.d.ts +32 -0
- package/dist/commands/fun.js +172 -0
- package/dist/commands/ifconfig.d.ts +7 -0
- package/dist/commands/ifconfig.js +52 -0
- package/dist/commands/last.d.ts +13 -0
- package/dist/commands/last.js +68 -0
- package/dist/commands/manuals-bundle.js +598 -6
- package/dist/commands/registry.js +24 -2
- package/dist/commands/runtime.js +159 -106
- package/dist/commands/sh.js +5 -0
- package/dist/commands/tput.d.ts +13 -0
- package/dist/commands/tput.js +76 -0
- package/dist/commands/w.d.ts +7 -0
- package/dist/commands/w.js +38 -0
- package/dist/utils/expand.d.ts +12 -0
- package/dist/utils/expand.js +84 -0
- package/package.json +9 -3
- package/.github/ISSUE_TEMPLATE/bug_report.yml +0 -50
- package/.github/ISSUE_TEMPLATE/feature_request.yml +0 -31
- package/.github/dependabot.yml +0 -27
- package/.github/pull_request_template.md +0 -21
- package/.github/workflows/create-pull-request.yml +0 -85
- package/.github/workflows/publish.yml +0 -25
- package/.github/workflows/test-battery.yml +0 -102
- package/.vscode/settings.json +0 -20
- package/CODE_OF_CONDUCT.md +0 -39
- package/CONTRIBUTING.md +0 -59
- package/HONEYPOT.md +0 -358
- package/SECURITY.md +0 -33
- package/benchmark-results.txt +0 -40
- package/benchmark-virtualshell.ts +0 -88
- package/biome.json +0 -37
- package/build.js +0 -22
- package/builds/fortune-nyx-v1.5.1-directbash-k6.1.0.mjs +0 -1768
- package/builds/fortune-nyx-v1.5.1-ssh-nosftp.js +0 -1768
- package/builds/fortune-nyx-v1.5.1-ssh.cjs +0 -1769
- package/builds/fortune-nyx-v1.5.1-web.min.js +0 -17022
- package/bun.lock +0 -244
- package/docs/.nojekyll +0 -1
- package/docs/app.js +0 -1755
- package/docs/assets/hierarchy.js +0 -1
- package/docs/assets/highlight.css +0 -162
- package/docs/assets/icons.js +0 -18
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -60
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1633
- package/docs/classes/HoneyPot.html +0 -31
- package/docs/classes/IdleManager.html +0 -162
- package/docs/classes/SshClient.html +0 -66
- package/docs/classes/VirtualFileSystem.html +0 -279
- package/docs/classes/VirtualPackageManager.html +0 -63
- package/docs/classes/VirtualSftpServer.html +0 -169
- package/docs/classes/VirtualShell.html +0 -285
- package/docs/classes/VirtualSshServer.html +0 -182
- package/docs/classes/VirtualUserManager.html +0 -276
- package/docs/demo.html +0 -82
- package/docs/functions/assertDiff.html +0 -6
- package/docs/functions/diffSnapshots.html +0 -7
- package/docs/functions/formatDiff.html +0 -6
- package/docs/functions/getArg.html +0 -13
- package/docs/functions/getFlag.html +0 -15
- package/docs/functions/ifFlag.html +0 -11
- package/docs/hierarchy.html +0 -1
- package/docs/index.html +0 -1869
- package/docs/interfaces/AuditLogEntry.html +0 -6
- package/docs/interfaces/CommandContext.html +0 -22
- package/docs/interfaces/CommandResult.html +0 -26
- package/docs/interfaces/ExecStream.html +0 -11
- package/docs/interfaces/HoneyPotStats.html +0 -16
- package/docs/interfaces/IdleManagerOptions.html +0 -7
- package/docs/interfaces/InstalledPackage.html +0 -20
- package/docs/interfaces/NanoEditorSession.html +0 -8
- package/docs/interfaces/PackageDefinition.html +0 -30
- package/docs/interfaces/PackageFile.html +0 -8
- package/docs/interfaces/PasswordChallenge.html +0 -16
- package/docs/interfaces/RemoveOptions.html +0 -4
- package/docs/interfaces/ShellEnv.html +0 -6
- package/docs/interfaces/ShellModule.html +0 -14
- package/docs/interfaces/ShellProperties.html +0 -14
- package/docs/interfaces/ShellStream.html +0 -11
- package/docs/interfaces/SudoChallenge.html +0 -24
- package/docs/interfaces/VfsBaseNode.html +0 -12
- package/docs/interfaces/VfsDiff.html +0 -10
- package/docs/interfaces/VfsDiffEntry.html +0 -6
- package/docs/interfaces/VfsDiffModified.html +0 -10
- package/docs/interfaces/VfsDirectoryNode.html +0 -15
- package/docs/interfaces/VfsFileNode.html +0 -17
- package/docs/interfaces/VfsOptions.html +0 -26
- package/docs/interfaces/VfsSnapshot.html +0 -3
- package/docs/interfaces/VfsSnapshotBaseNode.html +0 -8
- package/docs/interfaces/VfsSnapshotDirectoryNode.html +0 -10
- package/docs/interfaces/VfsSnapshotFileNode.html +0 -12
- package/docs/interfaces/VirtualActiveSession.html +0 -12
- package/docs/interfaces/VirtualSftpServerOptions.html +0 -7
- package/docs/interfaces/VirtualShellVfsLike.html +0 -15
- package/docs/interfaces/VirtualShellVfsOptions.html +0 -3
- package/docs/interfaces/WriteFileOptions.html +0 -6
- package/docs/media/LICENSE +0 -21
- package/docs/modules.html +0 -1
- package/docs/types/ArgParseOptions.html +0 -4
- package/docs/types/CommandMode.html +0 -2
- package/docs/types/CommandOutcome.html +0 -2
- package/docs/types/IdleState.html +0 -1
- package/docs/types/VfsNodeStats.html +0 -2
- package/docs/types/VfsNodeType.html +0 -2
- package/docs/types/VfsPersistenceMode.html +0 -5
- package/docs/types/VfsSnapshotNode.html +0 -2
- package/examples/README.md +0 -288
- package/examples/app.js +0 -1755
- package/examples/app.ts +0 -299
- package/examples/build.js +0 -27
- package/examples/demo.html +0 -33
- package/examples/honeypot-audit.ts +0 -180
- package/examples/honeypot-export.ts +0 -253
- package/examples/honeypot-quickstart.ts +0 -110
- package/examples/index.html +0 -82
- package/examples/server.js +0 -55
- package/polyfills/buffer.js +0 -117
- package/polyfills/node_child_process/index.js +0 -2
- package/polyfills/node_crypto/index.js +0 -167
- package/polyfills/node_events/index.js +0 -9
- package/polyfills/node_fs/index.js +0 -202
- package/polyfills/node_fs/promises.js +0 -4
- package/polyfills/node_os/index.js +0 -9
- package/polyfills/node_path/index.js +0 -28
- package/polyfills/node_vm/index.js +0 -7
- package/polyfills/node_zlib/index.js +0 -3
- package/polyfills/process.js +0 -14
- package/polyfills/ssh2/index.js +0 -75
- package/scripts/build-all.mjs +0 -226
- package/scripts/build-names.mjs +0 -43
- package/scripts/generate-manuals-bundle.mjs +0 -49
- package/scripts/postinstall.js +0 -42
- package/scripts/publish-package.sh +0 -70
- package/src/Honeypot/index.ts +0 -457
- package/src/SSHClient/index.ts +0 -270
- package/src/SSHMimic/exec.ts +0 -49
- package/src/SSHMimic/executor.ts +0 -251
- package/src/SSHMimic/hostKey.ts +0 -21
- package/src/SSHMimic/index.ts +0 -337
- package/src/SSHMimic/loginBanner.ts +0 -36
- package/src/SSHMimic/loginFormat.ts +0 -10
- package/src/SSHMimic/prompt.ts +0 -14
- package/src/SSHMimic/sftp.ts +0 -883
- package/src/VirtualFileSystem/binaryPack.ts +0 -258
- package/src/VirtualFileSystem/index.ts +0 -1193
- package/src/VirtualFileSystem/internalTypes.ts +0 -43
- package/src/VirtualFileSystem/journal.ts +0 -171
- package/src/VirtualFileSystem/path.ts +0 -74
- package/src/VirtualPackageManager/index.ts +0 -1006
- package/src/VirtualShell/idleManager.ts +0 -137
- package/src/VirtualShell/index.ts +0 -475
- package/src/VirtualShell/shell.ts +0 -700
- package/src/VirtualShell/shellParser.ts +0 -285
- package/src/VirtualUserManager/index.ts +0 -758
- package/src/bun.d.ts +0 -1
- package/src/commands/adduser.ts +0 -103
- package/src/commands/alias.ts +0 -69
- package/src/commands/apt.ts +0 -233
- package/src/commands/awk.ts +0 -168
- package/src/commands/base64.ts +0 -29
- package/src/commands/cat.ts +0 -52
- package/src/commands/cd.ts +0 -25
- package/src/commands/chmod.ts +0 -85
- package/src/commands/clear.ts +0 -15
- package/src/commands/command-helpers.ts +0 -286
- package/src/commands/cp.ts +0 -83
- package/src/commands/curl.ts +0 -147
- package/src/commands/cut.ts +0 -36
- package/src/commands/date.ts +0 -30
- package/src/commands/declare.ts +0 -49
- package/src/commands/deluser.ts +0 -98
- package/src/commands/df.ts +0 -23
- package/src/commands/diff.ts +0 -43
- package/src/commands/dpkg.ts +0 -180
- package/src/commands/du.ts +0 -56
- package/src/commands/echo.ts +0 -58
- package/src/commands/env.ts +0 -23
- package/src/commands/exit.ts +0 -18
- package/src/commands/export.ts +0 -34
- package/src/commands/find.ts +0 -68
- package/src/commands/free.ts +0 -47
- package/src/commands/grep.ts +0 -116
- package/src/commands/groups.ts +0 -19
- package/src/commands/gzip.ts +0 -88
- package/src/commands/head.ts +0 -52
- package/src/commands/help.ts +0 -152
- package/src/commands/helpers.ts +0 -234
- package/src/commands/history.ts +0 -34
- package/src/commands/hostname.ts +0 -14
- package/src/commands/htop.ts +0 -20
- package/src/commands/id.ts +0 -19
- package/src/commands/index.ts +0 -9
- package/src/commands/kill.ts +0 -19
- package/src/commands/ln.ts +0 -71
- package/src/commands/ls.ts +0 -243
- package/src/commands/lsb-release.ts +0 -63
- package/src/commands/man.ts +0 -31
- package/src/commands/manuals/adduser.txt +0 -11
- package/src/commands/manuals/apt-cache.txt +0 -12
- package/src/commands/manuals/apt.txt +0 -20
- package/src/commands/manuals/awk.txt +0 -13
- package/src/commands/manuals/cat.txt +0 -14
- package/src/commands/manuals/cd.txt +0 -16
- package/src/commands/manuals/chmod.txt +0 -16
- package/src/commands/manuals/clear.txt +0 -10
- package/src/commands/manuals/cp.txt +0 -10
- package/src/commands/manuals/curl.txt +0 -20
- package/src/commands/manuals/date.txt +0 -14
- package/src/commands/manuals/declare.txt +0 -12
- package/src/commands/manuals/deluser.txt +0 -10
- package/src/commands/manuals/df.txt +0 -10
- package/src/commands/manuals/dpkg-query.txt +0 -11
- package/src/commands/manuals/dpkg.txt +0 -14
- package/src/commands/manuals/du.txt +0 -11
- package/src/commands/manuals/echo.txt +0 -11
- package/src/commands/manuals/false.txt +0 -10
- package/src/commands/manuals/find.txt +0 -11
- package/src/commands/manuals/free.txt +0 -12
- package/src/commands/manuals/grep.txt +0 -13
- package/src/commands/manuals/groups.txt +0 -10
- package/src/commands/manuals/gzip.txt +0 -11
- package/src/commands/manuals/head.txt +0 -10
- package/src/commands/manuals/help.txt +0 -11
- package/src/commands/manuals/history.txt +0 -11
- package/src/commands/manuals/hostname.txt +0 -10
- package/src/commands/manuals/id.txt +0 -10
- package/src/commands/manuals/kill.txt +0 -13
- package/src/commands/manuals/ls.txt +0 -20
- package/src/commands/manuals/lsb_release.txt +0 -14
- package/src/commands/manuals/mkdir.txt +0 -10
- package/src/commands/manuals/mv.txt +0 -10
- package/src/commands/manuals/nano.txt +0 -11
- package/src/commands/manuals/neofetch.txt +0 -10
- package/src/commands/manuals/node.txt +0 -13
- package/src/commands/manuals/npm.txt +0 -13
- package/src/commands/manuals/npx.txt +0 -13
- package/src/commands/manuals/passwd.txt +0 -11
- package/src/commands/manuals/ping.txt +0 -10
- package/src/commands/manuals/printf.txt +0 -11
- package/src/commands/manuals/ps.txt +0 -10
- package/src/commands/manuals/pwd.txt +0 -10
- package/src/commands/manuals/python3.txt +0 -13
- package/src/commands/manuals/readlink.txt +0 -10
- package/src/commands/manuals/return.txt +0 -10
- package/src/commands/manuals/rm.txt +0 -10
- package/src/commands/manuals/sed.txt +0 -11
- package/src/commands/manuals/set.txt +0 -11
- package/src/commands/manuals/shift.txt +0 -10
- package/src/commands/manuals/sleep.txt +0 -10
- package/src/commands/manuals/sort.txt +0 -12
- package/src/commands/manuals/source.txt +0 -11
- package/src/commands/manuals/ssh.txt +0 -11
- package/src/commands/manuals/stat.txt +0 -10
- package/src/commands/manuals/su.txt +0 -13
- package/src/commands/manuals/sudo.txt +0 -11
- package/src/commands/manuals/tail.txt +0 -10
- package/src/commands/manuals/tar.txt +0 -19
- package/src/commands/manuals/tee.txt +0 -10
- package/src/commands/manuals/test.txt +0 -11
- package/src/commands/manuals/touch.txt +0 -11
- package/src/commands/manuals/tr.txt +0 -10
- package/src/commands/manuals/trap.txt +0 -10
- package/src/commands/manuals/true.txt +0 -10
- package/src/commands/manuals/type.txt +0 -10
- package/src/commands/manuals/uname.txt +0 -12
- package/src/commands/manuals/uniq.txt +0 -12
- package/src/commands/manuals/unset.txt +0 -10
- package/src/commands/manuals/uptime.txt +0 -11
- package/src/commands/manuals/wc.txt +0 -12
- package/src/commands/manuals/wget.txt +0 -12
- package/src/commands/manuals/which.txt +0 -10
- package/src/commands/manuals/whoami.txt +0 -10
- package/src/commands/manuals/xargs.txt +0 -10
- package/src/commands/manuals-bundle.ts +0 -898
- package/src/commands/mkdir.ts +0 -31
- package/src/commands/mv.ts +0 -50
- package/src/commands/nano.ts +0 -38
- package/src/commands/neofetch.ts +0 -53
- package/src/commands/node.ts +0 -341
- package/src/commands/npm.ts +0 -132
- package/src/commands/passwd.ts +0 -50
- package/src/commands/ping.ts +0 -32
- package/src/commands/printf.ts +0 -129
- package/src/commands/ps.ts +0 -58
- package/src/commands/pwd.ts +0 -9
- package/src/commands/python.ts +0 -2229
- package/src/commands/read.ts +0 -46
- package/src/commands/registry.ts +0 -249
- package/src/commands/rm.ts +0 -42
- package/src/commands/runtime.ts +0 -378
- package/src/commands/sed.ts +0 -68
- package/src/commands/seq.ts +0 -43
- package/src/commands/set.ts +0 -29
- package/src/commands/sh.ts +0 -467
- package/src/commands/shift.ts +0 -63
- package/src/commands/sleep.ts +0 -20
- package/src/commands/sort.ts +0 -46
- package/src/commands/source.ts +0 -52
- package/src/commands/stat.ts +0 -61
- package/src/commands/su.ts +0 -72
- package/src/commands/sudo.ts +0 -76
- package/src/commands/tail.ts +0 -53
- package/src/commands/tar.ts +0 -102
- package/src/commands/tee.ts +0 -36
- package/src/commands/test.ts +0 -137
- package/src/commands/touch.ts +0 -28
- package/src/commands/tr.ts +0 -70
- package/src/commands/tree.ts +0 -20
- package/src/commands/true.ts +0 -27
- package/src/commands/type.ts +0 -48
- package/src/commands/uname.ts +0 -29
- package/src/commands/uniq.ts +0 -39
- package/src/commands/unset.ts +0 -17
- package/src/commands/uptime.ts +0 -54
- package/src/commands/wc.ts +0 -55
- package/src/commands/wget.ts +0 -148
- package/src/commands/which.ts +0 -37
- package/src/commands/who.ts +0 -25
- package/src/commands/whoami.ts +0 -14
- package/src/commands/xargs.ts +0 -31
- package/src/index.ts +0 -67
- package/src/modules/linuxRootfs.ts +0 -1961
- package/src/modules/neofetch.ts +0 -358
- package/src/modules/shellInteractive.ts +0 -57
- package/src/modules/shellRuntime.ts +0 -76
- package/src/self-standalone.ts +0 -542
- package/src/standalone-wo-sftp.ts +0 -38
- package/src/standalone.ts +0 -72
- package/src/types/commands.ts +0 -146
- package/src/types/pipeline.ts +0 -52
- package/src/types/streams.ts +0 -32
- package/src/types/tar-stream.d.ts +0 -38
- package/src/types/vfs.ts +0 -98
- package/src/utils/expand.ts +0 -491
- package/src/utils/perfLogger.ts +0 -72
- package/src/utils/tokenize.ts +0 -98
- package/src/utils/vfsDiff.ts +0 -275
- package/tests/command-helpers.test.ts +0 -116
- package/tests/commands-admin-net.test.ts +0 -441
- package/tests/commands-advanced.test.ts +0 -456
- package/tests/commands-core.test.ts +0 -562
- package/tests/commands-missing.test.ts +0 -570
- package/tests/commands-specific-units.test.ts +0 -327
- package/tests/commands-text-sys.test.ts +0 -445
- package/tests/expand.test.ts +0 -170
- package/tests/helpers.test.ts +0 -97
- package/tests/new-features.test.ts +0 -1036
- package/tests/parser-executor.test.ts +0 -37
- package/tests/sftp.test.ts +0 -323
- package/tests/ssh-exec.test.ts +0 -45
- package/tests/test-helper.ts +0 -79
- package/tests/users.test.ts +0 -86
- package/tsconfig.json +0 -49
- 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, '&').replace(/</g, '<');
|
|
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...');
|
package/examples/demo.html
DELETED
|
@@ -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
|
-
});
|