In a previous chapter on testability, we mentioned the method of defensive programming. Even though this method is not strictly a security feature, it happens to help with creating a robust interface. Such interfaces, in turn, increase the overall security of your system.
As a good heuristic, you can treat all the external data as unsafe. What we mean by external data is every input coming to the system via some interface (either a programming interface or user interface). To denote this, you can go as far as prefixing the appropriate types as Unsafe, as follows:
RegistrationResult registerUser(UnsafeUsername username, PasswordHash passwordHash) { SafeUsername safeUsername = username.sanitize(); try { std::unique_ptr<User> user = std::make_unique<User>(safeUsername, passwordHash); CommitResult result = user->commit(); if (result == CommitResult::CommitSuccessful) { return RegistrationResult::RegistrationSuccessful...