openpen 0.2.0

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 (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +30 -0
  3. package/dist/checks/auth-bypass.d.ts +12 -0
  4. package/dist/checks/auth-bypass.js +93 -0
  5. package/dist/checks/bac.d.ts +12 -0
  6. package/dist/checks/bac.js +107 -0
  7. package/dist/checks/base.d.ts +22 -0
  8. package/dist/checks/base.js +13 -0
  9. package/dist/checks/index.d.ts +7 -0
  10. package/dist/checks/index.js +40 -0
  11. package/dist/checks/llm-leak.d.ts +23 -0
  12. package/dist/checks/llm-leak.js +251 -0
  13. package/dist/checks/mass-assignment.d.ts +12 -0
  14. package/dist/checks/mass-assignment.js +169 -0
  15. package/dist/checks/prompt-injection.d.ts +23 -0
  16. package/dist/checks/prompt-injection.js +262 -0
  17. package/dist/checks/security-headers.d.ts +12 -0
  18. package/dist/checks/security-headers.js +133 -0
  19. package/dist/checks/sensitive-data.d.ts +12 -0
  20. package/dist/checks/sensitive-data.js +122 -0
  21. package/dist/checks/sqli.d.ts +12 -0
  22. package/dist/checks/sqli.js +178 -0
  23. package/dist/checks/ssrf.d.ts +12 -0
  24. package/dist/checks/ssrf.js +126 -0
  25. package/dist/checks/xss.d.ts +12 -0
  26. package/dist/checks/xss.js +79 -0
  27. package/dist/cli.d.ts +5 -0
  28. package/dist/cli.js +300 -0
  29. package/dist/fuzzer/engine.d.ts +27 -0
  30. package/dist/fuzzer/engine.js +126 -0
  31. package/dist/fuzzer/mutator.d.ts +8 -0
  32. package/dist/fuzzer/mutator.js +54 -0
  33. package/dist/fuzzer/payloads.d.ts +13 -0
  34. package/dist/fuzzer/payloads.js +167 -0
  35. package/dist/reporter/index.d.ts +5 -0
  36. package/dist/reporter/index.js +5 -0
  37. package/dist/reporter/json.d.ts +5 -0
  38. package/dist/reporter/json.js +14 -0
  39. package/dist/reporter/terminal.d.ts +5 -0
  40. package/dist/reporter/terminal.js +59 -0
  41. package/dist/spec/openapi.d.ts +5 -0
  42. package/dist/spec/openapi.js +119 -0
  43. package/dist/spec/parser.d.ts +11 -0
  44. package/dist/spec/parser.js +45 -0
  45. package/dist/types.d.ts +145 -0
  46. package/dist/types.js +4 -0
  47. package/dist/utils/http.d.ts +37 -0
  48. package/dist/utils/http.js +92 -0
  49. package/dist/utils/logger.d.ts +8 -0
  50. package/dist/utils/logger.js +20 -0
  51. package/dist/ws/checks.d.ts +18 -0
  52. package/dist/ws/checks.js +558 -0
  53. package/dist/ws/engine.d.ts +47 -0
  54. package/dist/ws/engine.js +139 -0
  55. package/package.json +41 -0
@@ -0,0 +1,139 @@
1
+ /**
2
+ * WebSocket test engine
3
+ * Handles connections, message exchange, and response collection
4
+ */
5
+ import WebSocket from 'ws';
6
+ /**
7
+ * Open a WebSocket connection to the target
8
+ */
9
+ export function connect(url, options = {}) {
10
+ const timeout = options.timeout || 5000;
11
+ return new Promise((resolve, reject) => {
12
+ const ws = new WebSocket(url, {
13
+ headers: options.headers || {},
14
+ handshakeTimeout: timeout,
15
+ });
16
+ const conn = {
17
+ ws,
18
+ messages: [],
19
+ connected: false,
20
+ };
21
+ const timer = setTimeout(() => {
22
+ if (!conn.connected) {
23
+ ws.terminate();
24
+ reject(new Error(`Connection timeout after ${timeout}ms`));
25
+ }
26
+ }, timeout);
27
+ ws.on('open', () => {
28
+ clearTimeout(timer);
29
+ conn.connected = true;
30
+ resolve(conn);
31
+ });
32
+ ws.on('message', (data) => {
33
+ conn.messages.push({
34
+ direction: 'received',
35
+ data: data.toString(),
36
+ timestamp: Date.now(),
37
+ });
38
+ });
39
+ ws.on('close', (code, reason) => {
40
+ conn.connected = false;
41
+ conn.closedCode = code;
42
+ conn.closedReason = reason.toString();
43
+ });
44
+ ws.on('error', (err) => {
45
+ clearTimeout(timer);
46
+ if (!conn.connected) {
47
+ reject(err);
48
+ }
49
+ });
50
+ });
51
+ }
52
+ /**
53
+ * Send a message and wait for a response
54
+ */
55
+ export function sendAndWait(conn, data, options = {}) {
56
+ const timeout = options.timeout || 3000;
57
+ const startIdx = conn.messages.length;
58
+ return new Promise((resolve) => {
59
+ const timer = setTimeout(() => {
60
+ conn.ws.removeListener('message', onMessage);
61
+ resolve(null);
62
+ }, timeout);
63
+ const check = () => {
64
+ for (let i = startIdx; i < conn.messages.length; i++) {
65
+ const msg = conn.messages[i];
66
+ if (msg.direction === 'received') {
67
+ if (!options.matchFn || options.matchFn(msg.data)) {
68
+ clearTimeout(timer);
69
+ conn.ws.removeListener('message', onMessage);
70
+ resolve(msg.data);
71
+ return true;
72
+ }
73
+ }
74
+ }
75
+ return false;
76
+ };
77
+ const onMessage = () => { check(); };
78
+ conn.ws.on('message', onMessage);
79
+ conn.messages.push({
80
+ direction: 'sent',
81
+ data,
82
+ timestamp: Date.now(),
83
+ });
84
+ conn.ws.send(data);
85
+ // Check messages already received
86
+ check();
87
+ });
88
+ }
89
+ /**
90
+ * Send raw data (string or buffer) without recording
91
+ */
92
+ export function sendRaw(conn, data) {
93
+ conn.ws.send(data);
94
+ }
95
+ /**
96
+ * Close a connection gracefully
97
+ */
98
+ export function close(conn) {
99
+ return new Promise((resolve) => {
100
+ if (!conn.connected) {
101
+ resolve();
102
+ return;
103
+ }
104
+ conn.ws.on('close', () => resolve());
105
+ conn.ws.close();
106
+ setTimeout(() => resolve(), 1000);
107
+ });
108
+ }
109
+ /**
110
+ * Wait for a specific number of messages or timeout
111
+ */
112
+ export function waitForMessages(conn, count, timeout = 3000) {
113
+ const startIdx = conn.messages.length;
114
+ return new Promise((resolve) => {
115
+ const timer = setTimeout(() => {
116
+ resolve(conn.messages.slice(startIdx));
117
+ }, timeout);
118
+ const check = () => {
119
+ const received = conn.messages.slice(startIdx).filter(m => m.direction === 'received');
120
+ if (received.length >= count) {
121
+ clearTimeout(timer);
122
+ resolve(conn.messages.slice(startIdx));
123
+ }
124
+ };
125
+ conn.ws.on('message', () => check());
126
+ check();
127
+ });
128
+ }
129
+ /**
130
+ * Try to parse a message as JSON
131
+ */
132
+ export function parseJson(data) {
133
+ try {
134
+ return { parsed: true, value: JSON.parse(data) };
135
+ }
136
+ catch (e) {
137
+ return { parsed: false, error: e.message };
138
+ }
139
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "openpen",
3
+ "version": "0.2.0",
4
+ "description": "Open source CLI for API fuzzing and penetration testing",
5
+ "type": "module",
6
+ "bin": {
7
+ "openpen": "./dist/cli.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/cli.js",
12
+ "dev": "tsx src/cli.ts",
13
+ "test": "node --test dist/**/*.test.js"
14
+ },
15
+ "keywords": [
16
+ "api",
17
+ "security",
18
+ "fuzzing",
19
+ "pentest",
20
+ "owasp"
21
+ ],
22
+ "license": "MIT",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/tjamescouch/openpen"
26
+ },
27
+ "engines": {
28
+ "node": ">=18.0.0"
29
+ },
30
+ "dependencies": {
31
+ "chalk": "^5.0.0",
32
+ "commander": "^12.0.0",
33
+ "yaml": "^2.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "@types/node": "^20.0.0",
37
+ "@types/ws": "^8.18.1",
38
+ "tsx": "^4.0.0",
39
+ "typescript": "^5.3.0"
40
+ }
41
+ }