Conversation
| sa.Column('gmt_updated', sa.DateTime(timezone=True), nullable=False, server_default=sa.text('NOW()')), | ||
| sa.Column('gmt_deleted', sa.DateTime(timezone=True), nullable=True), | ||
| sa.PrimaryKeyConstraint('id', name=op.f('pk_prompt_template')) | ||
| ) |
There was a problem hiding this comment.
Missing unique constraint creates race condition for duplicates
Medium Severity
The prompt_template table lacks a unique constraint on (prompt_type, scope, user_id, language). The create_or_update_prompt_template method uses a read-check-write pattern (query existing, then create if not found) which is susceptible to race conditions. If two concurrent requests try to create the same prompt configuration, both could pass the existence check and create duplicate records, leading to data integrity issues and unpredictable behavior when querying.
Additional Locations (1)
| TemplateSyntaxError: If template has syntax errors | ||
| """ | ||
| jinja_template = Template(template) | ||
| return jinja_template.render(**variables) |
There was a problem hiding this comment.
Template preview allows server-side template injection
High Severity
The preview_prompt method uses Jinja2's basic Template class to render user-provided templates without sandboxing. This allows authenticated users to execute arbitrary Python code on the server through Server-Side Template Injection (SSTI) payloads. Jinja2's SandboxedEnvironment from jinja2.sandbox should be used instead to restrict access to dangerous attributes and methods.
Additional Locations (1)
| except TemplateSyntaxError as e: | ||
| raise HTTPException(status_code=400, detail=f"Template syntax error: {str(e)}") | ||
| except Exception as e: | ||
| raise HTTPException(status_code=400, detail=f"Template rendering error: {str(e)}") |
There was a problem hiding this comment.
Preview endpoint vulnerable to server-side template injection
High Severity
The /prompts/preview endpoint accepts user-provided Jinja2 templates and renders them using an unsandboxed Template(). This enables Server-Side Template Injection (SSTI). An attacker can craft a malicious template like {{ ''.__class__.__mro__[2].__subclasses__() }} to access Python internals, potentially leading to arbitrary code execution. Jinja2's SandboxedEnvironment is needed to restrict access to dangerous attributes and methods.
Additional Locations (1)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| description = Column(Text, nullable=True) | ||
| gmt_created = Column(DateTime(timezone=True), default=utc_now, nullable=False) | ||
| gmt_updated = Column(DateTime(timezone=True), default=utc_now, nullable=False) | ||
| gmt_deleted = Column(DateTime(timezone=True), nullable=True, index=True) |
There was a problem hiding this comment.
Race condition allows duplicate prompt records without unique constraint
Medium Severity
The PromptTemplate model and migration lack a unique constraint on the logical key (prompt_type, scope, user_id, language) for non-deleted records. The create_or_update_prompt_template method uses a check-then-act pattern (SELECT then INSERT) which creates a race condition. Concurrent requests could both find no existing record and both insert, creating duplicates. Subsequent queries use .first() without ORDER BY, causing non-deterministic results where updates might affect only one duplicate while stale data gets returned.


Note
Medium Risk
Introduces new DB-backed prompt resolution used in the agent chat flow plus new public endpoints; incorrect resolution/validation could change agent behavior or break chats, and includes a schema migration.
Overview
Adds first-class prompt customization backed by a new
prompt_templatetable (model, repository mixin, Alembic migration) and aPromptTemplateServicethat resolves prompts by priority (bot config → user default → system default → hardcoded) and supports preview/validation.Exposes new REST endpoints under
/api/v1/prompts/*(user CRUD/reset, system defaults, preview, validate) and updates OpenAPI schemas/clients accordingly; also extends collection config withindex_promptsfor per-collection index prompt overrides.Integrates the resolver into
agent_chat_serviceso WebSocket chats use resolved system/query prompts, bumpsmcp-agentto0.2.6with corresponding logger setting changes, and includes small compatibility fixes (FastAPIQuery(..., pattern=...), relax OTel span recording check).Written by Cursor Bugbot for commit 637cc04. This will update automatically on new commits. Configure here.