Flamboyant opener Sanath Jayasuriya was Sri Lanka's top scorer with a 30-ball 45, helping his side overhaul South Africa's total of 169 with 9.2 overs to spare.
Earlier off-spinner Muttiah Muralitheran took four for 35 on a pitch which gave the slow bowlers prodigious turn.
Sri Lanka, the only unbeaten side in the competition, extended their winning sequence to 13 in all one-day internationals.
Helped by a couple of dropped catches early on, Sri Lanka got off to their customary flying start as Jayasuriya and Romesh Kaluwitharana (27) smashed 69 runs in only nine overs.
But the introduction of off-spinner Pat Symcox in the 10th over had immediate effect.
Kaluwitharana perished first ball trying to unleash an expansive drive and, two overs later, Jayasuriya was caught low down by Daryll Cullinan at cover after top-edging a cut.
Symcox went on to return excellent figures of 10-1-20-2 as the Sri Lankan middle and lower order faltered and number eight Kumar Dharmasena had to fashion a responsible 18 not out to steer his team to victory.
Apart from a cultured 51 from Cullinan, South Africa struggled on a pitch on which the ball was turning square.
Wickets fell at regular intervals as their batsmen tried to force the pace and the Sri Lankan fielding, on a bumpy outfield, was impressive.
The biggest partnership of the South African innings was 36 for the fifth wicket between Cullinan and captain Hansie Cronje.
But just when it seemed Cronje had found his batting touch, he produced an ugly drive-cum-sweep to be bowled by Muralitheran for 15.
Cullinan's dismissal six overs later effectively ended South Africa's hopes of totalling 200.
Having reached his 50 from 71 balls with four fours and a six, he misjudged the length of the very first delivery from occasional off-spinner Aravinda de Silva and was bowled attempting to pull. South Africa