diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 29fcb5abbf..00a620955e 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -96,6 +96,8 @@ API • |nvim_clear_autocmds()| no longer treats an empty array event as nil. • |vim.o|, |vim.opt|, and |nvim_set_option_value()| expand `~` and environment variables (|expand-env|). +• Security: The |TUI| (also with |--remote-ui|) rejects server-to-client API + calls. Only UI events are allowed. DIAGNOSTICS diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index fc08084eeb..c9df280746 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -314,6 +314,15 @@ static void handle_request(Channel *channel, Unpacker *p, Array args) { assert(p->type == kMessageTypeRequest || p->type == kMessageTypeNotification); + // SECURITY: only allow UI events, disallow server-to-client API calls. Else a malicious (remote) + // server could run arbitrary code in the local UI process. + if (p->handler.fn && p->handler.fn != handle_nvim_error_event + && ui_client_channel_id && channel->id == ui_client_channel_id) { + api_set_error(&p->unpack_error, kErrorTypeException, "UI client does not accept API calls: %s", + p->handler.name); + p->handler.fn = NULL; + } + if (!p->handler.fn) { send_error(channel, p->handler, p->type, p->request_id, p->unpack_error.msg); api_clear_error(&p->unpack_error); diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua index a8c5e5efa7..3374e95bb3 100644 --- a/test/functional/terminal/tui_spec.lua +++ b/test/functional/terminal/tui_spec.lua @@ -3466,6 +3466,15 @@ describe('TUI', function() end) end) + it('security: server-to-client API calls are rejected', function() + local ok, err = unpack(child_exec_lua([[ + local ui = vim.api.nvim_list_uis()[1].chan + return { pcall(vim.rpcrequest, ui, 'nvim_exec_lua', 'return vim.fn.getpid()', {}) } + ]])) + eq(false, ok) + t.matches('UI client does not accept API calls: nvim_exec_lua', err) + end) + it('stdin and stdout are tty fds in embedded server #38172', function() eq( { 'tty', 'tty' },