Q: How can I get valid path from argument in #!/bin/sh script? I have some script(copy) and want to get valid path.
#!/bin/sh
cp -R $1 $2

I tried with parameter like this
./copy.sh /home/apple /home/pie;reboot

then server was rebooted and it's not acceptable in production server.
I know linux path is composed only with [a-zA-Z0-9_-/. ]
How can I filter $1 and $2, so I can call without worry.
#!/bin/sh
$filtered_path_1=some_filter_funtion($1)
$filtered_path_2=some_filter_function($2)
cp -R $filtered_path_1 $filtered_path_2

Background
I have jenkinsfile and call sh 'sudo /home/copy.sh ${Workspace} ${targetdir}' in this jenkinsfile.
Because jenkins user has no write access on ${targetdir}, I gave jenkins user root privileges only on this copy.sh script via
sudo visudo jenkins    
ALL = NOPASSWD: /home/copy.sh, 

And this jenkinsfile is in git repository.
If bad guy modify this jenkinsfile with bad code like reboot and commit it, then copy script is called automatically.
Because this script is called in root privilege, he can do bad things using this weakpoint.
He will remove sh 'sudo /home/copy.sh ${Workspace} ${targetdir}', and
will add sh 'sudo /home/copy.sh  /tmp /var;reboot'.
How can I protect him?

A: This has nothing to do with your script.  In Bash shell, the ; is seen as the termination command for the string of commands, and then right after it is a secondary command.  So in effect the way your stuff was processed as follows.

*

*Execute command before the ;:
./copycron.sh /home/apple /home/pie



*Execute second command after the ;:
 reboot

Because you were executing likely as root or superuser, it successfully rebooted.
However, if you do something more specific and execute another arbitrary command after the ; instead, you'll notice that command gets run.  Your two arguments to your script will remain /home/apple and /home/pie respectively.  The script never sees the ;reboot part because that's not parsed as an argument.  This is a Bash limitation and not something in your script.

You can test this with the following script and then command calls:
FILE: argecho.sh
#!/bin/bash

echo "Space delimited arguments: $*"
echo ""
echo "------"
echo ""

COMMAND TO EXECUTE:
./argecho.sh foo bar baz /tmp/something.txt;echo I Did Something Else
OUTPUT:
$ ./argecho.sh foo bar baz /tmp/something.txt;echo I Did Something Else Outside The Script, see?
Space delimited arguments: foo bar baz /tmp/something.txt

------

I Did Something Else Outside The Script, see?

You'll notice the 'echo' and the other arguments in it were not included in your arguments in your script.  This is Standard Bash Behavior.


Based on your edits, your concern is that someone is going to hijack your Jenkins repository commands and issue a malicious command, by changing the script from sh 'copycron "${Workspace}" "${targetdir}"' to sh copycron /home /boot;shutdown
Unfortunately for you, this has absolutley nothing you can fix, this would result in a failure of you to properly control who has access to the command repositories.  Such threat actors would have a lot more access to damage your system, not just run a simple command like the aforementioned changes.  They'd more likely install malware on your system, than anything, and unless you properly secure your command repositories so that nobody can just 'randomly edit them', your lack of control of the repositories is what'll screw you over.
There's no real hardening we can do here if the jenkins user has unlimited sudo privileges either.  There just isn't, because this is going to rely on you properly securing your systems or building an alternative deployment mechanism that is more secure and doesn't require full sudo to work with everything.
