Ignacio Vazquez-Abrams is correct, but lets see exactly how it works...
From 15.1.2.2 parseInt (string , radix):
When the parseInt function is called,
  the following steps are taken:
- Let inputString be ToString(string).
- Let S be a newly created substring of inputString consisting of the first
  character that is not a
  StrWhiteSpaceChar and all characters
  following that character. (In other
  words, remove leading white space.)
- Let sign be 1.
- If S is not empty and the first character of S is a minus sign -, let
  sign be −1.
- If S is not empty and the first character of S is a plus sign + or a
  minus sign -, then remove the first
  character from S.
- Let R = ToInt32(radix).
- Let stripPrefix be true.
- If R ≠ 0, then a. If R < 2 or R > 36, then return NaN. b. If R ≠ 16, let
  stripPrefix be false.
- Else, R = 0 a. Let R = 10.
- If stripPrefix is true, then a. If the length of S is at least 2 and the
  first two characters of S are either
  “0x” or “0X”, then remove the first
  two characters from S and let R = 16.
- If S contains any character that is not a radix-R digit, then let Z be the
  substring of S consisting of all
  characters before the first such
  character; otherwise, let Z be S.
- If Z is empty, return NaN.
- Let mathInt be the mathematical integer value that is represented by Z
  in radix-R notation, using the letters
  A-Z and a-z for digits with values 10
  through 35. (However, if R is 10 and Z
  contains more than 20 significant
  digits, every significant digit after
  the 20th may be replaced by a 0 digit,
  at the option of the implementation;
  and if R is not 2, 4, 8, 10, 16, or
  32, then mathInt may be an
  implementation-dependent approximation
  to the mathematical integer value that
  is represented by Z in radix-R
  notation.)
- Let number be the Number value for mathInt.
- Return sign × number.
NOTE parseInt may interpret only a
  leading portion of string as an
  integer value; it ignores any
  characters that cannot be interpreted
  as part of the notation of an integer,
  and no indication is given that any
  such characters were ignored.
There are two important parts here. I bolded both of them. So first of all, we have to find out what the toString representation of null is. We need to look at Table 13 — ToString Conversions in section 9.8.0 for that information:

Great, so now we know that doing toString(null) internally yields a 'null' string. Great, but how exactly does it handle digits (characters) that aren't valid within the radix provided?
We look above to 15.1.2.2 and we see the following remark:
If S contains any character that is
  not a radix-R digit, then let Z be the
  substring of S consisting of all
  characters before the first such
  character; otherwise, let Z be S.
That means that we handle all digits PRIOR to the specified radix and ignore everything else.
Basically, doing parseInt(null, 23) is the same thing as parseInt('null', 23). The u causes the two l's to be ignored (even though they ARE part of the radix 23). Therefore, we only can only parse n, making the entire statement synonymous to parseInt('n', 23). :)
Either way, great question!