Update python driver security and formatting#2330
Merged
MuhammadTahaNaveed merged 1 commit intoapache:masterfrom Feb 13, 2026
Merged
Update python driver security and formatting#2330MuhammadTahaNaveed merged 1 commit intoapache:masterfrom
MuhammadTahaNaveed merged 1 commit intoapache:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR enhances security in the Apache AGE Python driver by implementing SQL injection prevention measures and improving input validation. The changes focus on replacing unsafe string formatting with parameterized queries using psycopg's sql.SQL(), sql.Identifier(), and sql.Literal() constructs throughout the codebase.
Changes:
- Added input validation functions (
validate_graph_name,validate_identifier,_validate_column) with regex-based checks for graph names and SQL identifiers - Replaced string interpolation with parameterized queries in
age.pyandnetworkx/lib.pyusing psycopg.sql module - Fixed exception constructors to accept optional arguments and added new exception classes (
InvalidGraphName,InvalidIdentifier) - Corrected builder.py to raise ValueError instead of returning Exception object
- Cleaned up file formatting (removed Windows line endings, fixed requirements.txt encoding)
- Updated CI workflow (GitHub Actions v4→v5, moved --no-binary flag to pip command)
Reviewed changes
Copilot reviewed 5 out of 11 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
| drivers/python/age/age.py | Added validation functions and parameterized query construction for graph operations |
| drivers/python/age/networkx/lib.py | Replaced string formatting with sql.Identifier/Literal throughout NetworkX integration |
| drivers/python/age/exceptions.py | Fixed exception constructors and added InvalidGraphName/InvalidIdentifier classes |
| drivers/python/age/builder.py | Fixed bug: changed return Exception to raise ValueError for unknown float expressions |
| drivers/python/requirements.txt | Fixed encoding (UTF-16LE→UTF-8) and formatting (CRLF→LF) |
| .github/workflows/python-driver.yaml | Upgraded actions/setup-python v4→v5, moved --no-binary flag to pip command |
| drivers/python/test_agtypes.py | Removed Windows carriage returns (formatting only) |
| drivers/python/setup.py | Removed Windows carriage returns (formatting only) |
| drivers/python/age/init.py | Removed Windows carriage returns (formatting only) |
| drivers/python/age/VERSION.py | Removed Windows carriage returns (formatting only) |
| drivers/python/age/models.py | Removed Windows carriage returns (formatting only) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b635587 to
376744f
Compare
Note: This PR was created with AI tools and a human.
- Add parameterized query construction using psycopg.sql to prevent
SQL injection in all Cypher execution paths (age.py, networkx/lib.py)
- Replace all %-format and f-string SQL in networkx/lib.py with
sql.Identifier() for schema/table names and sql.Literal() for values
- Add validate_graph_name() with AGE-aligned VALID_GRAPH_NAME regex:
start with letter/underscore, allow dots and hyphens in middle positions,
end with letter/digit/underscore, min 3 chars, max 63 chars
- Add validate_identifier() with strict VALID_IDENTIFIER regex for labels,
column names, and SQL types (no dots or hyphens)
- Add validation calls to all networkx/lib.py entry points:
graph names validated on entry, labels validated before SQL construction
- Add _validate_column() to sanitize column specifications in buildCypher()
- Fix exception constructors (AgeNotSet, GraphNotFound, GraphAlreadyExists)
to always call super().__init__() with a meaningful default message so
that str(exception) never returns an empty string
- Add InvalidGraphName and InvalidIdentifier exception classes with
structured name/reason/context fields
- Fix builder.py: change erroneous 'return Exception(...)' to
'raise ValueError(...)' for unknown float expressions
- Fix copy-paste docstring in create_elabel() ('create_vlabels' -> 'create_elabels')
- Remove unused 'from psycopg.adapt import Loader' import in age.py
- Add design documentation in source explaining:
- VALID_GRAPH_NAME regex uses '*' (not '+') intentionally so that the
min-length check fires first with a clear error message
- buildCypher uses string concatenation (not sql.Identifier) because
column specs are pre-validated 'name type' pairs that don't map to
sql.Identifier(); graphName and cypherStmt are NOT embedded
- Update test_networkx.py GraphNotFound assertion to use assertIn()
instead of assertEqual() to match the improved exception messages
- Strip Windows carriage returns (^M) from 7 source files
- Fix requirements.txt: convert from UTF-16LE+BOM+CRLF to clean UTF-8+LF,
move --no-binary flag from requirements.txt to CI workflow pip command
- Upgrade actions/setup-python from v4 (deprecated) to v5 in CI workflow
- Add 46 security unit tests in test_security.py covering:
- Graph name validation (AGE naming rules, injection, edge cases)
- SQL identifier validation (labels, columns, types)
- Column spec sanitization
- buildCypher injection prevention
- Exception constructor correctness (str() never empty)
- Add test_security.py to CI pipeline (python-driver.yaml)
- pip-audit: 0 known vulnerabilities in all dependencies
modified: .github/workflows/python-driver.yaml
modified: drivers/python/age/VERSION.py
modified: drivers/python/age/__init__.py
modified: drivers/python/age/age.py
modified: drivers/python/age/builder.py
modified: drivers/python/age/exceptions.py
modified: drivers/python/age/models.py
modified: drivers/python/age/networkx/lib.py
modified: drivers/python/requirements.txt
modified: drivers/python/setup.py
modified: drivers/python/test_agtypes.py
modified: drivers/python/test_networkx.py
new file: drivers/python/test_security.py
376744f to
e379865
Compare
MuhammadTahaNaveed
approved these changes
Feb 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note: This PR was created with AI tools and a human.
modified: .github/workflows/python-driver.yaml
modified: drivers/python/age/VERSION.py
modified: drivers/python/age/init.py
modified: drivers/python/age/age.py
modified: drivers/python/age/builder.py
modified: drivers/python/age/exceptions.py
modified: drivers/python/age/models.py
modified: drivers/python/age/networkx/lib.py
modified: drivers/python/requirements.txt
modified: drivers/python/setup.py
modified: drivers/python/test_agtypes.py