Skip to content

contrib/mysql: add classic protocol support#4967

Draft
pablogonzalezpe wants to merge 2 commits intosecdev:masterfrom
pablogonzalezpe:contrib-mysql
Draft

contrib/mysql: add classic protocol support#4967
pablogonzalezpe wants to merge 2 commits intosecdev:masterfrom
pablogonzalezpe:contrib-mysql

Conversation

@pablogonzalezpe
Copy link
Copy Markdown

Summary

This PR adds a new scapy.contrib.mysql module implementing support for the MySQL classic protocol over TCP.

The current scope covers a first usable subset of the protocol for dissection and packet building, including:

  • packet framing (payload_length + sequence_id)
  • Protocol::HandshakeV10
  • Protocol::SSLRequest
  • Protocol::HandshakeResponse41
  • OldAuthSwitchRequest
  • AuthSwitchRequest
  • AuthSwitchResponse
  • AuthMoreData
  • OK_Packet
  • ERR_Packet
  • EOF_Packet
  • COM_QUERY
  • COM_STMT_PREPARE_OK
  • text resultsets:
    • column count
    • column definitions
    • text rows
    • EOF / OK terminators
  • prepared statement metadata flows
  • some legacy field-list style flows seen in real captures

Regression tests are added in test/contrib/mysql.uts.

Scope

This PR is intentionally limited to a usable MVP for the classic protocol.

Not implemented in this first version:

  • TLS-encrypted MySQL payloads after SSLRequest
  • compression
  • binary resultsets
  • full command coverage
  • full authentication plugin coverage
  • full prepared statement execution support

Validation

UTScapy

Added regression tests for:

  • handshake packets
  • auth switch and auth more data packets
  • OK / ERR / EOF packets
  • COM_QUERY
  • text resultsets
  • resultsets with multiple columns and NULL
  • resultsets terminated with OK when CLIENT_DEPRECATE_EOF applies
  • COM_STMT_PREPARE_OK metadata flows
  • legacy field-list style flows
  • multi-packet streams

Result:

  • UTScapy: 15/15 passing

Lint / typing

Validated locally with:

  • tox -e flake8 on Windows: OK
  • tox -e flake8 on WSL Ubuntu / Python 3.9: OK
  • tox -e mypy on Windows: OK

On WSL Ubuntu / Python 3.9, tox -e mypy reports existing repository-level typing issues outside this module.

Real PCAP validation

The contrib was also tested against these public MySQL captures:

  1. umitproject/packet-manipulator/audits/pcap-tests/mysql.pcap
  2. colinnewell/pcap2mysql-log/test/captures/big-data.pcap
  3. arkime/tests/pcap/mysql-allow.pcap

In local validation, the MySQL messages in these 3 captures were successfully parsed with the current implementation.

Notes

This PR follows the earlier discussion in #4954.

I tried to keep names close to the MySQL protocol naming where possible, while avoiding collisions with Scapy internals when needed.

Feedback is welcome on:

  • whether this is the right MVP boundary for scapy.contrib
  • whether any naming should be adjusted further
  • whether prepared statement metadata support should stay in this PR or be split out

Comment thread scapy/contrib/mysql.py
return repr(val)


class MySQLCapabilityFlagsField(LEIntField):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this "redefinition" of a FlagsField really necessary?

Comment thread scapy/contrib/mysql.py
return _flag_repr(int(val), MYSQL_COLUMN_FLAGS)


class MySQLLenEncStrField(Field[Any, Any]):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Whats the purpose of this field?

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

❌ Patch coverage is 81.45833% with 89 lines in your changes missing coverage. Please review.
✅ Project coverage is 80.33%. Comparing base (66ef96a) to head (43288ea).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
scapy/contrib/mysql.py 81.45% 89 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4967      +/-   ##
==========================================
+ Coverage   80.31%   80.33%   +0.01%     
==========================================
  Files         381      382       +1     
  Lines       93630    94110     +480     
==========================================
+ Hits        75202    75600     +398     
- Misses      18428    18510      +82     
Files with missing lines Coverage Δ
scapy/contrib/mysql.py 81.45% <81.45%> (ø)

... and 9 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread scapy/contrib/mysql.py
"""
Authentication response encoding depends on client capabilities.

- CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: string<lenenc>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It's not the scapy way to introduce a new Field for such a handling. More correct would be to use "ConditionalFields" or MultipleTypeFields

Comment thread scapy/contrib/mysql.py
return repr(val)


class MySQLTextRowValuesField(Field[Any, Any]):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this Field really necessary?

@polybassa
Copy link
Copy Markdown
Contributor

Please try to increase the test coverage, since this looks like AI-generated code.

@pablogonzalezpe
Copy link
Copy Markdown
Author

Thanks, that is fair feedback.

I will add more tests to exercise the currently uncovered branches in \scapy.contrib.mysql. The current version already includes UTScapy regression tests and validation against real MySQL pcaps, but I agree that the patch coverage can be improved further.

@pablogonzalezpe
Copy link
Copy Markdown
Author

I added more UTScapy tests to exercise uncovered branches, including auth-response variants, helper edge cases, fallback/error paths, and incomplete stream reassembly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants