menu_bookDocumentation

RPC Security: How s&box Validates Incoming RPCs — Attribute Check, Permission Flags, Kick on Unauthorized

calendar_today May 4, 2026 schedule ~2 min read person patrickjr verified 50

RPC Security: How s&box Validates Incoming RPCs

Understanding how s&box validates incoming RPCs is important for writing secure multiplayer code.

Validation Steps

When an RPC message arrives from the network, the engine performs these checks in order:

  1. GameObject lookup — The message contains the Guid of the target GameObject. If not found in the active scene, the RPC is dropped with a warning.
  2. Component lookup — If ComponentId != Guid.Empty, the target component is looked up. If not found, the RPC is dropped.
  3. Attribute check — The method must have an [RpcAttribute] (i.e., [Rpc.Broadcast], [Rpc.Host], or [Rpc.Owner]). If it doesn't, the calling connection is kicked: source.Kick( "Unauthorized RPC" ).
  4. Permission checkNetFlags.HostOnly and NetFlags.OwnerOnly are enforced:
- HostOnly: caller must be the host - OwnerOnly: caller must own the GameObject, or be the host if the object is unowned

Rpc.Owner Fallback Behavior

For [Rpc.Owner] RPCs, if the GameObject has no owner (OwnerId == Guid.Empty), the message is sent to the host instead. This means [Rpc.Owner] on an unowned object behaves like [Rpc.Host].

Local Execution

RPCs also execute locally on the caller. The engine checks:


Rpc.Caller Inside an RPC

CSHARP
[Rpc.Host]
public void RequestSomething()
{
    // Rpc.Caller is the Connection that sent this RPC
    // Rpc.Calling is true when called from the network
    // Rpc.CallerId is the Guid of the caller
    Log.Info( $"Called by: {Rpc.Caller.DisplayName}" );
}

GameObjectSystem RPCs

RPCs can also be declared on GameObjectSystem subclasses. They are routed by the system's Guid rather than a GameObject Guid. For [Rpc.Owner] on a system, "owner" means the host.

Was this helpful?