Path tracing with Next event estimation and area lights auto occlusion
I am no expert in offline renderers, but I'll give it a go until someone else comes with a better answer :)
Shadow rays intersecting area light
It is very common to assign an extent to your rays. How to do so? Think about the parametric formula of a ray:
$$R(t) = O + t\vec{D}$$
it should immediately jumps out that how far $R(t)$ can be from the origin $O$ depends on how much we can travel in the direction $\vec{D}$, and this travelling is clearly governed by the parameter $t$.
Your problem here is that you don't want to let the ray travel indefinitely, but you want to stop just before it hits the source of the light, because otherwise, as you correctly noticed, everything will result occluded.
So how do you limit how much your ray can travel? You just have to limit the maximum value that $t$ can take. You have two option:

Probably the most intuitive one is to compute at what $t_{light}$ your light source lies. By using the same parametric formulation of the ray, if $L_p$ is the point you've chosen on the area light, then $t_{light}$ will be:

$$t_{light} = \frac{L_{p}[i] - O[i]}{\vec{D}[i]}$$
where $[i]$ represents the coordinate of your choice.  Given this, you want to stop your shadow ray to travel just before $t$ reaches $t_{light}$. If it goes over this value, report an unoccluded result.

Now while the option above is probably the first thing that comes to mind, it is wasteful as you'd need to both have $L_p$ around and perform some unneeded arithmetic operations if you have your light vector $\vec{D}$ as unnormalized around. In fact, this is none other than $L_p - O$ and in a case like this, the Light lies at exactly $t == 1$:

$$ O + 1 \times (L_p - O ) = L_p $$
So if you trace your shadow ray with an unnormalized direction $\vec{D}$, you can just set your maximum $t$ to be just under $1$. This is in fact what PBRT does, and as far as I am aware many other renderers.
Black dots (or NaNs)
Nothing to add over @Dan Hulme comment, so I'll just add it here for completeness of the answer:

&quot;I think these are NaNs, will double check, but if you know common scenarios when this happens it'd be appreciated.&quot; The common scenario is that you're using floating-point and you have a bug in your code :-) You have to expect that you'll get NaNs during development, so you should either (a) make sure they get filtered out instead of propagated by the filter, or (b) show all NaNs as bright pink so it's immediately obvious when they're there. – Dan Hulme♦

and if I may add, you should expect some inf as well from time to time, so it's always good to account for these two special cases.
&quot;Bright pixels&quot;
With that, I assume you are talking about what is commonly referred to as fireflies. Fireflies avoidance is indeed quite a big topic and probably warrant its own question. However, just briefly.
Fireflies typically occur when you lots of your paths end in areas with low light and very few paths end up in very bright light.
There is lots of material on how to fight fireflies, a short google search will lead to a lot of techniques depending on your case.
Just to name drop a few:

Radiance clamping
Multiple Importance Sampling (especially if in presence of glossy/shiny surfaces)
Denoising techniques
Increment your sample count :-)
etc.

Also, generally increasing the size of the light source tends to help as well. Remember, the goal is always to hit those bright spot with higher probability!
A better solution to the problem is probably to use something like Bidirectional Path Tracing as this will have sub-paths starting from the light source as well, increasing the likelihood of sampling the bright areas.
Another cause of fireflies are caustics, but I don't want to make this answer longer, so if you are interested this is well worth an additional question.