xetex's right to left mechanism, known as TeX--XeT works essentially as a post processor to the generated dvi file. (The original version of the algorithm, TeX-XeT, was a post processor, TeX--XeT is essentially the same but built in to the etex and xetex engines.)
This means that almost all processing happens as if for left to right processing, then at the final stage each line separately is more or less naively written out to the dvi file in reverse order.
This has several drawbacks compared with the direction support in luatex (which is derived from Omega). Notably:
you can not specify right to left between paragraphs (in vertical mode). (This is why it is hard to have longtable columns right to left in xetex.)
Paired \special
like color start and color end will be written out in the wrong order if they are on the same line.
This is why having the paragraph end before the group (or having no group) makes the color work in your example: the color start is on one line and the color end is on a later line, and so even when each line is reversed the start is before the end.
If the color command knows the color was going to end on the same line, and it is an rtl region, it could write out the specials in the wrong order, so TeX--XeT would reverse them making them correct, however in general if it wrote them in the wrong order but there was a line break, the color end would again appear in the dvi before the color start.
This is a Non-answer marked as community wiki, if anyone has anything more coherent to add, feel free to edit...
From Cicada:
As given in the code, the main language for the document is defined as Arabic, so even English text (or any other text) will come out in RTL order.
In an RTL environment, put the \color
command token at the front (=on the right), so it comes first.
But better, why not use babel's \selectlanguage{}
command to switch languages?

MWE
\documentclass{article}
\setlength{\parindent}{0pt}
\usepackage{xcolor}
\usepackage[bidi=default]{babel}
\babelprovide[import,main]{arabic}
\babelfont{rm}{FreeSerif}
\begin{document}
\begingroup
English and $math$ -- this is blue\color{blue} % black
\endgroup
\color{red}English and $math$ -- this is red % red
هذا أحمر أم أزرق؟
\selectlanguage{english}
hadha 'ahmar 'am 'azaraq?
\begingroup
\color{blue} English and $math$ -- this is blue (in front, in English)% black
\endgroup
\color{red}English and $math$ -- this is red % red
\end{document}
\special
mechanism used for xetex color, so it's harder than it ought to be.[bidi=basic]
.