Another approach, which would seem even safer than the 'async assert/sync release' approach, would be to have an asynchronous reset detector (much as described elsewhere, with asynchronous 'assert' and synchronous 'release'), but have the output from that gate any outward-facing I/O devices without asynchronously resetting anything. If that is done, a runt pulse on the reset line which would be just the perfect length to throw the reset detector into a metastable state could cause glitches on I/O wires, but would either reset the system state or leave it alone.
Another thing to consider is that systems often have some registers which are not supposed to be affected by a reset. If an asynchronous reset could hit circuitry which writes to those registers, it would be possible for a reset pulse which arrives at the wrong time to clobber those registers, even if it's a clean (non-runt) pulse. For example, if code is trying to write to address 1111 and an async reset which arrives just before a clock pulse forces one of the address latches to zero just as the clock pulse is arriving, that could cause an erroneous write to address 1110. While one could use multiple internal reset lines with combinatorial delays to ensure that register writes were disabled before the address got clobbered, using synchronous internal reset logic avoids the issue altogether.