Brian Tinnion hit his sixth penalty of the season to give Cardiff's promotion hopes a devastating blow.
The spot-kick came early in the second half when a linesman signalled a handball by Cardiff defender Daniel Gabbidon.
The entire Cardiff side protested but when the rumpus died down, Tinnion calmly slotted his penalty to the left of keeper Neil Alexander.
Alexander, back in the side after missing five games with a groin injury, thought Tinnion would shoot to his right as he did when scoring from the spot at Ninian Park in December, another 2-0 win for Bristol City.
They have not been beaten by the Welsh club now in 21 League games.
With both clubs going for promotion the atmosphere was always highly charged and in the first half each side went close once to scoring.
Andy Legg from a narrow angle hit the Bristol City bar and then Alexander did well to drop on a powerful downward header by Lee Peacock following a corner.
Neither side though was getting in much in the way of shots although Cardiff stepped up the pressure after Tinnion's strike.
But Bristol City weathered the storm with Tommy Doherty and Tony Butler organising their back line and midfield.
Victory was assured for the home side when Christian Roberts turned in their second goal from a Scott Murray cross.
The tension which had been building since the disputed penalty boiled over in a fight in the last minute which saw the Robins' Aaron Brown and Gareth Ainsworth of Cardiff both sent off.
Bristol City Danny Wilson said after the game: "I didn't see the fight start but Aaron Brown told me his head was being held in an arm lock and he was trying to get free." This was Cardiff's third league defeat in a row undermining their bid for automatic promotion and their two final games are against promoted Wigan and second placed Crewe.
Wilson added: "Our dressing room firmly believes we can get automatic promotion ourselves. We have to win our last two games and hope either Crewe or Cardiff slip up again."