1+ import pytest
2+ import subprocess
3+ import sys
4+ from pathlib import Path
5+ from unittest .mock import patch , MagicMock
6+
7+ # Import the module under test
8+ sys .path .insert (0 , str (Path (__file__ ).parent .parent / "pyscripts" ))
9+ import fm11rf08s_recovery
10+
11+
12+ @pytest .mark .parametrize ("malicious_uid" , [
13+ "123456789ABCDEF; rm -rf /" , # Command injection with semicolon
14+ "123456789ABCDEF$(whoami)" , # Command substitution
15+ "123456789ABCDEF`id`" , # Backtick command substitution
16+ "123456789ABCDEF| cat /etc/passwd" , # Pipe injection
17+ "123456789ABCDEF" , # Valid UID (baseline)
18+ ])
19+ def test_shell_injection_prevention (malicious_uid ):
20+ """Invariant: Shell metacharacters in card UIDs never reach unescaped shell execution"""
21+
22+ # Mock the subprocess.run to capture what command would be executed
23+ captured_commands = []
24+
25+ def mock_run (cmd , * args , ** kwargs ):
26+ captured_commands .append (cmd )
27+ result = MagicMock ()
28+ result .stdout = ""
29+ result .returncode = 0
30+ return result
31+
32+ with patch ("subprocess.run" , side_effect = mock_run ):
33+ with patch ("fm11rf08s_recovery.detect_reader" , return_value = True ):
34+ with patch ("fm11rf08s_recovery.select_card" , return_value = True ):
35+ # Attempt to trigger command construction with malicious UID
36+ try :
37+ fm11rf08s_recovery .recover_card (malicious_uid )
38+ except Exception :
39+ pass # We only care about command construction, not execution
40+
41+ # Assert: if commands were captured, they must be lists (not shell-injectable strings)
42+ # or if strings, must not contain unescaped metacharacters from the payload
43+ for cmd in captured_commands :
44+ if isinstance (cmd , str ):
45+ # If cmd is a string, it should not contain raw shell metacharacters
46+ # from the malicious payload (they should be escaped or rejected)
47+ dangerous_chars = ["; rm" , "$(" , "`" , "| cat" ]
48+ for char_seq in dangerous_chars :
49+ assert char_seq not in cmd , \
50+ f"Unescaped shell metacharacter '{ char_seq } ' found in command: { cmd } "
51+ else :
52+ # Commands passed as lists are safe from shell injection
53+ assert isinstance (cmd , list ), \
54+ f"Command must be list or properly escaped string, got: { type (cmd )} "
0 commit comments