acidtest 0.8.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/.github/workflows/acidtest-pr-comment.yml +219 -0
  2. package/README.md +176 -36
  3. package/dist/analysis/dataflow-graph.d.ts +19 -0
  4. package/dist/analysis/dataflow-graph.d.ts.map +1 -0
  5. package/dist/analysis/dataflow-graph.js +365 -0
  6. package/dist/analysis/dataflow-graph.js.map +1 -0
  7. package/dist/analysis/dataflow-types.d.ts +86 -0
  8. package/dist/analysis/dataflow-types.d.ts.map +1 -0
  9. package/dist/analysis/dataflow-types.js +8 -0
  10. package/dist/analysis/dataflow-types.js.map +1 -0
  11. package/dist/analysis/dataflow.test.d.ts +7 -0
  12. package/dist/analysis/dataflow.test.d.ts.map +1 -0
  13. package/dist/analysis/dataflow.test.js +257 -0
  14. package/dist/analysis/dataflow.test.js.map +1 -0
  15. package/dist/analysis/taint-propagation.d.ts +30 -0
  16. package/dist/analysis/taint-propagation.d.ts.map +1 -0
  17. package/dist/analysis/taint-propagation.js +207 -0
  18. package/dist/analysis/taint-propagation.js.map +1 -0
  19. package/dist/index.js +1 -1
  20. package/dist/layers/code.d.ts +1 -1
  21. package/dist/layers/code.d.ts.map +1 -1
  22. package/dist/layers/code.js +247 -3
  23. package/dist/layers/code.js.map +1 -1
  24. package/dist/layers/code.test.js +196 -0
  25. package/dist/layers/code.test.js.map +1 -1
  26. package/dist/layers/crossref.d.ts.map +1 -1
  27. package/dist/layers/crossref.js +7 -0
  28. package/dist/layers/crossref.js.map +1 -1
  29. package/dist/layers/dataflow.d.ts +29 -0
  30. package/dist/layers/dataflow.d.ts.map +1 -0
  31. package/dist/layers/dataflow.js +217 -0
  32. package/dist/layers/dataflow.js.map +1 -0
  33. package/dist/layers/injection.d.ts.map +1 -1
  34. package/dist/layers/injection.js +8 -1
  35. package/dist/layers/injection.js.map +1 -1
  36. package/dist/layers/permissions.d.ts.map +1 -1
  37. package/dist/layers/permissions.js +7 -0
  38. package/dist/layers/permissions.js.map +1 -1
  39. package/dist/mcp-server.js +1 -1
  40. package/dist/parsers/parser-interface.d.ts +31 -0
  41. package/dist/parsers/parser-interface.d.ts.map +1 -0
  42. package/dist/parsers/parser-interface.js +6 -0
  43. package/dist/parsers/parser-interface.js.map +1 -0
  44. package/dist/parsers/parsers.test.d.ts +5 -0
  45. package/dist/parsers/parsers.test.d.ts.map +1 -0
  46. package/dist/parsers/parsers.test.js +111 -0
  47. package/dist/parsers/parsers.test.js.map +1 -0
  48. package/dist/parsers/python-parser.d.ts +18 -0
  49. package/dist/parsers/python-parser.d.ts.map +1 -0
  50. package/dist/parsers/python-parser.js +120 -0
  51. package/dist/parsers/python-parser.js.map +1 -0
  52. package/dist/parsers/typescript-parser.d.ts +16 -0
  53. package/dist/parsers/typescript-parser.d.ts.map +1 -0
  54. package/dist/parsers/typescript-parser.js +112 -0
  55. package/dist/parsers/typescript-parser.js.map +1 -0
  56. package/dist/patterns/dangerous-calls-python.json +220 -0
  57. package/dist/patterns/dangerous-imports-python.json +256 -0
  58. package/dist/patterns/insecure-crypto.json +163 -0
  59. package/dist/patterns/prototype-pollution.json +72 -0
  60. package/dist/patterns/python-deserialization.json +94 -0
  61. package/dist/patterns/regex-dos.json +50 -0
  62. package/dist/patterns/sql-injection.json +91 -0
  63. package/dist/patterns/xss-injection.json +115 -0
  64. package/dist/reporter.d.ts.map +1 -1
  65. package/dist/reporter.js +6 -0
  66. package/dist/reporter.js.map +1 -1
  67. package/dist/scanner.d.ts +1 -1
  68. package/dist/scanner.d.ts.map +1 -1
  69. package/dist/scanner.js +48 -5
  70. package/dist/scanner.js.map +1 -1
  71. package/dist/scanner.test.js +31 -0
  72. package/dist/scanner.test.js.map +1 -1
  73. package/dist/schemas/pattern.schema.json +139 -0
  74. package/dist/test-corpus/validate-corpus.d.ts +7 -0
  75. package/dist/test-corpus/validate-corpus.d.ts.map +1 -0
  76. package/dist/test-corpus/validate-corpus.js +341 -0
  77. package/dist/test-corpus/validate-corpus.js.map +1 -0
  78. package/dist/types.d.ts +4 -2
  79. package/dist/types.d.ts.map +1 -1
  80. package/dist/validation/pattern-validator.d.ts +34 -0
  81. package/dist/validation/pattern-validator.d.ts.map +1 -0
  82. package/dist/validation/pattern-validator.js +168 -0
  83. package/dist/validation/pattern-validator.js.map +1 -0
  84. package/dist/validation/pattern-validator.test.d.ts +5 -0
  85. package/dist/validation/pattern-validator.test.d.ts.map +1 -0
  86. package/dist/validation/pattern-validator.test.js +222 -0
  87. package/dist/validation/pattern-validator.test.js.map +1 -0
  88. package/dist/validation/validate-patterns.d.ts +6 -0
  89. package/dist/validation/validate-patterns.d.ts.map +1 -0
  90. package/dist/validation/validate-patterns.js +55 -0
  91. package/dist/validation/validate-patterns.js.map +1 -0
  92. package/package.json +11 -4
  93. package/test-fixtures/fixture-no-manifest-node/README.md +4 -0
  94. package/test-fixtures/fixture-no-manifest-node/index.js +24 -0
  95. package/test-fixtures/fixture-no-manifest-python/README.md +4 -0
  96. package/test-fixtures/fixture-no-manifest-python/app.py +24 -0
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Python parser implementation using tree-sitter-python
3
+ * Extracts imports, functions, and variables from Python code
4
+ */
5
+ import Parser from 'tree-sitter';
6
+ import Python from 'tree-sitter-python';
7
+ export class PythonParser {
8
+ parser;
9
+ constructor() {
10
+ this.parser = new Parser();
11
+ // For tree-sitter 0.21.x, Python is the language object itself
12
+ this.parser.setLanguage(Python);
13
+ }
14
+ /**
15
+ * Check if this parser can handle the given file
16
+ */
17
+ canParse(filePath) {
18
+ return /\.py$/i.test(filePath);
19
+ }
20
+ /**
21
+ * Parse Python file and extract information
22
+ */
23
+ parse(filePath, content) {
24
+ const tree = this.parser.parse(content);
25
+ const rootNode = tree.rootNode;
26
+ const imports = [];
27
+ const functions = [];
28
+ const variables = [];
29
+ // Traverse the AST
30
+ const traverse = (node) => {
31
+ // Extract import statements: import X, import Y
32
+ if (node.type === 'import_statement') {
33
+ const nameNode = node.childForFieldName('name');
34
+ if (nameNode) {
35
+ const module = nameNode.text;
36
+ const line = node.startPosition.row + 1;
37
+ imports.push({ module, names: [], line });
38
+ }
39
+ }
40
+ // Extract from imports: from X import Y, Z
41
+ if (node.type === 'import_from_statement') {
42
+ const moduleNode = node.childForFieldName('module_name');
43
+ const module = moduleNode ? moduleNode.text : '';
44
+ const names = [];
45
+ const line = node.startPosition.row + 1;
46
+ // Get imported names
47
+ for (let i = 0; i < node.childCount; i++) {
48
+ const child = node.child(i);
49
+ if (child?.type === 'dotted_name' || child?.type === 'identifier') {
50
+ // This might be the imported name
51
+ const nameText = child.text;
52
+ if (nameText !== module && !names.includes(nameText)) {
53
+ names.push(nameText);
54
+ }
55
+ }
56
+ else if (child?.type === 'aliased_import') {
57
+ const nameChild = child.childForFieldName('name');
58
+ if (nameChild) {
59
+ names.push(nameChild.text);
60
+ }
61
+ }
62
+ }
63
+ imports.push({ module, names, line });
64
+ }
65
+ // Extract function definitions
66
+ if (node.type === 'function_definition') {
67
+ const nameNode = node.childForFieldName('name');
68
+ if (nameNode) {
69
+ const name = nameNode.text;
70
+ const params = [];
71
+ const line = node.startPosition.row + 1;
72
+ // Get parameters
73
+ const parametersNode = node.childForFieldName('parameters');
74
+ if (parametersNode) {
75
+ for (let i = 0; i < parametersNode.childCount; i++) {
76
+ const paramChild = parametersNode.child(i);
77
+ if (paramChild?.type === 'identifier') {
78
+ params.push(paramChild.text);
79
+ }
80
+ else if (paramChild?.type === 'typed_parameter' || paramChild?.type === 'default_parameter') {
81
+ const paramName = paramChild.childForFieldName('name');
82
+ if (paramName) {
83
+ params.push(paramName.text);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ functions.push({ name, params, line });
89
+ }
90
+ }
91
+ // Extract variable assignments at module level
92
+ if (node.type === 'assignment' && node.parent?.type === 'expression_statement') {
93
+ const leftNode = node.childForFieldName('left');
94
+ const rightNode = node.childForFieldName('right');
95
+ if (leftNode?.type === 'identifier') {
96
+ const name = leftNode.text;
97
+ const value = rightNode ? rightNode.text.substring(0, 100) : undefined;
98
+ const line = node.startPosition.row + 1;
99
+ variables.push({ name, value, line });
100
+ }
101
+ }
102
+ // Recursively traverse children
103
+ for (let i = 0; i < node.childCount; i++) {
104
+ const child = node.child(i);
105
+ if (child) {
106
+ traverse(child);
107
+ }
108
+ }
109
+ };
110
+ traverse(rootNode);
111
+ return {
112
+ filePath,
113
+ ast: tree,
114
+ imports,
115
+ functions,
116
+ variables
117
+ };
118
+ }
119
+ }
120
+ //# sourceMappingURL=python-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"python-parser.js","sourceRoot":"","sources":["../../src/parsers/python-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * TypeScript/JavaScript parser implementation
3
+ * Extracts imports, functions, and variables from TypeScript/JavaScript code
4
+ */
5
+ import type { Parser, ParsedFile } from './parser-interface.js';
6
+ export declare class TypeScriptParser implements Parser {
7
+ /**
8
+ * Check if this parser can handle the given file
9
+ */
10
+ canParse(filePath: string): boolean;
11
+ /**
12
+ * Parse TypeScript/JavaScript file and extract information
13
+ */
14
+ parse(filePath: string, content: string): ParsedFile;
15
+ }
16
+ //# sourceMappingURL=typescript-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-parser.d.ts","sourceRoot":"","sources":["../../src/parsers/typescript-parser.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAA4D,MAAM,uBAAuB,CAAC;AAE1H,qBAAa,gBAAiB,YAAW,MAAM;IAC7C;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAInC;;OAEG;IACH,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,UAAU;CA+GrD"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * TypeScript/JavaScript parser implementation
3
+ * Extracts imports, functions, and variables from TypeScript/JavaScript code
4
+ */
5
+ import ts from 'typescript';
6
+ export class TypeScriptParser {
7
+ /**
8
+ * Check if this parser can handle the given file
9
+ */
10
+ canParse(filePath) {
11
+ return /\.(ts|js|mjs|cjs)$/i.test(filePath);
12
+ }
13
+ /**
14
+ * Parse TypeScript/JavaScript file and extract information
15
+ */
16
+ parse(filePath, content) {
17
+ const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
18
+ const imports = [];
19
+ const functions = [];
20
+ const variables = [];
21
+ // Traverse AST to extract imports, functions, and variables
22
+ const visit = (node) => {
23
+ // Extract import statements
24
+ if (ts.isImportDeclaration(node)) {
25
+ const importClause = node.importClause;
26
+ const moduleSpecifier = node.moduleSpecifier;
27
+ if (ts.isStringLiteral(moduleSpecifier)) {
28
+ const module = moduleSpecifier.text;
29
+ const names = [];
30
+ // Named imports
31
+ if (importClause?.namedBindings) {
32
+ if (ts.isNamedImports(importClause.namedBindings)) {
33
+ for (const element of importClause.namedBindings.elements) {
34
+ names.push(element.name.text);
35
+ }
36
+ }
37
+ else if (ts.isNamespaceImport(importClause.namedBindings)) {
38
+ names.push(importClause.namedBindings.name.text);
39
+ }
40
+ }
41
+ // Default import
42
+ if (importClause?.name) {
43
+ names.push(importClause.name.text);
44
+ }
45
+ const line = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
46
+ imports.push({ module, names, line });
47
+ }
48
+ }
49
+ // Extract require() calls
50
+ if (ts.isCallExpression(node)) {
51
+ const expression = node.expression;
52
+ if (ts.isIdentifier(expression) && expression.text === 'require') {
53
+ if (node.arguments.length > 0) {
54
+ const arg = node.arguments[0];
55
+ if (ts.isStringLiteral(arg)) {
56
+ const module = arg.text;
57
+ const line = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
58
+ imports.push({ module, names: [], line });
59
+ }
60
+ }
61
+ }
62
+ }
63
+ // Extract function declarations
64
+ if (ts.isFunctionDeclaration(node) && node.name) {
65
+ const name = node.name.text;
66
+ const params = node.parameters.map(p => {
67
+ if (ts.isIdentifier(p.name)) {
68
+ return p.name.text;
69
+ }
70
+ return p.name.getText(sourceFile);
71
+ });
72
+ const line = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
73
+ functions.push({ name, params, line });
74
+ }
75
+ // Extract arrow functions assigned to variables
76
+ if (ts.isVariableStatement(node)) {
77
+ for (const declaration of node.declarationList.declarations) {
78
+ if (ts.isIdentifier(declaration.name) && declaration.initializer) {
79
+ const name = declaration.name.text;
80
+ const line = sourceFile.getLineAndCharacterOfPosition(declaration.getStart()).line + 1;
81
+ // Check if it's a function
82
+ if (ts.isArrowFunction(declaration.initializer) || ts.isFunctionExpression(declaration.initializer)) {
83
+ const funcNode = declaration.initializer;
84
+ const params = funcNode.parameters.map(p => {
85
+ if (ts.isIdentifier(p.name)) {
86
+ return p.name.text;
87
+ }
88
+ return p.name.getText(sourceFile);
89
+ });
90
+ functions.push({ name, params, line });
91
+ }
92
+ else {
93
+ // Regular variable
94
+ const value = declaration.initializer.getText(sourceFile).substring(0, 100);
95
+ variables.push({ name, value, line });
96
+ }
97
+ }
98
+ }
99
+ }
100
+ ts.forEachChild(node, visit);
101
+ };
102
+ visit(sourceFile);
103
+ return {
104
+ filePath,
105
+ ast: sourceFile,
106
+ imports,
107
+ functions,
108
+ variables
109
+ };
110
+ }
111
+ }
112
+ //# sourceMappingURL=typescript-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typescript-parser.js","sourceRoot":"","sources":["../../src/parsers/typescript-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,220 @@
1
+ {
2
+ "category": "dangerous-calls",
3
+ "patterns": [
4
+ {
5
+ "id": "pycall-001",
6
+ "name": "subprocess-shell-true",
7
+ "description": "Uses subprocess with shell=True, enabling shell injection",
8
+ "severity": "CRITICAL",
9
+ "match": {
10
+ "type": "regex",
11
+ "value": "subprocess\\.(run|call|Popen|check_output|check_call)\\s*\\([^)]*shell\\s*=\\s*True",
12
+ "flags": "g"
13
+ },
14
+ "layer": "code",
15
+ "remediation": {
16
+ "title": "Remove shell=True from subprocess calls",
17
+ "suggestions": [
18
+ "Use explicit argument lists: subprocess.run(['cmd', 'arg1', 'arg2'])",
19
+ "Never set shell=True, especially with user input",
20
+ "Use shlex.quote() if you must construct shell commands",
21
+ "Consider using pathlib or os.path for file operations instead",
22
+ "Validate and sanitize all arguments before passing to subprocess"
23
+ ]
24
+ }
25
+ },
26
+ {
27
+ "id": "pycall-002",
28
+ "name": "os-system-call",
29
+ "description": "Uses os.system() for direct shell command execution",
30
+ "severity": "CRITICAL",
31
+ "match": {
32
+ "type": "regex",
33
+ "value": "os\\.system\\s*\\(",
34
+ "flags": "g"
35
+ },
36
+ "layer": "code",
37
+ "remediation": {
38
+ "title": "Replace os.system() with subprocess",
39
+ "suggestions": [
40
+ "Use subprocess.run() with explicit arguments instead",
41
+ "Never use os.system() with user-controlled input",
42
+ "Consider using built-in Python APIs for file/path operations",
43
+ "If shell commands are needed, use subprocess without shell=True"
44
+ ]
45
+ }
46
+ },
47
+ {
48
+ "id": "pycall-003",
49
+ "name": "os-popen-call",
50
+ "description": "Uses os.popen() for shell command execution",
51
+ "severity": "CRITICAL",
52
+ "match": {
53
+ "type": "regex",
54
+ "value": "os\\.popen[234]?\\s*\\(",
55
+ "flags": "g"
56
+ },
57
+ "layer": "code"
58
+ },
59
+ {
60
+ "id": "pycall-004",
61
+ "name": "os-exec-family",
62
+ "description": "Uses os.exec* family for program execution",
63
+ "severity": "HIGH",
64
+ "match": {
65
+ "type": "regex",
66
+ "value": "os\\.(execl|execle|execlp|execlpe|execv|execve|execvp|execvpe)\\s*\\(",
67
+ "flags": "g"
68
+ },
69
+ "layer": "code"
70
+ },
71
+ {
72
+ "id": "pycall-005",
73
+ "name": "os-spawn-family",
74
+ "description": "Uses os.spawn* family for process spawning",
75
+ "severity": "HIGH",
76
+ "match": {
77
+ "type": "regex",
78
+ "value": "os\\.(spawnl|spawnle|spawnlp|spawnlpe|spawnv|spawnve|spawnvp|spawnvpe)\\s*\\(",
79
+ "flags": "g"
80
+ },
81
+ "layer": "code"
82
+ },
83
+ {
84
+ "id": "pycall-006",
85
+ "name": "pickle-loads-call",
86
+ "description": "Uses pickle.loads() which can execute arbitrary code",
87
+ "severity": "CRITICAL",
88
+ "match": {
89
+ "type": "regex",
90
+ "value": "pickle\\.(loads?|Unpickler)\\s*\\(",
91
+ "flags": "g"
92
+ },
93
+ "layer": "code",
94
+ "remediation": {
95
+ "title": "Avoid unpickling untrusted data",
96
+ "suggestions": [
97
+ "Use json.loads() for deserializing JSON data instead",
98
+ "Never unpickle data from untrusted or user-controlled sources",
99
+ "If pickle is required, verify data integrity with HMAC signatures",
100
+ "Consider using safer formats like JSON, msgpack, or protobuf",
101
+ "Implement a restricted unpickler with custom find_class() method"
102
+ ]
103
+ }
104
+ },
105
+ {
106
+ "id": "pycall-007",
107
+ "name": "marshal-loads-call",
108
+ "description": "Uses marshal.loads() for deserialization",
109
+ "severity": "HIGH",
110
+ "match": {
111
+ "type": "regex",
112
+ "value": "marshal\\.loads?\\s*\\(",
113
+ "flags": "g"
114
+ },
115
+ "layer": "code"
116
+ },
117
+ {
118
+ "id": "pycall-008",
119
+ "name": "yaml-unsafe-load",
120
+ "description": "Uses yaml.load() without safe loader, enabling arbitrary code execution",
121
+ "severity": "CRITICAL",
122
+ "match": {
123
+ "type": "regex",
124
+ "value": "yaml\\.load\\s*\\([^,)]*\\)",
125
+ "flags": "g"
126
+ },
127
+ "layer": "code",
128
+ "remediation": {
129
+ "title": "Use yaml.safe_load() instead",
130
+ "suggestions": [
131
+ "Replace yaml.load() with yaml.safe_load()",
132
+ "If you need custom tags, use yaml.load(data, Loader=yaml.SafeLoader)",
133
+ "Never use yaml.load() with untrusted input",
134
+ "Consider validating YAML structure after loading"
135
+ ]
136
+ }
137
+ },
138
+ {
139
+ "id": "pycall-009",
140
+ "name": "code-object-exec",
141
+ "description": "Executes code objects from compile()",
142
+ "severity": "HIGH",
143
+ "match": {
144
+ "type": "regex",
145
+ "value": "exec\\s*\\(\\s*compile\\s*\\(",
146
+ "flags": "g"
147
+ },
148
+ "layer": "code"
149
+ },
150
+ {
151
+ "id": "pycall-010",
152
+ "name": "file-write-operations",
153
+ "description": "Opens files in write mode which could overwrite data",
154
+ "severity": "MEDIUM",
155
+ "match": {
156
+ "type": "regex",
157
+ "value": "open\\s*\\([^)]*['\"]w",
158
+ "flags": "g"
159
+ },
160
+ "layer": "code"
161
+ },
162
+ {
163
+ "id": "pycall-011",
164
+ "name": "os-remove-operations",
165
+ "description": "Deletes files or directories",
166
+ "severity": "MEDIUM",
167
+ "match": {
168
+ "type": "regex",
169
+ "value": "os\\.(remove|unlink|rmdir|removedirs)\\s*\\(",
170
+ "flags": "g"
171
+ },
172
+ "layer": "code"
173
+ },
174
+ {
175
+ "id": "pycall-012",
176
+ "name": "shutil-rmtree",
177
+ "description": "Recursively deletes directory trees",
178
+ "severity": "HIGH",
179
+ "match": {
180
+ "type": "regex",
181
+ "value": "shutil\\.rmtree\\s*\\(",
182
+ "flags": "g"
183
+ },
184
+ "layer": "code"
185
+ },
186
+ {
187
+ "id": "pycall-013",
188
+ "name": "tempfile-mktemp",
189
+ "description": "Uses deprecated mktemp() which has security issues",
190
+ "severity": "MEDIUM",
191
+ "match": {
192
+ "type": "regex",
193
+ "value": "tempfile\\.mktemp\\s*\\(",
194
+ "flags": "g"
195
+ },
196
+ "layer": "code",
197
+ "remediation": {
198
+ "title": "Replace mktemp() with safer alternatives",
199
+ "suggestions": [
200
+ "Use tempfile.mkstemp() which creates files securely",
201
+ "Use tempfile.TemporaryFile() for automatic cleanup",
202
+ "Use tempfile.NamedTemporaryFile() if you need a file name",
203
+ "Never use mktemp() as it's vulnerable to race conditions"
204
+ ]
205
+ }
206
+ },
207
+ {
208
+ "id": "pycall-014",
209
+ "name": "assert-statement",
210
+ "description": "Uses assert statements which are removed in optimized bytecode",
211
+ "severity": "LOW",
212
+ "match": {
213
+ "type": "regex",
214
+ "value": "\\bassert\\s+",
215
+ "flags": "g"
216
+ },
217
+ "layer": "code"
218
+ }
219
+ ]
220
+ }