@aikidosec/safe-chain 1.1.6 → 1.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aikidosec/safe-chain",
3
- "version": "1.1.6",
3
+ "version": "1.1.7",
4
4
  "scripts": {
5
5
  "test": "node --test --experimental-test-module-mocks 'src/**/*.spec.js'",
6
6
  "test:watch": "node --test --watch --experimental-test-module-mocks 'src/**/*.spec.js'",
package/src/main.js CHANGED
@@ -11,6 +11,21 @@ export async function main(args) {
11
11
  const proxy = createSafeChainProxy();
12
12
  await proxy.startServer();
13
13
 
14
+ // Global error handlers to log unhandled errors
15
+ process.on("uncaughtException", (error) => {
16
+ ui.writeError(`Safe-chain: Uncaught exception: ${error.message}`);
17
+ ui.writeVerbose(`Stack trace: ${error.stack}`);
18
+ process.exit(1);
19
+ });
20
+
21
+ process.on("unhandledRejection", (reason) => {
22
+ ui.writeError(`Safe-chain: Unhandled promise rejection: ${reason}`);
23
+ if (reason instanceof Error) {
24
+ ui.writeVerbose(`Stack trace: ${reason.stack}`);
25
+ }
26
+ process.exit(1);
27
+ });
28
+
14
29
  try {
15
30
  // This parses all the --safe-chain arguments and removes them from the args array
16
31
  args = initializeCliArguments(args);
@@ -1,6 +1,7 @@
1
1
  import https from "https";
2
2
  import { generateCertForHost } from "./certUtils.js";
3
3
  import { HttpsProxyAgent } from "https-proxy-agent";
4
+ import { ui } from "../environment/userInteraction.js";
4
5
 
5
6
  export function mitmConnect(req, clientSocket, isAllowed) {
6
7
  const { hostname } = new URL(`http://${req.url}`);
@@ -13,6 +14,15 @@ export function mitmConnect(req, clientSocket, isAllowed) {
13
14
 
14
15
  const server = createHttpsServer(hostname, isAllowed);
15
16
 
17
+ server.on("error", (err) => {
18
+ ui.writeError(`Safe-chain: HTTPS server error: ${err.message}`);
19
+ if (!clientSocket.headersSent) {
20
+ clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
21
+ } else if (clientSocket.writable) {
22
+ clientSocket.end();
23
+ }
24
+ });
25
+
16
26
  // Establish the connection
17
27
  clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
18
28
 
@@ -37,13 +47,15 @@ function createHttpsServer(hostname, isAllowed) {
37
47
  forwardRequest(req, hostname, res);
38
48
  }
39
49
 
40
- return https.createServer(
50
+ const server = https.createServer(
41
51
  {
42
52
  key: cert.privateKey,
43
53
  cert: cert.certificate,
44
54
  },
45
55
  handleRequest
46
56
  );
57
+
58
+ return server;
47
59
  }
48
60
 
49
61
  function getRequestPathAndQuery(url) {
@@ -62,6 +74,11 @@ function forwardRequest(req, hostname, res) {
62
74
  res.end("Bad Gateway");
63
75
  });
64
76
 
77
+ req.on("error", (err) => {
78
+ ui.writeError(`Safe-chain: Error reading client request: ${err.message}`);
79
+ proxyReq.destroy();
80
+ });
81
+
65
82
  req.on("data", (chunk) => {
66
83
  proxyReq.write(chunk);
67
84
  });
@@ -88,6 +105,16 @@ function createProxyRequest(hostname, req, res) {
88
105
  }
89
106
 
90
107
  const proxyReq = https.request(options, (proxyRes) => {
108
+ proxyRes.on("error", (err) => {
109
+ ui.writeError(
110
+ `Safe-chain: Error reading upstream response: ${err.message}`
111
+ );
112
+ if (!res.headersSent) {
113
+ res.writeHead(502);
114
+ res.end("Bad Gateway");
115
+ }
116
+ });
117
+
91
118
  res.writeHead(proxyRes.statusCode, proxyRes.headers);
92
119
  proxyRes.pipe(res);
93
120
  });
@@ -43,8 +43,13 @@ export function handleHttpProxyRequest(req, res) {
43
43
  }
44
44
  )
45
45
  .on("error", (err) => {
46
- res.writeHead(502);
47
- res.end(`Bad Gateway: ${err.message}`);
46
+ if (!res.headersSent) {
47
+ res.writeHead(502);
48
+ res.end(`Bad Gateway: ${err.message}`);
49
+ } else {
50
+ // Headers already sent, just destroy the response
51
+ res.destroy();
52
+ }
48
53
  });
49
54
 
50
55
  req.on("error", () => {
@@ -24,12 +24,6 @@ export function tunnelRequest(req, clientSocket, head) {
24
24
  function tunnelRequestToDestination(req, clientSocket, head) {
25
25
  const { port, hostname } = new URL(`http://${req.url}`);
26
26
 
27
- clientSocket.on("error", () => {
28
- // NO-OP
29
- // This can happen if the client TCP socket sends RST instead of FIN.
30
- // Not subscribing to 'close' event will cause node to throw and crash.
31
- });
32
-
33
27
  const serverSocket = net.connect(port || 443, hostname, () => {
34
28
  clientSocket.write("HTTP/1.1 200 Connection Established\r\n\r\n");
35
29
  serverSocket.write(head);
@@ -37,6 +31,14 @@ function tunnelRequestToDestination(req, clientSocket, head) {
37
31
  clientSocket.pipe(serverSocket);
38
32
  });
39
33
 
34
+ clientSocket.on("error", () => {
35
+ // This can happen if the client TCP socket sends RST instead of FIN.
36
+ // Not subscribing to 'error' event will cause node to throw and crash.
37
+ if (serverSocket.writable) {
38
+ serverSocket.end();
39
+ }
40
+ });
41
+
40
42
  serverSocket.on("error", (err) => {
41
43
  ui.writeError(
42
44
  `Safe-chain: error connecting to ${hostname}:${port} - ${err.message}`
@@ -103,6 +105,13 @@ function tunnelRequestViaProxy(req, clientSocket, head, proxyUrl) {
103
105
  if (clientSocket.writable) {
104
106
  clientSocket.end("HTTP/1.1 502 Bad Gateway\r\n\r\n");
105
107
  }
108
+ } else {
109
+ ui.writeError(
110
+ `Safe-chain: proxy socket error after connection - ${err.message}`
111
+ );
112
+ if (clientSocket.writable) {
113
+ clientSocket.end();
114
+ }
106
115
  }
107
116
  });
108
117