Skip to content

[Code scan] Avoid mutating the global sitemap while rendering the banner #86

Description

@njzjz

This issue is a result of a Codex global code scan of deepmodeling/deepmodeling_sphinx at commit 156679f.

Problem

render_banner() writes the active CSS class directly into the module-level sitemap. The mutation persists across subsequent calls, so rendering one site as active and then rendering another can leave multiple navigation items marked active.

Code references:

sitemap = [
{"title": "Home", "url": "https://deepmodeling.com"},
{"title": "Blog", "url": "https://blogs.deepmodeling.com"},
{"title": "Tutorials", "url": "https://tutorials.deepmodeling.com"},
{
"title": "Docs",
"url": "https://docs.deepmodeling.com/",
"subitem": [
{
"title": "DeePMD-kit",
"url": "https://docs.deepmodeling.com/projects/deepmd/",
},
{"title": "DP-GEN", "url": "https://docs.deepmodeling.com/projects/dpgen/"},
{
"title": "dpdata",
"url": "https://docs.deepmodeling.com/projects/dpdata/",
},
{
"title": "DPDispatcher",
"url": "https://docs.deepmodeling.com/projects/dpdispatcher/",
},
{"title": "ABACUS", "url": "https://abacus.deepmodeling.com/"},
{"title": "DeepFlame", "url": "https://deepflame.deepmodeling.com/"},
{"title": "DPTI", "url": "https://docs.deepmodeling.com/projects/dpti/"},
],
},
{"title": "Publications", "url": "https://blogs.deepmodeling.com/papers/"},
{"title": "GitHub", "url": "https://github.com/deepmodeling"},
]
active_class = "active docs-active"
icp_no = "京ICP备20010051号-8"

def render_banner(current_site="Docs") -> str:
"""Use jinja2 to render banner.
Returns
-------
str
HTML content of banner.
"""
source = os.path.join(
os.path.abspath(os.path.dirname(__file__)),
"banner.html",
)
with open(source) as f:
template = Template(f.read())
for item in sitemap:
if item["title"] == current_site:
item["class"] = active_class
return template.render(
items=sitemap,
)

Reproduction

from deepmodeling_sphinx.inject import render_banner
from deepmodeling_sphinx.config import sitemap

render_banner("Docs")
render_banner("Blog")
print([(item["title"], item.get("class")) for item in sitemap if item.get("class")])

The output includes both Docs and Blog with active docs-active.

Impact

Repeated in-process builds, tests, or custom integrations that render the banner with different deepmodeling_current_site values can leak active state between renders.

Suggested fix

Build a per-render copy of the sitemap and assign active state on that copy, or compute the class in the Jinja template without mutating shared module state.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Todo

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions