Just an update in case anybody finds this one day.
IMHO USB is full of sh*it and the only reason why it works "ok" today is because billion $ commercial interests have spent countless man-years fixing various issues, and with each USB product vendor wasting this time and money in-house independently.
I've managed to eliminate some very subtle problems by doing 2 things
1) checking for VBUS=1 before sending any data out of USB
2) checking a flag which is set/reset by CDC_Init_FS() and CDC_DeInit_FS(). Experts tell me that that is all one can do without having a custom driver.
Note also that the ST Cube code uses the heap (malloc and free) in these two functions, so your product will eventually crash.