The Rossoneri appeared to take control of the tie thanks to a 61st-minute finish from Ante Rebic. Milan was then reduced to 10 men after former Real Madrid left-back Theo Hernandez was sent off for a second yellow card after he brought down Paulo Dybala.
Juve made the extra man count after Davide Calabria blocked Ronaldo's overhead kick. A VAR review deemed the incident worthy of a spot-kick, and Ronaldo made no mistake from 12 yards.
The result means the Bianconeri have a priceless away goal going into the second leg in Turin on March 4. Meanwhile, Milan attacking talisman Zlatan Ibrahimovic will miss the second leg after being booked for a clash with Matthijs de Ligt.
Milan had the better of the early exchanges, with Ibrahimovic being teed up in the box after a smart turn from Rebic. Unusually, the powerhouse striker's touch let him down and Juve cleared.
Another smart Milan move saw Rebic and Ibrahimovic combine to provide Calabria with a shooting chance. The defender's powerful effort drew a fine save from 42-year-old Gianluigi Buffon.
Juve's decorated veteran stopper was needed again when Hakan Calhanoglu hit one low from the edge of the box. Buffon was up to the test, but Milan were finding too much time and space behind a forward-thinking Juventus midfield trio of Miralem Pjanic, Blaise Matuidi and Aaron Ramsey.
The Bianconeri needed to seize control of the game and begin providing an anonymous Ronaldo with chances. A decent opportunity came and went when Juan Cuadrado's low shot forced Gianluigi Donnarumma to parry.
Things soon became testy between the rivals, with Ibrahimovic being shown a yellow card for catching De Ligt with an arm to the face.
Then Ramsey went into the book soon after for preventing Hernandez from breaking clear. Hernandez ended the half with a yellow card that proved significant.
It capped what had been a fractious first 45 minutes that lacked genuine quality despite the marquee names on the pitch.
Juve needed Buffon again once the action resumed, and he produced a solid stop to deny Rebic. The latter had broken clear thanks to another smart run but could only shoot straight at Juve's 'keeper.
Rebic had fluffed his lines, but he continued to find space by running off Ramsey and Co. Fittingly, it was the Croatia international who beat Buffon just after the hour mark when he scooped in a finish from a Samu Castillejo cross.
The goal continued a fine run for Rebic, who is thriving against the toughest opposition:
Buffon was beaten just seconds after making a fine save to get a hand to Ibrahimovic's side-footed effort aimed toward the near post.
Milan merited the lead, and Maurizio Sarri responded by substituting Ramsey, who was visibly angry when leaving the pitch for Rodrigo Bentancur. Soon after, former Milan loanee Gonzalo Higuain entered the fray in place of full-back Mattia De Sciglio, while Adrien Rabiot came in for a disappointing Matuidi.
Stefano Pioli then needed to reshuffle the Milan lineup when Hernandez was dismissed for a second booking following a late challenge on Dybala. Diego Laxalt replaced Rebic to ensure Milan kept a set back four.
Juve pushed to make the man advantage count but still couldn't get Ronaldo involved enough. He cut a forlorn figure, playing wide on the left following Higuain's introduction.
He may have appeared to be on the fringes of the game, but it was Ronaldo's overhead kick that drew the disputed handball claim against Calabria. The defender was close to Ronaldo with his back turned, but his arm was extended.
Ronaldo made no mistake with the finish to prove that any concerns his powers are waning in the winter of his career are premature:
In the process, Ronaldo also ensured 13-time winners Juve are in the box seat to reach yet another final.