If the attacker controls SQLCMD inputs, then they can do anything their login credentials (authorized or stolen) can do. That's just normal functioning.
Don't do this. This is a bad practice if there's any input from the outside going into your SQLCMD.
If you insist on this, then if you want to use SQLCMD with parameter substitution from environment variables (perhaps), you probably want to experiment with credentials that can only EXECUTE within a certain, limited schema
CREATE SCHEMA FromSqlCmd AUTHORIZATION myuser
GRANT EXECUTE ON SCHEMA::[FromSqlCmd] TO [myschema_execute];
Within each stored procedure, NEVER concatenate what's passed in to dynamic SQL.
NEVER put the results into a table without a whitelist; otherwise you're opening yourself up for second order sql injection.
If you're consider Powershell, then cjsommer.com has an article about this - he found that neither powershell SQLPS command protected against injection, even with parameters.
It's worse than that
If you actually let input - validated or not - from others be part of your command line for SQLCMD, then you're opening yourself up for command line injection!!! The & character is one way for a command prompt to run multiple commands; try it with
C: & cd \ & format /? & del /?
Now imagine this in the middle of your sqlcmd.
Also note that Powershell uses ; to separate commands.