Skip to content

plugin loader: SandboxedEnvironment(autoescape=True) silently corrupts non-HTML config values #4605

@gandhipratik203

Description

@gandhipratik203

Summary

mcpgateway/plugins/framework/loader/config.py:80 builds the Jinja env for rendering plugins/config.yaml with autoescape=True:

jinja_env = SandboxedEnvironment(loader=jinja2.BaseLoader(), autoescape=True)
rendered_template = jinja_env.from_string(template).render(env=os.environ)

autoescape=True HTML-encodes &, <, >, " in the rendered output. That's correct for HTML templates and wrong for YAML — any Jinja-rendered value (e.g. {{ env.REDIS_URL }} or any other env var passed through this path) containing those characters is silently corrupted before yaml.safe_load consumes it.

Concrete failure cases

  • REDIS_URL=redis://user:p&w@host:6379/0 (password containing &) renders as redis://user:p&amp;w@host:6379/0 → broken URL.
  • Any env-sourced TLS cert content, API key, or token containing <, >, ", or & → silently corrupted.
  • The corruption is silent: YAML parses successfully, plugin init fails downstream with a confusing error that doesn't point back at the encoding step.

Affects every Jinja-templated value in plugins/config.yaml, not just redis_url. Surfaced during review of #4582.

Proposed fix

jinja_env = SandboxedEnvironment(loader=jinja2.BaseLoader(), autoescape=False)

autoescape=False is the right default for non-HTML output; YAML's own escaping handles structural characters at the yaml.safe_load layer.

Acceptance criteria

  • SandboxedEnvironment constructed with autoescape=False
  • Regression test that asserts a env var containing &, <, >, " round-trips through Jinja substitution unchanged

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions