This isn't a bug. it's by design.
By default WebGL does the same as GL. It doesn't flip anything. The "data" pointer passed to texImage2D represents the bottom left corner of the texture. Whether that's an ArrayBuffer, an Image, a Canvas, a Video. For Image, Canvas, and Video that means by default they'be upside down (which is the same as GL).
CopyTexImage2D in GL has always been "effectively" backward relative to TexImage2D when talking about images because most (all?) image libraries load images with the first pixel in the top, left and GL expects the first pixel is the bottom, left. Since CopyTexImage is copying internally it appears to have different behavior because it's matching src data 0x0 = bottom, left, dst data 0x0 = bottom left where as TexImage2D, when passing standard image data, is src data 0x0 = top,left, dest = bottom, left
If you want WebGL to flip the data for you call gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
There is no PACK_FLIP_Y so readPixels will always return the bottom,left as the first data in the array buffer.
As for matching implementations it's all tested in the conformance tests AFAIK.