> // No idea where negative values come from :(
I don't know, but:
> newRay.origin += sign(dot(newRay.direction, geometryNormal)) * geometryNormal * 1e-4;
The new origin should be along the reflected ray, not along the direction of the normal. This line basically adds the normal (with a sign) to the origin (intersection point), which seems odd.
Poor's man way to find where the negatives come from is to max(0,...) stuff until you find it.