Skip to content

fix(safety): exclude PDO method calls from exec() false-positive detection - #28

Merged
M9nx merged 2 commits into
M9nx:mainfrom
elhussienysabry:fix/issue-19-pdo-exec-false-positive
Sep 7, 2026
Merged

M9nx merged 2 commits into
M9nx:mainfrom
elhussienysabry:fix/issue-19-pdo-exec-false-positive

Conversation

@elhussienysabry

Copy link
Copy Markdown
Contributor

Summary

Fixes #19

The PHP safety scanner was reporting false positives for legitimate PDO method calls like $pdo->exec() and PDO::exec(), flagging them as dynamic code execution findings.

Root Cause

The exec() danger pattern used a simple word-boundary regex:

(r"\bexec\s*\(", "exec() call — avoid dynamic code execution")

This matched any exec( — including PHP PDO method calls like $connection->exec($sql).

Fix

Added negative lookbehinds for -> and :: so only standalone function calls are flagged:

(r"(?<!->)(?<!::)\bexec\s*\(", "exec() call — avoid dynamic code execution")
Pattern Before After
exec('cmd') ⛔ flagged ⛔ flagged (correct)
exec(user_code) ⛔ flagged ⛔ flagged (correct)
$pdo->exec($sql) ❌ false positive ✅ allowed
$connection->exec($sql) ❌ false positive ✅ allowed
PDO::exec($stmt) ❌ false positive ✅ allowed

Files Changed

  • semantic_code_intelligence/llm/safety.py — 1-line regex fix
  • semantic_code_intelligence/tests/test_phase12.py — 6 regression tests

Resolves #19

The exec() danger pattern used a simple word-boundary regex that
matched any call whose name ended in 'exec', including PHP PDO
method calls such as $pdo->exec() and PDO::exec().

Apply negative look-behinds for '->' and '::' so that only standalone
function invocations (the global PHP exec() / Python exec()) are flagged.
Method-call forms are safe SQL-execution APIs and must not generate
false-positive safety warnings.

Changes:
- semantic_code_intelligence/llm/safety.py: update exec() pattern
- semantic_code_intelligence/tests/test_phase12.py: add 6 regression tests
@M9nx
M9nx self-requested a review September 7, 2026 10:27
@M9nx M9nx added the bug Something isn't working label Sep 7, 2026

@M9nx M9nx left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

Inline comment on semantic_code_intelligence/llm/safety.py line 26:

This lookbehind only excludes ->exec and ::exec when the operator is immediately adjacent to exec. PHP permits whitespace around these operators, so valid calls such as $pdo -> exec($sql) and SomeClass :: exec($sql) are still reported as dynamic code execution. Please make the matching token-aware or normalize whitespace around ->/:: before applying the rule, and add regression tests for both whitespace-separated forms.

The current tests cover the compact forms and pass, but they do not cover this valid PHP formatting case.

Comment thread semantic_code_intelligence/llm/safety.py
@elhussienysabry

Copy link
Copy Markdown
Contributor Author

@M9nx This PR fixes issue #19 — the PHP safety scanner was generating false positives for legitimate PDO method calls like $pdo->exec() and PDO::exec(), incorrectly flagging them as dynamic code execution.

Fix is minimal and safe:

  • 1-line regex change in semantic_code_intelligence/llm/safety.py
  • Added 6 regression tests confirming:
    • ✅ Global exec() is still correctly flagged
    • ✅ $pdo->exec(), $connection->exec(), PDO::exec() are no longer false positives

Ready for review and merge. 🙏

@M9nx

M9nx commented Sep 7, 2026

Copy link
Copy Markdown
Owner

@elhussienysabry Following up on your comment: the compact cases are fixed, but the current regex still flags valid PHP when whitespace surrounds the call operator.

POC against commit 85f7f3c:

from semantic_code_intelligence.llm.safety import SafetyValidator

validator = SafetyValidator()
for code in ["$pdo -> exec($sql)", "PDO :: exec($sql)"]:
    print(code, validator.is_safe(code))

Output:

$pdo -> exec($sql) False
PDO :: exec($sql) False

These are still false positives because the lookbehinds only match -> and :: when immediately adjacent to exec. Please add regression tests for the whitespace-separated forms and update the matcher. This is the same concern raised in the inline review conversation: #28 (comment)

Addresses M9nx review on PR #28.

The previous fix used fixed-width negative lookbehinds (?<!->) and
(?<!::) that only excluded exec() when the operator was immediately
adjacent. PHP permits whitespace around -> and :: so spaced forms
such as $pdo -> exec($sql) and SomeClass :: exec($sql) were still
being reported as dynamic code execution (false positives).

Fix: introduce _PHP_OPERATOR_WS pre-processing in SafetyValidator.validate()
that collapses any surrounding whitespace around -> and :: to their compact
forms before applying the pattern list. This makes the lookbehinds work
correctly for all valid PHP spacing styles.

Tests added for whitespace-separated forms:
- $pdo -> exec($sql)           (arrow with spaces)
- $connection -> exec($sql)    (arrow with spaces)
- PDO :: exec($stmt)            (double-colon with spaces)
- SomeClass :: exec($sql)       (double-colon with spaces)
- result = exec(user_input)      (bare exec still flagged)
@elhussienysabry

Copy link
Copy Markdown
Contributor Author

Thanks for the review @M9nx!

You're absolutely right — the fixed-width lookbehinds didn't handle whitespace around -> and ::.

Fix applied in the latest commit:

Instead of trying to extend the lookbehinds (which require fixed width in Python's re module), I added a pre-processing step in SafetyValidator.validate() that normalises whitespace around -> and :: before any pattern is applied:

_PHP_OPERATOR_WS = re.compile(r'\s*(->|::)\s*')

# In validate(), per line:
normalised = _PHP_OPERATOR_WS.sub(r'\1', line)

This collapses $pdo -> exec($sql) → $pdo->exec($sql) and SomeClass :: exec($sql) → SomeClass::exec($sql) so the existing lookbehinds work for all valid PHP spacing styles.

New regression tests added for spaced forms:

  • $pdo -> exec($sql) ✅ not flagged
  • $connection -> exec($sql) ✅ not flagged
  • PDO :: exec($stmt) ✅ not flagged
  • SomeClass :: exec($sql) ✅ not flagged
  • result = exec(user_input) ⛔ still flagged

All 9 test cases pass. Ready for re-review! 🙏

@M9nx
M9nx merged commit 2870ec5 into M9nx:main Sep 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] PHP safety scan flags PDO::exec() as dynamic code execution

2 participants