The vulnerability is a denial-of-service (DoS) in ChatterBot caused by the exhaustion of the database connection pool. The root cause lies in the chatterbot.storage.sql_storage.SQLStorageAdapter class, which is responsible for all database interactions.
The SQLStorageAdapter.__init__ method improperly configured the SQLAlchemy session maker. It used sessionmaker directly, which is not thread-safe for managing sessions across concurrent requests. This meant that when multiple threads (e.g., from a web server) called the get_response method on the chatbot, they would receive sessions that were not isolated, leading to race conditions and improper session lifecycle management.
Furthermore, several methods within SQLStorageAdapter that perform database operations (such as filter, update, count, etc.) did not have robust error handling to ensure that database sessions were always closed and their connections returned to the pool. For example, if an exception occurred during a database query, the session.close() call would be skipped, causing a connection to leak.
Under concurrent load, as described in the proof-of-concept, these connection leaks accumulate rapidly, exhausting the SQLAlchemy connection pool. Once the pool is exhausted, all subsequent requests to the chatbot that require a database connection will hang and eventually time out, rendering the application unresponsive and effectively causing a denial of service.
The patch addresses these issues by:
- Introducing
scoped_session in the __init__ method to create a thread-local session registry. This ensures that each thread gets its own isolated database session.
- Wrapping database operations within
try...finally blocks in all methods that interact with the database. This guarantees that session.close() is called even if an exception occurs, preventing connection leaks.
- Adding connection pool configuration parameters to
create_engine to control the pool size and behavior, providing another layer of defense against exhaustion.