Revision message is rendered unescaped into the migration docstring; triple quotes and backslashes break the generated script

未关闭 适合新手
#1,879 3 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

@ApparentlyTejas 已经在做这个了。

开始于 2026年10月23日。

  • #1880 来自 @Eryx-Z —— 已关闭,未合并
  • #1881 来自 @Eryx-Z —— 已关闭,未合并

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
70/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
python, sql
领域
tooling

调研方向

从 alembic/script/base.py 的第 743 行左右开始,generate_revision() 在这里把 message 传给 script.py.mako 模板,然后查看这些模板的第 1 行,以看到 docstring。使用包含三引号或反斜杠的消息,通过 alembic revision -m 复现问题。完成的标准是:消息在渲染前被转义,并且 RevisionCommandTest 针对 script.doc 和 script.longdoc 的往返测试与现有测试一起通过。

由索引模型根据 Issue 内容生成。

描述

bug command interface

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:

  1. 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.
  2. Backslash interpretation: Backslashes are interpreted as Python escape sequences. For example, \n becomes a newline, invalid escape sequences such as \p can trigger SyntaxWarning on Python 3.12+, and a trailing backslash can escape the newline following the message. Consequently, script.doc may 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

  1. Initialise an Alembic environment:

    alembic init migrations
    
  2. 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__ = """'
    
  3. 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.

主要语言
Python
星标
4.5k
派生
391
PR 合并指标
30 天内没有已合并 PR

环境准备

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

sqlalchemy/alembic 的其他 Issue

查看 sqlalchemy/alembic 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。