It is important to ensure that the less-privileged end of the channel (typically agents) cannot run arbitrary code on the more-privileged end (typically a controller), so care needs to be taken when implementing Callables.
The remoting library offers the RoleSensitive interface for this which Callable extends.
Callables can use it to limit where they can be executed by implementing #checkRoles(RoleChecker).
 
The abstract supertypes ControllerToAgentCallable and SlaveToMasterCallable implement this interface with two well-defined modes:
 
- 
ControllerToAgentCallable can be sent from a controller to an agent.
In practice, almost all Callable implementations will be ControllerToAgentCallables.
(Prior to Jenkins 2.485 when `ControllerToAgentCallable was introduced, use the abstract superclass `MasterToSlaveCallable.)
 
- 
SlaveToMasterCallable can be sent from an agent to a controller.
This is extremely risky, as malicious agents can use poorly-reviewed implementations to run code on a controller.
 
 
Despite their names, either implementation can be executed anywhere; the name just describes through which channels it can be sent for execution.
ControllerToAgentCallable can be executed on the controller, just not sent from an agent to a controller for execution;
whereas SlaveToMasterCallable can be sent through a controller/agent channel in either direction.
 
In addition to the above, NotReallyRoleSensitiveCallable can be used for a Callable that is not intended to be sent through a channel.
Its #checkRoles method will throw an exception, thereby preventing it from being executed on any side of a communication channel that performs a role check.
This would only be used when some API is defined using hudson.remoting.Callable rather than a more generic functional interface,
for example because it has a Throwable type parameter.
 
It is recommended to use one of these supertypes in your plugin, rather than implementing #checkRoles(RoleChecker) directly.
 
Mandatory role checks
Since Jenkins 2.319 and LTS 2.303.3, Callable implementations providing an implementation of #checkRoles(RoleChecker) that neither throws an exception nor calls RoleChecker#check will result in the Callable being rejected when sent through the channel to a side that requires a role check before execution.
A typical implementation that breaks will look like the following:
 
class MyCallable implements Callable<ReturnType,ExceptionType> {
    private String parameter;
    public MyCallable(String parameter) {
        this.parameter = parameter;
    }
    public ReturnType call() throws ExceptionType {
        return Some.code().operatesOn(this.parameter);
    }
    public void checkRoles(RoleChecker checker) {
        // this is an empty block (1)
    }
}
 
 
| 1 | 
Nothing is being done here even though a call to RoleChecker#check(…) is expected. | 
 
If a plugin implementing an inadequate role check (like this example) attempts to send a Callable through the remoting channel from the agent to the controller, the security improvement will detect it and throw an exception before #call() would be invoked.
 
While administrators can allow specific Callable subtypes to bypass this protection mechanism (see documentation), plugin developers are advised to update their plugins:
Callable implementations should extend from one of the classes mentioned above, with a strong preference for ControllerToAgentCallable, which should work in almost all cases.
If that does not work and the plugin cannot be restructured to work with a ControllerToAgentCallable, the Callable implementation should be changed to a SlaveToMasterCallable, and the best practices recommended below must be implemented to ensure it cannot be bypassed.