Eishaan commited on
Commit
306d70e
·
1 Parent(s): f10b032

security: patch 5 critical grader and environment vulnerabilities

Browse files
__pycache__/models.cpython-312.pyc CHANGED
Binary files a/__pycache__/models.cpython-312.pyc and b/__pycache__/models.cpython-312.pyc differ
 
server/__pycache__/environment.cpython-312.pyc CHANGED
Binary files a/server/__pycache__/environment.cpython-312.pyc and b/server/__pycache__/environment.cpython-312.pyc differ
 
server/__pycache__/grader.cpython-312.pyc CHANGED
Binary files a/server/__pycache__/grader.cpython-312.pyc and b/server/__pycache__/grader.cpython-312.pyc differ
 
server/environment.py CHANGED
@@ -116,7 +116,7 @@ class DbMigrationEnvironment(Environment):
116
  def _is_read_query(self, sql: str) -> bool:
117
  """Check if SQL is a read-only query (SELECT or certain PRAGMAs)."""
118
  stripped = sql.strip().upper()
119
- if stripped.startswith("SELECT"):
120
  return True
121
  # PRAGMA table_info, foreign_key_list, etc. are read-only
122
  if stripped.startswith("PRAGMA") and "=" not in stripped:
@@ -318,7 +318,7 @@ class DbMigrationEnvironment(Environment):
318
 
319
  # --- A3: Dangerous SQL Blacklist ---
320
  sql_lower = sql_command.lower()
321
- if "pragma" in sql_lower and "foreign_keys" in sql_lower and "off" in sql_lower:
322
  execution_result = "Security Error: Disabling PRAGMA foreign_keys is strictly explicitly forbidden."
323
  action_error = "pragma_off_blocked"
324
  elif _DANGEROUS_PATTERNS.search(sql_command):
 
116
  def _is_read_query(self, sql: str) -> bool:
117
  """Check if SQL is a read-only query (SELECT or certain PRAGMAs)."""
118
  stripped = sql.strip().upper()
119
+ if stripped.startswith("SELECT") or stripped.startswith("WITH"):
120
  return True
121
  # PRAGMA table_info, foreign_key_list, etc. are read-only
122
  if stripped.startswith("PRAGMA") and "=" not in stripped:
 
318
 
319
  # --- A3: Dangerous SQL Blacklist ---
320
  sql_lower = sql_command.lower()
321
+ if re.search(r"pragma\s+foreign_keys\s*=\s*(off|0)", sql_lower):
322
  execution_result = "Security Error: Disabling PRAGMA foreign_keys is strictly explicitly forbidden."
323
  action_error = "pragma_off_blocked"
324
  elif _DANGEROUS_PATTERNS.search(sql_command):
server/grader.py CHANGED
@@ -61,6 +61,11 @@ def _get_column_names(conn: sqlite3.Connection, table: str) -> Set[str]:
61
  return {col["name"] for col in _get_column_info(conn, table)}
62
 
63
 
 
 
 
 
 
64
  def _get_row_count(conn: sqlite3.Connection, table: str) -> int:
65
  """Get row count. Returns 0 on error."""
66
  try:
@@ -95,12 +100,12 @@ def _has_foreign_key(conn: sqlite3.Connection, table: str, ref_table: str) -> bo
95
 
96
 
97
  def _count_foreign_keys(conn: sqlite3.Connection, table: str) -> int:
98
- """Count all FK relationships for a table."""
99
  try:
100
  cursor = conn.execute(f"PRAGMA foreign_key_list([{table}])")
101
  refs = set()
102
  for row in cursor.fetchall():
103
- refs.add(row[2].lower())
104
  return len(refs)
105
  except Exception:
106
  return 0
@@ -199,6 +204,7 @@ class StateReconciler:
199
  self._golden_table_data[table] = {
200
  "columns": _get_column_info(self._golden_conn, table),
201
  "col_names": _get_column_names(self._golden_conn, table),
 
202
  "rows": _get_all_rows(self._golden_conn, table),
203
  "row_count": _get_row_count(self._golden_conn, table),
204
  "fk_count": _count_foreign_keys(self._golden_conn, table),
@@ -274,9 +280,9 @@ class StateReconciler:
274
 
275
  if table in agent_tables:
276
  tables_found += 1
277
- # Column name comparison
278
- agent_cols = _get_column_names(conn, table)
279
- golden_cols = golden_info["col_names"]
280
  if golden_cols:
281
  col_overlap = len(agent_cols & golden_cols) / len(golden_cols)
282
  total_col_match += col_overlap
@@ -329,7 +335,12 @@ class StateReconciler:
329
  conn.execute("PRAGMA foreign_keys = ON")
330
  cursor = conn.execute("PRAGMA integrity_check")
331
  result = cursor.fetchone()[0]
332
- integrity_ok = (result == "ok")
 
 
 
 
 
333
  except Exception:
334
  pass
335
 
 
61
  return {col["name"] for col in _get_column_info(conn, table)}
62
 
63
 
64
+ def _get_column_signatures(conn: sqlite3.Connection, table: str) -> Set[Tuple[str, str]]:
65
+ """Get (name, type) tuples for strict schema grading."""
66
+ return {(col["name"], col["type"]) for col in _get_column_info(conn, table)}
67
+
68
+
69
  def _get_row_count(conn: sqlite3.Connection, table: str) -> int:
70
  """Get row count. Returns 0 on error."""
71
  try:
 
100
 
101
 
102
  def _count_foreign_keys(conn: sqlite3.Connection, table: str) -> int:
103
+ """Count unique FK constraints for a table using the FK id."""
104
  try:
105
  cursor = conn.execute(f"PRAGMA foreign_key_list([{table}])")
106
  refs = set()
107
  for row in cursor.fetchall():
108
+ refs.add(row[0]) # row[0] is the sequential ID of the foreign key constraint
109
  return len(refs)
110
  except Exception:
111
  return 0
 
204
  self._golden_table_data[table] = {
205
  "columns": _get_column_info(self._golden_conn, table),
206
  "col_names": _get_column_names(self._golden_conn, table),
207
+ "col_signatures": _get_column_signatures(self._golden_conn, table),
208
  "rows": _get_all_rows(self._golden_conn, table),
209
  "row_count": _get_row_count(self._golden_conn, table),
210
  "fk_count": _count_foreign_keys(self._golden_conn, table),
 
280
 
281
  if table in agent_tables:
282
  tables_found += 1
283
+ # Signature (name + type) comparison
284
+ agent_cols = _get_column_signatures(conn, table)
285
+ golden_cols = golden_info["col_signatures"]
286
  if golden_cols:
287
  col_overlap = len(agent_cols & golden_cols) / len(golden_cols)
288
  total_col_match += col_overlap
 
335
  conn.execute("PRAGMA foreign_keys = ON")
336
  cursor = conn.execute("PRAGMA integrity_check")
337
  result = cursor.fetchone()[0]
338
+
339
+ # Explicitly run foreign_key_check to catch orphaned rows
340
+ fk_cursor = conn.execute("PRAGMA foreign_key_check")
341
+ fk_violations = fk_cursor.fetchall()
342
+
343
+ integrity_ok = (result == "ok" and len(fk_violations) == 0)
344
  except Exception:
345
  pass
346