With the Stratum V1 protocol in use today (and the Stratum V2 protocol as it is currently proposed), mining pools actually send the parts of the coinbase transaction to their miners for those miners to modify. Specifically, they reserve space in their coinbase transactions for miners to use as an extra nonce. Those miners will construct the coinbase transaction, insert their extra nonce, compute the merkle root (they are given merkle branches to be able to complete the merkle root), and then create the block header.
However when the miner submits their work, they are only submitting the pieces that they added - namely the nonce, the timestamp, and the extra nonce. The pool will then reconstruct the coinbase transaction with the given extra nonce, reconstruct the merkle root, reconstruct the block header, and verify that the block header meets the PoW requirement for that miner. If the coinbase transaction had been modified by the miner, or by an attacker who sits between the pool and the miner, then it is unlikely that the block hash they calculate for that submitted share will meet the PoW requirement for that miner.
It is unlikely that miners are using createrawtransaction
for creating their coinbase transactions as it is unable to do so anyways. createrawtransaction
does not allow the caller to set an input's vout
to be the right value for a coinbase transaction. So mining pool software are most likely creating the coinbase transaction internally rather than outsourcing it to bitcoind. In that case, they will be using the correct outputs. If they aren't, then either something is manipulating the coinbase transaction after the pool sends it but before the miner receives it, or the attacker is able to directly modify the pool software's memory.
In the first case, the PoW checking I described earlier is the protection. In any case, the pool can't really do much about an external entity (by external, I mean external to the pool software, it could still be running on the same compromised machine) modifying the coinbase when they send it out. In the second case, the pool can't protect against that as the attacker can just always make the software think that their coinbase is correct.