In my view, there's a bright line dividing "safe" languages where programs cannot have Undefined Behavior, and "unsafe" languages where they can.
There's no meaningful sense in which this can be further subdivided into memory safety, thread safety, type safety, and whatnot -- it doesn't matter *why* your program has UB, what matters is that a program with UB defies the basic abstractions of the language itself, and this is a perfect breeding ground for vulnerabilities.
In my view, there's a bright line dividing "safe" languages where programs cannot have Undefined Behavior, and "unsafe" languages where they can.
There's no meaningful sense in which this can be further subdivided into memory safety, thread safety, type safety, and whatnot -- it doesn't matter *why* your program has UB, what matters is that a program with UB defies the basic abstractions of the language itself, and this is a perfect breeding ground for vulnerabilities.