What are some ways a SPO can attack the Cardano blockchain? E.g. in Bitcoin, a miner could intentionally exclude certain transactions to the extend that the miner's hash power allows. Is something like this possible in Cardano? What about other forms of attack? What discourages such attacks or mitigates the harm they can cause?
I am still researching if it is possible for a SPO to choose and exclude transactions when they are elected to create the block. I am pretty sure it isn't something you can just do 'out of the box,' I believe you would need to modify the client code of your block producer. With that said, if they could do that, it still wouldn't cause much damage. The reason why is because there is enough entropy built into the slot leader selection that the next block would pick up the excluded transaction. This is because it would be a new slot leader, thus only causing a ~20 second delay. This kind of attack is also discouraged because there is not incentive for just 1 pool operator to cherry pick (choose some, exclude others) transactions because the rewards are pooled and distributed at the end of the epoch. Meaning that if there were a lot of full-blocks, you could very slightly increase the overall rewards. However, after dividing it out to all the SPOs who created blocks, it likely wouldn't be worth your time. Now if multiple SPOs worked together on something like this, and we were constantly creating full blocks there could be incentive to choose the transactions that have larger fees (like ETH).
Decentralization is the mitigation against attacks in almost all of these systems, they all assume that a centralized player has not gained the power to control consensus.
An SPO could theoretically re-write their block producers software to do anything, like award themselves a million ADA. But it doesnt have any effect because no other SPOs agree that should happen.
Chain forks are probably the next thing an SPO could try to do, if they could create a dummy chain they could double-spend ADA. Ouroborous can withstand at least 6 blocks in any 22 blocks being created by attackers trying to fork the chain, and with 15 confirmations no users will be duped onto the wrong chain. It would be very hard for any SPO to co-ordinate more than 6 in 22 blocks becaise of the random nature of slot leader selection, unless they had a very high amount of stake and could wait for the the right time. Of course the problem there is that having a lot of stake on the system and damaging the system is stupid, because you are damaging your own value.
Forking is also dis-incentivized by the fact that all SPOs earn more if there are more successful blocks on the main chain. As rewards are held to the epoch end and distributed to SPOs based on the number of blocks they created on the main chain, its an incentive for all SPOs to find and stay on the main chain.
The most feasible (and most well-established) method by which any kind of validator (be it a miner, SPO, etc) can game the system is through Miner Extractable Value (MEV), a.k.a front-running. It is an endemic (though non-catastrophic) problem for any public blockchain network that is maintained in a trust-less fashion.
In a nutshell, when a validator creates a new block, she temporarily gains a non-insignificant glimpse into the future of the blockchain before the rest of the network does. This is because there is a small amount of time elapsed between the validator making the block locally and that block being validated and incorporated into the rest of the network. Let's call this the MEV-window. If during this window the issuing validator is quick enough to act, they can gain an arbitrage opportunity over the rest of the network. This is especially true if the validator in question is responsible for more than just good 'ol block production on the CSL, but is also providing oracle data, babel fee liquidity, DEX scooping, and/or a variety of other distributed services.
For example, if I'm an SPO and an oracle provider, and I see that the block I'm about to publish contains a sudden surge of transactions towards a known exchange address(es), I may conclude that the price is about to go down, so I may then include some of my own buy orders in the same block. I can also adjust my oracle feeds to match where I expect the price to go before anyone else does; I'd be using my position as a block producer (in that moment) to front-run the market. This is just one of many ways MEV can be used to game the system.
As far as I am aware, there is no generalized solution to the problem of MEV, and I believe it is widely accepted as an issue that can only be minimized, but not completely eliminated. The good news is there may be ways to minimize this problem to the point of relative obscurity. Things like minimizing the MEV window, clever use of ZK-technology, or just building applications with a highly meticulous approach to the underlying game theory, just like IOG did with the development of Cardano.