Coverage for src/taipanstack/security/types.py: 100%

34 statements  

« prev     ^ index     » next       coverage.py v7.15.1, created at 2026-10-13 20:52 +0000

1""" 

2Pydantic-compatible security types. 

3 

4Provide ``Annotated`` type aliases that integrate TaipanStack's 

5runtime security guards with Pydantic v2 validation, enabling 

6declarative, type-safe input validation inside ``BaseModel`` 

7definitions. 

8""" 

9 

10from typing import Annotated 

11 

12from pydantic.functional_validators import AfterValidator 

13 

14from taipanstack.core.result import Ok 

15from taipanstack.security.guards import ( 

16 SecurityError, 

17 guard_command_injection, 

18 guard_path_traversal, 

19 guard_ssrf, 

20) 

21from taipanstack.security.validators import ( 

22 validate_project_name, 

23 validate_url, 

24) 

25 

26 

27def _validate_safe_url(url: str) -> str: 

28 """Validate a URL is safe from SSRF attacks. 

29 

30 Args: 

31 url: The URL string to validate. 

32 

33 Returns: 

34 The validated URL. 

35 

36 Raises: 

37 ValueError: If the URL fails SSRF validation. 

38 

39 """ 

40 result = guard_ssrf(url) 

41 if isinstance(result, Ok): 

42 return result.ok_value 

43 raise ValueError(str(result.err_value)) from result.err_value 

44 

45 

46def _validate_safe_path(path: str) -> str: 

47 """Validate a path is safe from traversal attacks. 

48 

49 Args: 

50 path: The path string to validate. 

51 

52 Returns: 

53 The validated path string. 

54 

55 Raises: 

56 ValueError: If path traversal is detected. 

57 

58 """ 

59 try: 

60 guard_path_traversal(path) 

61 except SecurityError as exc: 

62 raise ValueError(str(exc)) from exc 

63 return path 

64 

65 

66def _validate_safe_command(command: str) -> str: 

67 """Validate a command string is safe from injection attacks. 

68 

69 Args: 

70 command: The command string to validate. 

71 

72 Returns: 

73 The validated command string. 

74 

75 Raises: 

76 ValueError: If command injection is detected. 

77 

78 """ 

79 try: 

80 guard_command_injection([command]) 

81 except SecurityError as exc: 

82 raise ValueError(str(exc)) from exc 

83 return command 

84 

85 

86def _validate_safe_project_name(name: str) -> str: 

87 """Validate a project name conforms to safe naming rules. 

88 

89 Args: 

90 name: The project name to validate. 

91 

92 Returns: 

93 The validated project name. 

94 

95 Raises: 

96 ValueError: If the name is invalid. 

97 

98 """ 

99 return validate_project_name(name) 

100 

101 

102def _validate_safe_url_format(url: str) -> str: 

103 """Validate a URL has a correct format and allowed scheme. 

104 

105 Args: 

106 url: The URL string to validate. 

107 

108 Returns: 

109 The validated URL. 

110 

111 Raises: 

112 ValueError: If the URL format is invalid. 

113 

114 """ 

115 return validate_url(url) 

116 

117 

118SafeUrl = Annotated[ 

119 str, 

120 AfterValidator(_validate_safe_url_format), 

121 AfterValidator(_validate_safe_url), 

122] 

123"""A URL validated for correct format and safe from SSRF attacks.""" 

124 

125SafePath = Annotated[str, AfterValidator(_validate_safe_path)] 

126"""A filesystem path validated against path-traversal attacks.""" 

127 

128SafeCommand = Annotated[str, AfterValidator(_validate_safe_command)] 

129"""A command string validated against shell-injection attacks.""" 

130 

131SafeProjectName = Annotated[str, AfterValidator(_validate_safe_project_name)] 

132"""A project name validated for safe naming conventions."""