-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
security: add whitelist validation for SQLite PRAGMA settings #1529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -60,8 +60,16 @@ def create_connection(): | |||||||||||||||||||||||||||||||||||||||||
| cursor = connection.cursor() | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| # Performance enhancing configurations. Put WAL cause that helps with concurrency. | ||||||||||||||||||||||||||||||||||||||||||
| cursor.execute(f"PRAGMA journal_mode={Config.db.journal_mode}") | ||||||||||||||||||||||||||||||||||||||||||
| cursor.execute(f"PRAGMA synchronous={Config.db.synchronous_mode}") | ||||||||||||||||||||||||||||||||||||||||||
| allowed_journal_modes = {"DELETE", "WAL", "MEMORY", "OFF"} | ||||||||||||||||||||||||||||||||||||||||||
| allowed_sync_modes = {"OFF", "NORMAL", "FULL", "EXTRA"} | ||||||||||||||||||||||||||||||||||||||||||
| journal_mode = Config.db.journal_mode | ||||||||||||||||||||||||||||||||||||||||||
| sync_mode = Config.db.synchronous_mode | ||||||||||||||||||||||||||||||||||||||||||
| if journal_mode not in allowed_journal_modes: | ||||||||||||||||||||||||||||||||||||||||||
| raise ValueError(f"Invalid journal_mode: {journal_mode}") | ||||||||||||||||||||||||||||||||||||||||||
| if sync_mode not in allowed_sync_modes: | ||||||||||||||||||||||||||||||||||||||||||
| raise ValueError(f"Invalid synchronous_mode: {sync_mode}") | ||||||||||||||||||||||||||||||||||||||||||
| cursor.execute(f"PRAGMA journal_mode={journal_mode}") | ||||||||||||||||||||||||||||||||||||||||||
| cursor.execute(f"PRAGMA synchronous={sync_mode}") | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+63
to
+72
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: The valid values for SQLite PRAGMA journal_mode are: DELETE, TRUNCATE, PERSIST, MEMORY, WAL, OFF. These are explicitly listed in the official SQLite documentation as the options that can be queried or set using PRAGMA journal_mode = DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF. DELETE is the default mode, using a rollback journal that is deleted after each transaction. TRUNCATE truncates the journal to zero length. PERSIST overwrites the journal header but keeps the file. MEMORY stores the journal in RAM (risking corruption on crash). WAL uses write-ahead logging for better concurrency. OFF disables journaling entirely (highly risky, disables atomic commits). Note that for in-memory databases, only MEMORY or OFF are applicable, and changes to other modes are ignored. WAL mode is persistent across connections. Citations:
🏁 Script executed: # First, locate and read the database file
find . -name "db.py" -path "*/database/*" | head -20Repository: OWASP/Nettacker Length of output: 86 🏁 Script executed: # Read the specific lines from the file
sed -n '50,80p' ./nettacker/database/db.pyRepository: OWASP/Nettacker Length of output: 1464 🌐 Web query:
💡 Result: The valid values for the SQLite PRAGMA synchronous are: - 0 or OFF: Minimal synchronization, fastest but risks corruption on OS crash or power loss. - 1 or NORMAL: Syncs at critical moments, good balance for WAL mode, small risk in rollback mode. - 2 or FULL: Ensures data is written to disk before continuing, safe against crashes (default for rollback journal). - 3 or EXTRA: Like FULL but also syncs the directory after unlinking rollback journal, maximum durability. Usage: PRAGMA [schema.]synchronous; (query) or PRAGMA [schema.]synchronous = value; (set). TEMP schema always uses OFF. FULL is recommended for durability in rollback mode; NORMAL for WAL mode performance. Citations:
Whitelist omits two valid SQLite journal modes and uses case-sensitive comparison. SQLite's 🔧 Proposed fix- allowed_journal_modes = {"DELETE", "WAL", "MEMORY", "OFF"}
- allowed_sync_modes = {"OFF", "NORMAL", "FULL", "EXTRA"}
- journal_mode = Config.db.journal_mode
- sync_mode = Config.db.synchronous_mode
- if journal_mode not in allowed_journal_modes:
- raise ValueError(f"Invalid journal_mode: {journal_mode}")
- if sync_mode not in allowed_sync_modes:
- raise ValueError(f"Invalid synchronous_mode: {sync_mode}")
- cursor.execute(f"PRAGMA journal_mode={journal_mode}")
- cursor.execute(f"PRAGMA synchronous={sync_mode}")
+ allowed_journal_modes = {"DELETE", "TRUNCATE", "PERSIST", "MEMORY", "WAL", "OFF"}
+ allowed_sync_modes = {"OFF", "NORMAL", "FULL", "EXTRA"}
+ journal_mode = str(Config.db.journal_mode).upper()
+ sync_mode = str(Config.db.synchronous_mode).upper()
+ if journal_mode not in allowed_journal_modes:
+ raise ValueError(f"Invalid journal_mode: {Config.db.journal_mode}")
+ if sync_mode not in allowed_sync_modes:
+ raise ValueError(f"Invalid synchronous_mode: {Config.db.synchronous_mode}")
+ cursor.execute(f"PRAGMA journal_mode={journal_mode}")
+ cursor.execute(f"PRAGMA synchronous={sync_mode}")📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return connection, cursor | ||||||||||||||||||||||||||||||||||||||||||
| except Exception as e: | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,11 @@ def mysql_create_database(): | |
| existing_databases = [d[0] for d in existing_databases] | ||
|
|
||
| if Config.db.name not in existing_databases: | ||
| conn.execute(text("CREATE DATABASE {0} ".format(Config.db.name))) | ||
| db_name = Config.db.name | ||
| if db_name.isalnum() and db_name[0].isalpha(): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The new check Useful? React with 👍 / 👎. |
||
| conn.execute(text(f"CREATE DATABASE `{db_name}` ")) | ||
| else: | ||
| raise ValueError(f"Invalid database name: {db_name}") | ||
| except Exception as e: | ||
| print(e) | ||
|
Comment on lines
22
to
29
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The raised The new validation raises 🔧 Proposed fix- except Exception as e:
- print(e)
+ except ValueError:
+ raise
+ except Exception as e:
+ print(e)Also, 🧰 Tools🪛 Ruff (0.15.11)[warning] 28-28: Do not catch blind exception: (BLE001) 🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -26,7 +26,11 @@ def postgres_create_database(): | |||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| conn = engine.connect() | ||||||||||||||||||||||||||
| conn = conn.execution_options(isolation_level="AUTOCOMMIT") | ||||||||||||||||||||||||||
| conn.execute(text(f"CREATE DATABASE {Config.db.name}")) | ||||||||||||||||||||||||||
| db_name = Config.db.name | ||||||||||||||||||||||||||
| if db_name.isalnum() and db_name[0].isalpha(): | ||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The same validation pattern in PostgreSQL setup now rejects common valid names like Useful? React with 👍 / 👎. |
||||||||||||||||||||||||||
| conn.execute(text(f'CREATE DATABASE "{db_name}"')) | ||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||
| raise ValueError(f"Invalid database name: {db_name}") | ||||||||||||||||||||||||||
|
Comment on lines
+29
to
+33
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validation is too strict — rejects valid PostgreSQL identifiers containing underscores.
🔧 Proposed fix+import re
...
db_name = Config.db.name
- if db_name.isalnum() and db_name[0].isalpha():
+ if re.fullmatch(r"[A-Za-z_][A-Za-z0-9_]*", db_name):
conn.execute(text(f'CREATE DATABASE "{db_name}"'))
else:
- raise ValueError(f"Invalid database name: {db_name}")
+ raise ValueError(f"Invalid database name: {db_name}") from NoneThe same tightening applies symmetrically in 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.15.11)[warning] 33-33: Within an (B904) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||
| conn.close() | ||||||||||||||||||||||||||
| engine = create_engine( | ||||||||||||||||||||||||||
| "postgresql+psycopg2://{username}:{password}@{host}:{port}/{name}".format( | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tighten the file-read exception scope.
The new
withblocks are good, but these catches still swallow decode and I/O failures under a genericException, which makes bad input look like the samedie_failure(...)path. Narrow them to the file errors you actually expect and apply the same change to all four read-from-file paths.♻️ Example tightening
Apply the same narrowing to the
targets_list,passwords_list, andread_from_fileblocks.Also applies to: 717-721, 726-730, 733-737
🧰 Tools
🪛 Ruff (0.15.12)
[warning] 617-617: Do not catch blind exception:
Exception(BLE001)
🤖 Prompt for AI Agents