CVE-2018-7160
Description
The Node.js inspector, in 6.x and later is vulnerable to a DNS rebinding attack which could be exploited to perform remote code execution. An attack is possible from malicious websites open in a web browser on the same computer, or another computer with network access to the computer running the Node.js process. A malicious website could use a DNS rebinding attack to trick the web browser to bypass same-origin-policy checks and to allow HTTP connections to localhost or to hosts on the local network. If a Node.js process with the debug port active is running on localhost or on a host on the local network, the malicious website could connect to it as a debugger, and get full code execution access.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Node.js inspector in 6.x+ vulnerable to DNS rebinding allowing remote code execution from malicious websites.
Vulnerability
The Node.js inspector (debugger protocol) in versions 6.x and later, activated via --inspect or related flags, was vulnerable to a DNS rebinding attack. A malicious website could trick the browser into bypassing same-origin policy and connect to the inspector on localhost or local network, leading to full code execution. [1]
Exploitation
An attacker needs only a malicious website open in a browser on the same computer or a computer with network access to the victim's Node.js process. The attack uses DNS rebinding to bypass same-origin checks, making the browser think it is connecting to a legitimate external host while actually targeting the local Node.js inspector debug port. [1]
Impact
Successful exploitation grants the attacker full remote code execution on the Node.js process, as the debugger has full access to the Node.js runtime. This can lead to complete compromise of the application and potentially the host system. [1]
Mitigation
The vulnerability was fixed in Node.js 9.10.0 (Current), 8.11.0 (LTS "Carbon"), 6.14.0 (LTS "Boron"), and 4.9.0 (LTS "Argon") released March 2018. Users should upgrade to these versions. The fix validates the Host header to prevent DNS rebinding. [1][3]
AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
node-inspectornpm | >= 6.0 | — |
Affected products
18- ghsa-coords17 versionspkg:npm/node-inspectorpkg:rpm/suse/firefox-atk&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-cairo&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-gdk-pixbuf&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-glib2&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-gtk3&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-harfbuzz&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-libffi&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-libffi-gcc5&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/firefox-pango&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/MozillaFirefox-branding-SLED&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/MozillaFirefox&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/mozilla-nspr&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/mozilla-nss&distro=SUSE%20Linux%20Enterprise%20Server%2011%20SP4-LTSSpkg:rpm/suse/nodejs6&distro=SUSE%20Enterprise%20Storage%204pkg:rpm/suse/nodejs6&distro=SUSE%20Linux%20Enterprise%20Module%20for%20Web%20and%20Scripting%2012pkg:rpm/suse/nodejs6&distro=SUSE%20OpenStack%20Cloud%207
>= 6.0+ 16 more
- (no CPE)range: >= 6.0
- (no CPE)range: < 2.26.1-2.8.4
- (no CPE)range: < 1.15.10-2.13.4
- (no CPE)range: < 2.36.11-2.8.4
- (no CPE)range: < 2.54.3-2.14.7
- (no CPE)range: < 3.10.9-2.15.3
- (no CPE)range: < 1.7.5-2.7.4
- (no CPE)range: < 3.2.1.git259-2.3.3
- (no CPE)range: < 5.3.1+r233831-14.1
- (no CPE)range: < 1.40.14-2.7.4
- (no CPE)range: < 68-21.9.8
- (no CPE)range: < 68.2.0-78.51.4
- (no CPE)range: < 4.21-29.6.1
- (no CPE)range: < 3.45-38.9.3
- (no CPE)range: < 6.14.1-11.12.1
- (no CPE)range: < 6.14.1-11.12.1
- (no CPE)range: < 6.14.1-11.12.1
- The Node.js Project/Node.jsv5Range: ^6.0.0 || ^8.0.0 || ^9.0.0
Patches
1e3950d1a402binspector: check Host header
3 files changed · +84 −7
src/inspector_socket.cc+51 −7 modified@@ -393,12 +393,7 @@ static int header_value_cb(http_parser* parser, const char* at, size_t length) { auto inspector = static_cast<InspectorSocket*>(parser->data); auto state = inspector->http_parsing_state; state->parsing_value = true; - if (state->current_header.size() == sizeof(SEC_WEBSOCKET_KEY_HEADER) - 1 && - node::StringEqualNoCaseN(state->current_header.data(), - SEC_WEBSOCKET_KEY_HEADER, - sizeof(SEC_WEBSOCKET_KEY_HEADER) - 1)) { - state->ws_key.append(at, length); - } + state->headers[state->current_header].append(at, length); return 0; } @@ -471,10 +466,59 @@ static void handshake_failed(InspectorSocket* inspector) { // init_handshake references message_complete_cb static void init_handshake(InspectorSocket* inspector); +static std::string TrimPort(const std::string& host) { + size_t last_colon_pos = host.rfind(":"); + if (last_colon_pos == std::string::npos) + return host; + size_t bracket = host.rfind("]"); + if (bracket == std::string::npos || last_colon_pos > bracket) + return host.substr(0, last_colon_pos); + return host; +} + +static bool IsIPAddress(const std::string& host) { + if (host.length() >= 4 && host[0] == '[' && host[host.size() - 1] == ']') + return true; + int quads = 0; + for (char c : host) { + if (c == '.') + quads++; + else if (!isdigit(c)) + return false; + } + return quads == 3; +} + +static std::string HeaderValue(const struct http_parsing_state_s* state, + const std::string& header) { + bool header_found = false; + std::string value; + for (const auto& header_value : state->headers) { + if (node::StringEqualNoCaseN(header_value.first.data(), header.data(), + header.length())) { + if (header_found) + return ""; + value = header_value.second; + header_found = true; + } + } + return value; +} + +static bool IsAllowedHost(const std::string& host_with_port) { + std::string host = TrimPort(host_with_port); + return host.empty() || IsIPAddress(host) + || node::StringEqualNoCase(host.data(), "localhost") + || node::StringEqualNoCase(host.data(), "localhost6"); +} + static int message_complete_cb(http_parser* parser) { InspectorSocket* inspector = static_cast<InspectorSocket*>(parser->data); struct http_parsing_state_s* state = inspector->http_parsing_state; - if (parser->method != HTTP_GET) { + state->ws_key = HeaderValue(state, "Sec-WebSocket-Key"); + + if (!IsAllowedHost(HeaderValue(state, "Host")) || + parser->method != HTTP_GET) { handshake_failed(inspector); } else if (!parser->upgrade) { if (state->callback(inspector, kInspectorHandshakeHttpGet, state->path)) {
src/inspector_socket.h+2 −0 modified@@ -5,6 +5,7 @@ #include "util-inl.h" #include "uv.h" +#include <map> #include <string> #include <vector> @@ -37,6 +38,7 @@ struct http_parsing_state_s { std::string ws_key; std::string path; std::string current_header; + std::map<std::string, std::string> headers; }; struct ws_state_s {
test/cctest/test_inspector_socket.cc+31 −0 modified@@ -906,4 +906,35 @@ TEST_F(InspectorSocketTest, ErrorCleansUpTheSocket) { EXPECT_EQ(UV_EPROTO, err); } +static void HostCheckedForGet_handshake(enum inspector_handshake_event state, + const std::string& path, bool* cont) { + EXPECT_EQ(kInspectorHandshakeFailed, state); + EXPECT_TRUE(path.empty()); + *cont = false; +} + +TEST_F(InspectorSocketTest, HostCheckedForGet) { + handshake_delegate = HostCheckedForGet_handshake; + const char WRITE_REQUEST[] = "GET /respond/withtext HTTP/1.1\r\n" + "Host: notlocalhost:9222\r\n\r\n"; + send_in_chunks(WRITE_REQUEST, sizeof(WRITE_REQUEST) - 1); + + expect_handshake_failure(); + assert_both_sockets_closed(); +} + +TEST_F(InspectorSocketTest, HostCheckedForUpgrade) { + handshake_delegate = HostCheckedForGet_handshake; + const char UPGRADE_REQUEST[] = "GET /ws/path HTTP/1.1\r\n" + "Host: nonlocalhost:9229\r\n" + "Upgrade: websocket\r\n" + "Connection: Upgrade\r\n" + "Sec-WebSocket-Key: aaa==\r\n" + "Sec-WebSocket-Version: 13\r\n\r\n"; + send_in_chunks(UPGRADE_REQUEST, sizeof(UPGRADE_REQUEST) - 1); + + expect_handshake_failure(); + assert_both_sockets_closed(); +} + } // anonymous namespace
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-wq4c-wm6x-jw44ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2018-7160ghsaADVISORY
- github.com/nodejs/node/commit/e3950d1a402b80e4098a40aacddd6a104da0cfa9ghsaWEB
- nodejs.org/en/blog/vulnerability/march-2018-security-releasesghsaWEB
- nodejs.org/en/blog/vulnerability/march-2018-security-releases/mitrex_refsource_CONFIRM
- support.f5.com/csp/article/K63025104mitrex_refsource_CONFIRM
- support.f5.com/csp/article/K63025104ghsaWEB
- www.oracle.com//security-alerts/cpujul2021.htmlghsax_refsource_MISCWEB
News mentions
0No linked articles in our index yet.