CVE-2026-106173: FortiSIEM gRPC Path Traversal RCE Fortinet published advisory FG-IR-26-180 on 13 October 2026 for CVE-2026-106173, a critical path traversal in FortiSIEM's phQueryMaster gRPC service on tcp/27918 that allows unauthenticated attackers to write arbitrary files and achieve remote code execution. Horizon3 researchers found the service accepts connections without client certificates and that the SendQueryResult handler builds a file path from an unvalidated query-id, so a value like ../../../../../tmp/x escapes the query directory, with the streamed bytes becoming the file's contents. The flaw sits in a component Horizon3 had not previously examined, distinct from the phMonitor service on tcp/7900 behind its earlier FortiSIEM disclosures CVE-2023-34992, CVE-2024-23108 and CVE-2025-64155. On 13 October 2026, Fortinet published a security advisory https://fortiguard.fortinet.com/psirt/FG-IR-26-180 for a critical vulnerability affecting their FortiSIEM product. The vulnerability, CVE-2026-106173, allows for an arbitrary file write by abusing an issue in a gRPC service. Horizon3 is no stranger to the FortiSIEM. We’ve disclosed several critical vulnerabilities through the years that you can catch up on: 1. CVE-2023-34992: Fortinet FortiSIEM Command Injection Deep-Dive https://horizon3.ai/attack-research/disclosures/cve-2023-34992-fortinet-fortisiem-command-injection-deep-dive/ 2. CVE-2024-23108: Fortinet FortiSIEM 2nd Order Command Injection Deep-Dive https://horizon3.ai/attack-research/disclosures/cve-2024-23108-fortinet-fortisiem-2nd-order-command-injection-deep-dive/ 3. CVE-2025-64155: Three Years of Remotely Rooting the Fortinet FortiSIEM https://horizon3.ai/attack-research/disclosures/cve-2025-64155-three-years-of-remotely-rooting-the-fortinet-fortisiem/ All of our prior research has involved the same component, the phMonitor service which listens on port tcp/7900. This latest advisory details a new service that we had never looked at, a gRPC service on port tcp/27918. Given our familiarity and the intrigue of a new service to look at we dove in. Reaching the Vulnerable Service Looking at the listening services on the FortiSIEM, we find that phQueryMaster is bound to tcp/27918. The phQueryMaster service stands the gRPC server up in grpcNotificationServer::run . The listen port comes from the command port config value 7918 , which is passed through phSecureUtils::getGrpcPort and mapped to tcp/27918; the address is built as :: :27918 , so the service binds every interface. // grpcNotificationServer::run libphGrpcServices.so unsigned short port = mServerPort; // command port = 7918 std::string addr = " :: :" + phSecureUtils::getGrpcPort port ; // :: :27918 grpc::SslServerCredentialsOptions sslOps; // sslOps.client certificate request stays 0 == GRPC SSL DONT REQUEST CLIENT CERTIFICATE auto creds = grpc::SslServerCredentials sslOps ; builder.AddListeningPort addr, creds, 0 ; builder.RegisterService &svc ; builder.BuildAndStart ; Sometimes, gRPC servers can require client certificates for authentication, but here there server sets that option to false. This means any remote client can connect to the gRPC service on port tcp/27918 unauthenticated and without presenting a client certificate to reach the vulnerable gRPC service. The Path to Arbitrary File Write Now that we’ve found the vulnerable gRPC service, we inspect the available RPC methods and find SendQueryResult . message QueryResultReq { bytes file content = 1; } service phoenixSvc { rpc SendQueryResult stream QueryResultReq returns PhoenixReply ; } SendQueryResult ’s handler parses four values from the received message: query-id , src-ip , period-start , and period-end . The handler then constructs a file path with the lightly formatted src-ip and query-id. // grpcNotificationService::SendQueryResult grpcNotificationService.cpp replaceString srcIp, ".", " " ; std::string fileDir = "/query/result/" + queryId; if phMiscUtils::DirExists fileDir.c str phMiscUtils::mkdir fileDir.c str ; Bug 1 is that fileDir is built by string concatenation with an attacker controlled value, without any input validation. A query-id of ../../../../../tmp/x allows an attacker to traverse outside of the query directory. So an attacker has arbitrary directory control. The filename itself is also partially attacker controlled, result-