Yes — the two rules live in different places, and neither is where you looked.
null clears a key during a merge that happens before validation. That is the project file: framework defaults are merged with sdods.project.yaml and the result is then parsed. So a null there removes the key from the merged object, and the schema default takes over for it — which usually means you get the default back rather than nothing. In an environment file the order is reversed, the file is parsed first, so mask: null is a type error exactly as you saw.
undefined skipped is the flag layer, and it is what makes flags usable at all: a flag you did not pass is undefined and never overwrites the yaml. Without that rule every unpassed flag would blank out the value beneath it.
Also worth knowing: a bare mask: in YAML with nothing after it is null, not "unset". People write that meaning "leave it alone" and get the other behaviour.