@@ -60,6 +60,54 @@ def test_s_client_x509(self):
6060 self .assertIn ("-----BEGIN CERTIFICATE-----" , result .stdout ,
6161 "Expected x509 PEM output not found" )
6262
63+ class ShellInjectionTest (unittest .TestCase ):
64+ """Regression tests for shell command injection via hostname.
65+
66+ Applies to the WOLFSSL_USE_POPEN_HOST path where peer is concatenated
67+ into a popen() shell command. On other builds, getaddrinfo /
68+ gethostbyname reject these hostnames before any shell is involved,
69+ so the tests pass either way -- the injected command must never run.
70+ """
71+
72+ INJECTION_PROBE = "clu_injection_probe.txt"
73+
74+ def setUp (self ):
75+ if os .path .exists (self .INJECTION_PROBE ):
76+ os .remove (self .INJECTION_PROBE )
77+ self .addCleanup (lambda : os .remove (self .INJECTION_PROBE )
78+ if os .path .exists (self .INJECTION_PROBE ) else None )
79+
80+ def _assert_no_injection (self , peer , description ):
81+ """Run s_client with the given -connect peer and verify that the
82+ injected `touch` command did not execute."""
83+ subprocess .run (
84+ [WOLFSSL_BIN , "s_client" , "-connect" , peer ],
85+ capture_output = True ,
86+ stdin = subprocess .DEVNULL ,
87+ timeout = 30 ,
88+ )
89+ self .assertFalse (
90+ os .path .exists (self .INJECTION_PROBE ),
91+ f"SECURITY FAILURE: command injection via hostname "
92+ f"({ description } )" )
93+
94+ def test_semicolon_injection (self ):
95+ """evil.com;touch probe:443 must not execute the touch command."""
96+ self ._assert_no_injection (
97+ f"evil.com;touch { self .INJECTION_PROBE } :443" ,
98+ "semicolon" )
99+
100+ def test_command_substitution_injection (self ):
101+ """evil$(touch probe).com:443 must not execute the touch command."""
102+ self ._assert_no_injection (
103+ f"evil$(touch { self .INJECTION_PROBE } ).com:443" ,
104+ "command substitution" )
105+
106+ def test_pipe_injection (self ):
107+ """evil.com|touch probe:443 must not execute the touch command."""
108+ self ._assert_no_injection (
109+ f"evil.com|touch { self .INJECTION_PROBE } :443" ,
110+ "pipe" )
63111
64112if __name__ == "__main__" :
65113 test_main ()
0 commit comments