or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

command-line-tools.mdcontext-analysis.mdcore-management.mdindex.mdissue-reporting.mdoutput-formatters.mdplugin-development.md

context-analysis.mddocs/

0

# Context Analysis

1

2

AST node analysis and import tracking during security test execution. The Context system provides detailed information about function calls, imports, and code patterns essential for accurate vulnerability detection in Python source code.

3

4

## Capabilities

5

6

### Context

7

8

Provides contextual information during AST node analysis for security tests. Context objects give access to function call details, string literals, import patterns, and other code analysis data.

9

10

```python { .api }

11

class Context:

12

def __init__(self, context_object=None):

13

"""

14

Initialize context with optional context object.

15

16

Parameters:

17

- context_object: optional context data for initialization

18

"""

19

20

@property

21

def call_function_name(self):

22

"""

23

Get function name being called (not fully qualified).

24

25

Returns:

26

str: Function name or None if not a function call

27

"""

28

29

@property

30

def call_function_name_qual(self):

31

"""

32

Get fully qualified function name including module path.

33

34

Returns:

35

str: Qualified function name (e.g., 'os.system') or None

36

"""

37

38

@property

39

def call_args(self):

40

"""

41

Get list of function call arguments.

42

43

Returns:

44

list: Function call arguments as AST nodes

45

"""

46

47

@property

48

def call_args_count(self):

49

"""

50

Get number of function call arguments.

51

52

Returns:

53

int: Number of arguments in function call

54

"""

55

56

@property

57

def call_keywords(self):

58

"""

59

Get dictionary of keyword parameters.

60

61

Returns:

62

dict: Keyword arguments mapped to values

63

"""

64

65

@property

66

def string_literal_value(self):

67

"""

68

Get value of string literal node.

69

70

Returns:

71

str: String literal value or None if not a string literal

72

"""

73

74

@property

75

def node(self):

76

"""

77

Get the current AST node being analyzed.

78

79

Returns:

80

ast.Node: Current AST node

81

"""

82

83

@property

84

def string_val(self):

85

"""

86

Get string literal value (alternative to string_literal_value).

87

88

Returns:

89

str: String value or None

90

"""

91

92

@property

93

def bytes_val(self):

94

"""

95

Get bytes literal value.

96

97

Returns:

98

bytes: Bytes value or None

99

"""

100

101

def is_module_being_imported(self, module):

102

"""

103

Check if specified module is being imported.

104

105

Parameters:

106

- module: str, module name to check

107

108

Returns:

109

bool: True if module is being imported

110

"""

111

112

def is_module_imported_like(self, module):

113

"""

114

Check if module is imported with pattern matching.

115

116

Parameters:

117

- module: str, module pattern to match

118

119

Returns:

120

bool: True if module matches import pattern

121

"""

122

123

def is_module_imported_exact(self, module):

124

"""

125

Check if exact module name is imported.

126

127

Parameters:

128

- module: str, exact module name

129

130

Returns:

131

bool: True if exact module is imported

132

"""

133

134

def check_call_arg_value(self, argument_name, argument_values):

135

"""

136

Check if function call argument matches specific values.

137

138

Parameters:

139

- argument_name: str, name of argument to check

140

- argument_values: list, acceptable values for the argument

141

142

Returns:

143

bool: True if argument matches any of the values

144

"""

145

146

def get_lineno_for_call_arg(self, argument_name):

147

"""

148

Get line number for specific function call argument.

149

150

Parameters:

151

- argument_name: str, name of argument

152

153

Returns:

154

int: Line number or None if not found

155

"""

156

```

157

158

## Usage Examples

159

160

### Function Call Analysis

161

162

```python

163

from bandit.core import test_properties as test

164

import bandit

165

166

@test.checks('Call')

167

@test.test_id('B999')

168

def check_dangerous_calls(context):

169

"""Example security test using context analysis."""

170

171

# Check function name

172

if context.call_function_name == 'eval':

173

return bandit.Issue(

174

severity=bandit.HIGH,

175

confidence=bandit.HIGH,

176

text="Use of eval() detected - potential code injection",

177

cwe=94

178

)

179

180

# Check qualified function name

181

if context.call_function_name_qual == 'os.system':

182

# Analyze arguments

183

if context.call_args_count > 0:

184

first_arg = context.call_args[0]

185

if hasattr(first_arg, 's'): # String literal

186

command = first_arg.s

187

if any(char in command for char in ['&', '|', ';']):

188

return bandit.Issue(

189

severity=bandit.HIGH,

190

confidence=bandit.MEDIUM,

191

text="Shell command with potential injection vectors",

192

cwe=78

193

)

194

```

195

196

### Import Pattern Detection

197

198

```python

199

@test.checks('Import', 'ImportFrom')

200

@test.test_id('B900')

201

def check_dangerous_imports(context):

202

"""Check for dangerous module imports."""

203

204

# Check for specific dangerous imports

205

dangerous_modules = ['pickle', 'cPickle', 'dill', 'shelve']

206

207

for module in dangerous_modules:

208

if context.is_module_being_imported(module):

209

return bandit.Issue(

210

severity=bandit.MEDIUM,

211

confidence=bandit.HIGH,

212

text=f"Import of {module} module detected - potential deserialization risk",

213

cwe=502

214

)

215

216

# Check for wildcard imports from security-sensitive modules

217

if context.is_module_imported_like('subprocess.*'):

218

return bandit.Issue(

219

severity=bandit.LOW,

220

confidence=bandit.MEDIUM,

221

text="Wildcard import from subprocess module",

222

cwe=20

223

)

224

```

225

226

### String Literal Analysis

227

228

```python

229

@test.checks('Str')

230

@test.test_id('B901')

231

def check_hardcoded_secrets(context):

232

"""Check for hardcoded secrets in string literals."""

233

234

if context.string_literal_value:

235

value = context.string_literal_value.lower()

236

237

# Check for common secret patterns

238

secret_patterns = [

239

'password=',

240

'secret_key=',

241

'api_key=',

242

'access_token=',

243

'private_key='

244

]

245

246

for pattern in secret_patterns:

247

if pattern in value and len(value) > 20:

248

return bandit.Issue(

249

severity=bandit.HIGH,

250

confidence=bandit.MEDIUM,

251

text="Potential hardcoded secret detected",

252

cwe=259

253

)

254

```

255

256

### Keyword Argument Analysis

257

258

```python

259

@test.checks('Call')

260

@test.test_id('B902')

261

def check_ssl_context(context):

262

"""Check SSL context configuration."""

263

264

if context.call_function_name_qual in ['ssl.create_default_context', 'ssl.SSLContext']:

265

keywords = context.call_keywords

266

267

# Check for disabled certificate verification

268

if 'check_hostname' in keywords:

269

if hasattr(keywords['check_hostname'], 'value') and not keywords['check_hostname'].value:

270

return bandit.Issue(

271

severity=bandit.HIGH,

272

confidence=bandit.HIGH,

273

text="SSL hostname verification disabled",

274

cwe=295

275

)

276

277

# Check for weak SSL versions

278

if 'protocol' in keywords:

279

protocol_node = keywords['protocol']

280

if hasattr(protocol_node, 'attr') and 'SSL' in protocol_node.attr:

281

if any(weak in protocol_node.attr for weak in ['SSLv2', 'SSLv3', 'TLSv1']):

282

return bandit.Issue(

283

severity=bandit.HIGH,

284

confidence=bandit.HIGH,

285

text="Weak SSL/TLS protocol version",

286

cwe=326

287

)

288

```

289

290

### Complex Context Analysis

291

292

```python

293

@test.checks('Call')

294

@test.test_id('B903')

295

def check_subprocess_shell(context):

296

"""Advanced subprocess call analysis."""

297

298

if context.call_function_name_qual in ['subprocess.call', 'subprocess.run', 'subprocess.Popen']:

299

keywords = context.call_keywords

300

args = context.call_args

301

302

# Check if shell=True is used

303

shell_enabled = False

304

if 'shell' in keywords:

305

shell_node = keywords['shell']

306

if hasattr(shell_node, 'value') and shell_node.value:

307

shell_enabled = True

308

309

if shell_enabled and args:

310

# Analyze first argument for user input patterns

311

first_arg = args[0]

312

if hasattr(first_arg, 's'): # String literal

313

command = first_arg.s

314

# Check for common injection patterns

315

if any(pattern in command for pattern in ['%s', '{}', '+', 'format(']):

316

return bandit.Issue(

317

severity=bandit.HIGH,

318

confidence=bandit.MEDIUM,

319

text="subprocess call with shell=True and potential injection",

320

cwe=78

321

)

322

```