Revision message is rendered unescaped into the migration docstring; triple quotes and backslashes break the generated script
@ApparentlyTejas ya está trabajando en esto.
Desde el 23/10/2026.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 70/100
Línea de trabajo
Empieza en alembic/script/base.py alrededor de la línea 743, donde generate_revision() pasa message a las plantillas script.py.mako, y revisa la línea 1 de esas plantillas para ver el docstring. Reproduce el problema con alembic revision -m usando un mensaje que contenga comillas triples o barras invertidas. Está terminado cuando el mensaje se escapa antes de renderizarse y las pruebas de ida y vuelta de RevisionCommandTest para script.doc y script.longdoc pasan junto con las pruebas existentes.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Description
ScriptDirectory.generate_revision() passes the message argument directly into script.py.mako, where all built-in revision templates render it inside a triple-quoted docstring (line 1). This affects the generic, async, multidb, pyproject, and pyproject_async templates (alembic/script/base.py:743).
Because the message is not escaped before rendering, two issues arise:
- Docstring termination: A message containing
"""prematurely closes the docstring, allowing the remainder of the message to be emitted as module-level Python code. When the generated revision is subsequently imported, this code executes. - Backslash interpretation: Backslashes are interpreted as Python escape sequences. For example,
\nbecomes a newline, invalid escape sequences such as\pcan triggerSyntaxWarningon Python 3.12+, and a trailing backslash can escape the newline following the message. Consequently,script.docmay not preserve the original message.
This was initially reported to Tidelift. The maintainers confirmed the behaviour but classified it as a developer-tool input issue rather than a security-boundary vulnerability, suggesting it be reported publicly as a defense-in-depth bug. I agree with that assessment.
Steps to Reproduce
-
Initialise an Alembic environment:
alembic init migrations -
Create a revision with a message that terminates the docstring:
alembic revision -m 'add users""" print("this line is not part of the docstring") __doc__ = """' -
Run:
alembic history
The generated revision is imported, and the injected print() statement executes.
The same behaviour can be triggered through command.revision(cfg, message=...).
Backslash handling can be reproduced with:
alembic revision -m 'C:\path\new'
The generated file may emit a SyntaxWarning for invalid escape sequences on import, and the revision's script.doc value does not round-trip to the original message.
Expected Behaviour
The generated revision should preserve the original message in script.doc and script.longdoc, without allowing the message to terminate the docstring or introduce executable Python code.
Affected Versions and Environment
- Alembic: 1.20.1 (main at
1bc21b8) - Python: 3.12.13
Proposed Fix
Escape the message in generate_revision() before passing it to the template. This centralises the handling and covers both built-in templates and custom script.py.mako templates copied into user projects.
For example:
def _escape_docstring_message(message: str) -> str:
return message.replace("\\", "\\\\").replace('"""', '\\"\\"\\"')
Apply this helper at alembic/script/base.py:743, before rendering the template.
I verified this approach locally. Two new tests in RevisionCommandTest, covering triple quotes and backslash round-tripping through script.doc and script.longdoc, pass alongside the existing 11 tests in that class.
- Lenguaje dominante
- Python
- Estrellas
- 4.5k
- Forks
- 391
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de sqlalchemy/alembic
-
on_version_apply is typed as a positional callable, but alembic calls it with keyword argumentsQuizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
sqlalchemy/alembic#1883 · 1 comentario ·
-
bug pep 484
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
sqlalchemy/alembic#1341 · 2 comentarios ·
-
autogenerate - detection bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
sqlalchemy/alembic#1121 · 3 comentarios ·
-
Identity and Computed comparison skipped when compare_server_default is not set, as of 1.18.0Quizá libre de nuevo Un pull request para esta issue se cerró sin fusionarse. Abiertoautogenerate - defaults bug regression
Dificultad 3/5 1-2 días Aptitud para principiantes 50/100
sqlalchemy/alembic#1877 · 1 comentario ·
-
Entry point for DefaultImpl subclasses? (or, just use plugins?)Posiblemente ocupada @dwreeves la tomó hace 40 días. Abiertocode review in progress migration environment use case
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
sqlalchemy/alembic#1874 · 1 comentario ·
Todos los issues de sqlalchemy/alembic
Issues similares
-
SslLibrary crashes with unhandled OSError: port/proto not found on non-standard SSL portsPosiblemente ocupada @himanchalkaushale la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
OWASP/Nettacker#1884 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
A-connection-core C-enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
aws-samples/sample-per-model-bedrock#869 ·
Los mantenedores suelen responder en 1 día
-
Spec: say that included_antigen_sources gates LENS labels; do not merge it into antigen kindsAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
fzn0x/watchtower#17 ·