File size: 6,280 Bytes
20f108c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { runTool, runPipe, formatExternal } from "../lib/runtime.mjs";
import { hackerTools } from "../lib/tools.mjs";

describe("runTool wrapper", () => {
  it("wraps a normal tool call", async () => {
    const r = await runTool(hackerTools, "shell", "echo hello");
    assert.match(r, /hello/);
  });

  it("returns error for unknown tool", async () => {
    const r = await runTool(hackerTools, "nonexistent_tool_xyz", "");
    assert.match(r, /Unknown tool/);
  });

  it("returns JSON when json=true", async () => {
    const r = await runTool(hackerTools, "shell", "echo hi", { json: true });
    const parsed = JSON.parse(r);
    assert.equal(parsed.ok, true);
    assert.equal(parsed.tool, "shell");
    assert.match(parsed.data, /hi/);
  });

  it("JSON error for unknown tool", async () => {
    const r = await runTool(hackerTools, "bad_tool", "", { json: true });
    const parsed = JSON.parse(r);
    assert.equal(parsed.ok, false);
    assert.match(parsed.error, /Unknown tool/);
  });
});

describe("runPipe chaining", () => {
  it("single tool works like normal run", async () => {
    const r = await runPipe(hackerTools, "shell|echo simple_pipe_test");
    assert.match(r, /simple_pipe_test/);
  });

  it("two-tool pipe feeds output to next tool", async () => {
    // shell -> hash (shell output becomes hash input)
    const r = await runPipe(hackerTools, "shell|echo testdata | hash");
    assert.match(r, /hash|testdata|[a-f0-9]/i);
  });

  it("single tool returns JSON with option", async () => {
    const r = await runPipe(hackerTools, "shell|echo json_ok", { json: true });
    const p = JSON.parse(r);
    assert.equal(p.ok, true);
  });

  it("handles empty chain gracefully", async () => {
    const r = await runPipe(hackerTools, "", {});
    assert.match(r, /empty/i);
  });
});

describe("formatExternal edge cases", () => {
  it("handles very long target names", () => {
    const long = "a".repeat(200);
    const r = formatExternal("Test", long, ["result"]);
    assert.match(r, new RegExp(long));
  });

  it("single line with maxLines=1", () => {
    const r = formatExternal("T", "x", ["a", "b", "c"], 1);
    assert.match(r, /and 2 more/);
  });

  it("empty lines array without target", () => {
    const r = formatExternal("Tool", "", []);
    assert.equal(r, "[Tool] No results for ");
  });
});

describe("CLI --json smoke", () => {
  it("--tool --json shell returns valid JSON", async () => {
    const { execSync } = await import("child_process");
    const out = execSync("node phantom.mjs --tool --json shell 'echo json_test_cli' 2>&1", { cwd: "/root/usb/Phantom", encoding: "utf-8", timeout: 10000 });
    const parsed = JSON.parse(out);
    assert.equal(parsed.ok, true);
    assert.equal(parsed.tool, "shell");
    assert.match(parsed.data, /json_test_cli/);
  });

  it("--tool --json with bad tool exits 1 with error", async () => {
    const { execSync } = await import("child_process");
    try {
      execSync("node phantom.mjs --tool --json bad_tool_xyz '' 2>&1", { cwd: "/root/usb/Phantom", encoding: "utf-8", timeout: 10000 });
      assert.fail("Should have thrown");
    } catch (e) {
      const out = e.stdout;
      const parsed = JSON.parse(out);
      assert.equal(parsed.ok, false);
      assert.match(parsed.error, /Unknown tool/);
    }
  });
});

describe("schedule tool", () => {
  it("returns usage for no args", async () => {
    const r = await hackerTools.schedule("");
    assert.match(r, /Usage/);
  });

  it("returns empty list when no schedules active", async () => {
    const r = await hackerTools.schedule("list");
    assert.match(r, /No active schedules/);
  });

  it("returns error for unknown tool in schedule", async () => {
    const r = await hackerTools.schedule("daily|bad_tool_xyz|target.com");
    assert.match(r, /Unknown tool/);
  });
});

describe("hackerone tool", () => {
  it("returns help for no args", async () => {
    const r = await hackerTools.hackerone("");
    assert.match(r, /HackerOne Tool/);
    assert.match(r, /programs/);
    assert.match(r, /scope/);
    assert.match(r, /reports/);
    assert.match(r, /report/);
    assert.match(r, /submit/);
    assert.match(r, /me/);
    assert.match(r, /test/);
  });

  it("returns help for 'help' command", async () => {
    const r = await hackerTools.hackerone("help");
    assert.match(r, /HackerOne Tool/);
  });

  it("returns help for 'list' command", async () => {
    const r = await hackerTools.hackerone("list");
    assert.match(r, /HackerOne Tool/);
  });

  it("handles 'programs' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone("programs");
    // Just verify it returns a string response (not an exception)
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("handles 'scope' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone("scope acme-corp");
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("handles 'reports' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone("reports acme-corp");
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("handles 'report' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone("report 1234567");
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("handles 'submit' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone('submit acme-corp "XSS" high "details"');
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("handles 'me' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone("me");
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("handles 'test' command (credentials may or may not work)", async () => {
    const r = await hackerTools.hackerone("test");
    assert.ok(typeof r === "string" && r.length > 0);
  });

  it("returns unknown command error for invalid command", async () => {
    const r = await hackerTools.hackerone("invalid_command");
    assert.match(r, /Unknown command/);
  });
});