Looking at the source (and the stack trace I got by reproing which you omitted :P)
This is because it's binding to a different overload of the ConstructorArgument ctor than the normal usage (i.e., where you're passing a Value Type or a non-null Reference Type) does.
The workaround is to cast the null to Object:-
var ninja = kernel.Get<Ninja>( new ConstructorArgument( "weapon", (object)null ) );
Ninject 2 source:
public class ConstructorArgument : Parameter
{
    /// <summary>
    /// Initializes a new instance of the <see cref="ConstructorArgument"/> class.
    /// </summary>
    /// <param name="name">The name of the argument to override.</param>
    /// <param name="value">The value to inject into the property.</param>
    public ConstructorArgument(string name, object value) : base(name, value, false) { }
    /// <summary>
    /// Initializes a new instance of the <see cref="ConstructorArgument"/> class.
    /// </summary>
    /// <param name="name">The name of the argument to override.</param>
    /// <param name="valueCallback">The callback to invoke to get the value that should be injected.</param>
    public ConstructorArgument(string name, Func<IContext, object> valueCallback) : base(name, valueCallback, false) { }
}
Repro:
public class ReproAndResolution
{
    public interface IWeapon
    {
    }
    public class Ninja
    {
        private readonly IWeapon _weapon;
        public Ninja( IWeapon weapon )
        {
            _weapon = weapon;
        }
    }
    [Fact]
    public void TestMethod()
    {
        var kernel = new StandardKernel();
        var ninja = kernel.Get<Ninja>( new ConstructorArgument( "weapon", (object)null ) );
    }
}
Lesson? You'd be crazy not to download the latest source and look at it. Great comments, nice clean codebase. Thanks again to @Ian Davis for that tip/prodding!