transform.forward = foo;
is basically a shortcut for
transform.rotation = Quaternion.LookRotation(foo, Vector3.up);
ie. it's not turning just one component of the orientation, it's forming a whole new orientation from scratch, discarding anything that came before.
Since a single vector is not enough information to fully determine the orientation, it assumes you want the local up vector to align as best it can with the global y+ axis,
(0, 1, 0)
When you do this every frame, and then try to
transform.Rotate() incrementally afterwards, that incremental rotation doesn't have an opportunity to accumulate over subsequent frames. In the next frame it will just be replaced by the orientation computed from the forward vector, and you'll only ever get a single frame's worth of twist added on afterward. Since frames can vary in duration, this creates the vibration you're seeing.
So, instead you can do one of two things:
A) Track roll separately, and add it all at once.
m_RollAngle += m_RotateSpeed * Time.deltaTime * 500;
m_RollAngle = m_RollAngle % 350f;
transform.forward = m_Rigidbody.velocity;
transform.Rotate(0, 0, m_RollAngle);
B) Rotate your up vector, and form your new orientation using that.
var newUp = Quaternion.AngleAxis(m_RotateSpeed * Time.deltaTime * 500, transform.forward) * transform.up;
transform.rotation = Quaternion.LookRotation(m_Rigidbody.velocity, newUp);