X.509 Name Constraints extension is what you are looking for.
They are VERY expensive when ordered from public CA, but we use them at work for internal PKI.
When I was setting up internal PKI back in 2015, I wanted to limit the CA to be less dangerous. At the time name constraints did not work. At all.
It wasn't possible to create a CSR with the field in OpenSSL, because the config parser didn't know about the key. So I did what any self-respecting person would do: I created the CSR manually with low-level API, plugging in the OID directly. When I tried to sign that one, the openssl libs just blew up with BIO_read_XXX errors everywhere.
I then tried the same thing with golang's TLS stack. Trying to operate on a CSR with name constraints triggered a panic. So I gave up - no name constraints on internal CA.
Never got to try it out, but considering how the client libraries behaved on seeing the flag, it would have been amusing to see how different clients behaved when served with a certificate chain that ended up in name constrained CA.
Yes, they are. The extension should be marked as critical, so if the client does not understand it it should error out.
At least java, go, curl and all major browser support it.
I believe clients that don't support name constraints extension won't pass certificate chain verification should the root, intermediate or certificate itself have a name constraint defined.
Good question. I’m guessing that modern browsers such as Google Chrome and Firefox does. When it comes to agents such as wget, curl, mstsc.exe, etc, then I’m not so sure.