-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathquery_validation.py
More file actions
133 lines (116 loc) · 4.4 KB
/
Copy pathquery_validation.py
File metadata and controls
133 lines (116 loc) · 4.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import nltk
import numpy as np
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from nltk.corpus import stopwords
import re
class QueryValidator:
def __init__(self):
self.tokenizer = Tokenizer(num_words=1000)
self.max_length = 20
self.model = self._create_model()
# Download NLTK data
nltk.download('punkt', quiet=True)
nltk.download('stopwords', quiet=True)
# Load stopwords
self.stop_words = set(stopwords.words('english'))
# SQL-related keywords that should be present in valid queries
self.sql_keywords = {
'show', 'select', 'find', 'get', 'list', 'count', 'display',
'where', 'how many', 'which', 'what', 'table', 'database',
'total', 'average', 'sum', 'join', 'group', 'filter'
}
# Common informal/chat patterns
self.informal_patterns = [
r'^hi\b',
r'^hello\b',
r'^hey\b',
r'how are you',
r'who are you',
r'what is your name',
r'tell me about yourself',
r'^thanks?\b',
r'^ok\b',
r'^bye\b'
]
# Suspicious patterns
self.patterns = [
r"drop\s+table",
r"delete\s+from",
r"truncate\s+table",
r"alter\s+table",
r"exec\s*\(",
r"system\s*\(",
r"union\s+select",
r"information_schema",
r"--", # SQL comment
r";\s*\w+", # Multiple statements
r"xp_cmdshell",
r"INTO\s+OUTFILE",
r"LOAD_FILE",
r"0x[0-9a-fA-F]+", # Hex values
r"@@", # System variables
r"waitfor\s+delay",
r"benchmark\s*\("
]
def _create_model(self):
model = tf.keras.Sequential([
tf.keras.layers.Embedding(1000, 16, input_length=self.max_length),
tf.keras.layers.GlobalAveragePooling1D(),
tf.keras.layers.Dense(24, activation='relu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
model.compile(optimizer='adam', loss='binary_crossentropy')
return model
def validate(self, query):
# Check for informal or chat-like text
query_lower = query.lower()
# Check for informal patterns
for pattern in self.informal_patterns:
if re.search(pattern, query_lower):
return {
'is_safe': False,
'warning': "This appears to be informal text. Please ask a database-related question."
}
# Check if query contains any SQL-related keywords
tokens = nltk.word_tokenize(query_lower)
words = set(tokens) - self.stop_words
has_sql_keyword = any(kw in query_lower for kw in self.sql_keywords)
if not has_sql_keyword:
return {
'is_safe': False,
'warning': "Your question doesn't appear to be related to database querying. Please rephrase with SQL-related terms."
}
# Check for suspicious SQL patterns
for pattern in self.patterns:
if re.search(pattern, query_lower):
return {
'is_safe': False,
'warning': f"Suspicious pattern detected: {pattern}"
}
# Check complexity
if len(tokens) > 20:
return {
'is_safe': False,
'warning': "Query too complex"
}
# Check for multiple statements
if query.count(';') > 1:
return {
'is_safe': False,
'warning': "Multiple SQL statements not allowed"
}
# Check for direct string literals
if "'" in query or '"' in query:
return {
'is_safe': False,
'warning': "Direct string literals not allowed in natural language query"
}
# Check for numeric overflow attempts
if re.search(r'\d{10,}', query):
return {
'is_safe': False,
'warning': "Suspicious numeric values detected"
}
return {'is_safe': True}