Every CVE Search/ Get API key

CVE-2026-54757

Trestle has Server-Side Template Injection (SSTI) via Recursive Template Re-evaluation of Untrusted Data

7.8 HighFix available

Compliance-trestle (Trestle) is a Python SDK and command-line tool for managing OSCAL compliance documents. In versions before 3.12.4 and versions 4.0.0 through 4.0.3, Trestle is vulnerable to server-side template injection that can lead to remote code execution. This occurs because the MDCleanInclude and MDSectionInclude Jinja2 tags re-parse untrusted Markdown content as template source code using a non-sandboxed jinja2.Environment. An attacker who controls content that Trestle renders, such as a crafted workspace Markdown file, a third-party SSP document, or a YAML lookup-table value, can inject a Jinja2 expression that traverses Python object internals to execute arbitrary operating system commands in the context of the Trestle process. This issue is fixed in versions 3.12.4 and 4.1.0.

Attack profile

How easy it is to exploit

Attack vector
Local
Complexity
Low
Privileges needed
None
User interaction
Required

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.36%Up 0.1 points since Aug 26, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.8

Trestle has Server-Side Template Injection (SSTI) via Recursive Template Re-evaluation of Untrusted Data

Compliance-trestle (Trestle) is a Python SDK and command-line tool for managing OSCAL compliance documents. In versions before 3.12.4 and versions 4.0.0 through 4.0.3, Trestle is vulnerable to server-side template injection that can lead to remote code execution. This occurs because the MDCleanInclude and MDSectionInclude Jinja2 tags re-parse untrusted Markdown content as template source code using a non-sandboxed jinja2.Environment. An attacker who controls content that Trestle renders, such as a crafted workspace Markdown file, a third-party SSP document, or a YAML lookup-table value, can inject a Jinja2 expression that traverses Python object internals to execute arbitrary operating system commands in the context of the Trestle process. This issue is fixed in versions 3.12.4 and 4.1.0.

Record
CVE-2026-54757
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
EUVDEUVD-2026-66209 7.8

Compliance-trestle (Trestle) is a Python SDK and command-line tool for managing OSCAL compliance documents. In versions before 3.12.4 and versions 4.0.0 through 4.0.3, Trestle is vulnerable to server-side template injection that can lead to remote code execution. This occurs because the MDCleanInclude and MDSectionInclude Jinja2 tags re-parse untrusted Markdown content as template source code using a non-sandboxed jinja2.Environment. An attacker who controls content that Trestle renders, such as a crafted workspace Markdown file, a third-party SSP document, or a YAML lookup-table value, can inject a Jinja2 expression that traverses Python object internals to execute arbitrary operating system commands in the context of the Trestle process. This issue is fixed in versions 3.12.4 and 4.1.0.

Record
EUVD-2026-66209
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-jw39-3688-r4rx 7.8

Trestle has Server-Side Template Injection (SSTI) via Recursive Template Re-evaluation of Untrusted Data

Impact

A Server-Side Template Injection (SSTI) vulnerability exists in multiple locations of trestle's Jinja2 rendering pipeline due to a systemic pattern: untrusted data is re-parsed as Jinja2 template source code without sandboxing. This advisory tracks the root cause across all affected code paths.

The core anti-pattern is: treating runtime data (rendered output, included Markdown content, LUT values) as Jinja2 template source code and passing it to Parser.parse() or an equivalent rendering cycle, without using SandboxedEnvironment or escaping Jinja2 syntax delimiters. Because jinja2.Environment (not SandboxedEnvironment) is used, injected expressions can traverse Python object chains (__class__.__mro__, __globals__, __subclasses__()) to achieve arbitrary command execution via os.system() or subprocess.

Previously fixed instance (historical context):

An earlier version of render_template() in trestle/core/commands/author/jinja.py implemented a recursive while loop: rendered output was loaded via DictLoader into a new Environment and re-rendered until convergence. This allowed an attacker to inject {{ namespace.__init__.__globals__.os.system('command') }} into SSP data fields or LUT YAML values. When a trusted template rendered these data fields (e.g., Title: {{ ssp.metadata.title }}), the injected payload was written into the output, then re-evaluated as executable Jinja2 code in the next loop iteration. **This specific code path was fixed — render_template() now performs a single template.render(**lut) call.

Still-vulnerable code paths (this advisory):

  1. MDCleanInclude.parse() — trestle/core/jinja/tags.py:148-151: Markdown file content is loaded via FileSystemLoader.get_source(), then re-parsed as Jinja2 source via Parser(self.environment, content).parse().

  2. MDSectionInclude.parse() — trestle/core/jinja/tags.py:100-103: Extracted Markdown section text (md_section.content.raw_text) is re-parsed as Jinja2 source via Parser(self.environment, raw_text).parse().

  3. MDDatestamp.parse() — trestle/core/jinja/tags.py:198-201: Date string is re-parsed; lower risk because the date string is internally generated from strftime() rather than user input.

All three paths share the identical root cause: data that should be treated as plain text is passed to Parser.parse() and executed as Jinja2 code in an un-sandboxed Environment.

Attack vectors:

  • Path A (Markdown include): Attacker places a malicious .md file with embedded Jinja2 payload in the trestle workspace. When {% md_clean_include "malicious.md" %} or {% mdsection_include %} is processed, the payload executes.
  • Path B (Data field injection — SSP/LUT): Attacker crafts an SSP document or YAML LUT where a data field value (e.g., metadata.title) contains {{ namespace.__init__.__globals__.os.system('id') }}. When rendered into a trusted template, if the output subsequently flows through any re-parsing code path, the payload executes.

The same __globals__.os.system() RCE technique demonstrated in the previously-fixed render_template vulnerability applies to the remaining re-parsing paths.

Workarounds

  1. Disable vulnerable tags: Remove MDCleanInclude and MDSectionInclude from the Jinja2 extensions list in trestle/core/jinja/ext.py:32 if markdown includes are not required.
  2. Audit included Markdown files: Review all Markdown files referenced by {% md_clean_include %} and {% mdsection_include %} tags for unexpected Jinja2 syntax ({{ }}, {% %}, {# #}).
  3. Scan data sources: Scan SSP documents, YAML LUT files, and any other data sources rendered into templates for Jinja2 syntax patterns.
  4. Restrict workspace write access: Ensure only trusted users can add or modify files in trestle workspace directories.
  5. Pre-commit hook: Add a pre-commit hook to scan .md, .json, .yaml files for Jinja2 syntax…
Record
GHSA-jw39-3688-r4rx
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
NVD 7.8

Compliance-trestle (Trestle) is a Python SDK and command-line tool for managing OSCAL compliance documents. In versions before 3.12.4 and versions 4.0.0 through 4.0.3, Trestle is vulnerable to server-side template injection that can lead to remote code execution. This occurs because the MDCleanInclude and MDSectionInclude Jinja2 tags re-parse untrusted Markdown content as template source code using a non-sandboxed jinja2.Environment. An attacker who controls content that Trestle renders, such as a crafted workspace Markdown file, a third-party SSP document, or a YAML lookup-table value, can inject a Jinja2 expression that traverses Python object internals to execute arbitrary operating system commands in the context of the Trestle process. This issue is fixed in versions 3.12.4 and 4.1.0.

Record
CVE-2026-54757
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
OSV 7.8

Trestle has Server-Side Template Injection (SSTI) via Recursive Template Re-evaluation of Untrusted Data

Compliance-trestle (Trestle) is a Python SDK and command-line tool for managing OSCAL compliance documents. In versions before 3.12.4 and versions 4.0.0 through 4.0.3, Trestle is vulnerable to server-side template injection that can lead to remote code execution. This occurs because the MDCleanInclude and MDSectionInclude Jinja2 tags re-parse untrusted Markdown content as template source code using a non-sandboxed jinja2.Environment. An attacker who controls content that Trestle renders, such as a crafted workspace Markdown file, a third-party SSP document, or a YAML lookup-table value, can inject a Jinja2 expression that traverses Python object internals to execute arbitrary operating system commands in the context of the Trestle process. This issue is fixed in versions 3.12.4 and 4.1.0.

Record
CVE-2026-54757
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
OSVGHSA-jw39-3688-r4rx 7.8

Trestle has Server-Side Template Injection (SSTI) via Recursive Template Re-evaluation of Untrusted Data

Impact

A Server-Side Template Injection (SSTI) vulnerability exists in multiple locations of trestle's Jinja2 rendering pipeline due to a systemic pattern: untrusted data is re-parsed as Jinja2 template source code without sandboxing. This advisory tracks the root cause across all affected code paths.

The core anti-pattern is: treating runtime data (rendered output, included Markdown content, LUT values) as Jinja2 template source code and passing it to Parser.parse() or an equivalent rendering cycle, without using SandboxedEnvironment or escaping Jinja2 syntax delimiters. Because jinja2.Environment (not SandboxedEnvironment) is used, injected expressions can traverse Python object chains (__class__.__mro__, __globals__, __subclasses__()) to achieve arbitrary command execution via os.system() or subprocess.

Previously fixed instance (historical context):

An earlier version of render_template() in trestle/core/commands/author/jinja.py implemented a recursive while loop: rendered output was loaded via DictLoader into a new Environment and re-rendered until convergence. This allowed an attacker to inject {{ namespace.__init__.__globals__.os.system('command') }} into SSP data fields or LUT YAML values. When a trusted template rendered these data fields (e.g., Title: {{ ssp.metadata.title }}), the injected payload was written into the output, then re-evaluated as executable Jinja2 code in the next loop iteration. **This specific code path was fixed — render_template() now performs a single template.render(**lut) call.

Still-vulnerable code paths (this advisory):

  1. MDCleanInclude.parse() — trestle/core/jinja/tags.py:148-151: Markdown file content is loaded via FileSystemLoader.get_source(), then re-parsed as Jinja2 source via Parser(self.environment, content).parse().

  2. MDSectionInclude.parse() — trestle/core/jinja/tags.py:100-103: Extracted Markdown section text (md_section.content.raw_text) is re-parsed as Jinja2 source via Parser(self.environment, raw_text).parse().

  3. MDDatestamp.parse() — trestle/core/jinja/tags.py:198-201: Date string is re-parsed; lower risk because the date string is internally generated from strftime() rather than user input.

All three paths share the identical root cause: data that should be treated as plain text is passed to Parser.parse() and executed as Jinja2 code in an un-sandboxed Environment.

Attack vectors:

  • Path A (Markdown include): Attacker places a malicious .md file with embedded Jinja2 payload in the trestle workspace. When {% md_clean_include "malicious.md" %} or {% mdsection_include %} is processed, the payload executes.
  • Path B (Data field injection — SSP/LUT): Attacker crafts an SSP document or YAML LUT where a data field value (e.g., metadata.title) contains {{ namespace.__init__.__globals__.os.system('id') }}. When rendered into a trusted template, if the output subsequently flows through any re-parsing code path, the payload executes.

The same __globals__.os.system() RCE technique demonstrated in the previously-fixed render_template vulnerability applies to the remaining re-parsing paths.

Workarounds

  1. Disable vulnerable tags: Remove MDCleanInclude and MDSectionInclude from the Jinja2 extensions list in trestle/core/jinja/ext.py:32 if markdown includes are not required.
  2. Audit included Markdown files: Review all Markdown files referenced by {% md_clean_include %} and {% mdsection_include %} tags for unexpected Jinja2 syntax ({{ }}, {% %}, {# #}).
  3. Scan data sources: Scan SSP documents, YAML LUT files, and any other data sources rendered into templates for Jinja2 syntax patterns.
  4. Restrict workspace write access: Ensure only trusted users can add or modify files in trestle workspace directories.
  5. Pre-commit hook: Add a pre-commit hook to scan .md, .json, .yaml files for Jinja2 syntax…
Record
GHSA-jw39-3688-r4rx
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Weakness
CWE-94
Updated
2026-11-02
OSVPYSEC-2026-3817 7.8

Trestle has Server-Side Template Injection (SSTI) via Recursive Template Re-evaluation of Untrusted Data

Impact

A Server-Side Template Injection (SSTI) vulnerability exists in multiple locations of trestle's Jinja2 rendering pipeline due to a systemic pattern: untrusted data is re-parsed as Jinja2 template source code without sandboxing. This advisory tracks the root cause across all affected code paths.

The core anti-pattern is: treating runtime data (rendered output, included Markdown content, LUT values) as Jinja2 template source code and passing it to Parser.parse() or an equivalent rendering cycle, without using SandboxedEnvironment or escaping Jinja2 syntax delimiters. Because jinja2.Environment (not SandboxedEnvironment) is used, injected expressions can traverse Python object chains (__class__.__mro__, __globals__, __subclasses__()) to achieve arbitrary command execution via os.system() or subprocess.

Previously fixed instance (historical context):

An earlier version of render_template() in trestle/core/commands/author/jinja.py implemented a recursive while loop: rendered output was loaded via DictLoader into a new Environment and re-rendered until convergence. This allowed an attacker to inject {{ namespace.__init__.__globals__.os.system('command') }} into SSP data fields or LUT YAML values. When a trusted template rendered these data fields (e.g., Title: {{ ssp.metadata.title }}), the injected payload was written into the output, then re-evaluated as executable Jinja2 code in the next loop iteration. **This specific code path was fixed — render_template() now performs a single template.render(**lut) call.

Still-vulnerable code paths (this advisory):

  1. MDCleanInclude.parse() — trestle/core/jinja/tags.py:148-151: Markdown file content is loaded via FileSystemLoader.get_source(), then re-parsed as Jinja2 source via Parser(self.environment, content).parse().

  2. MDSectionInclude.parse() — trestle/core/jinja/tags.py:100-103: Extracted Markdown section text (md_section.content.raw_text) is re-parsed as Jinja2 source via Parser(self.environment, raw_text).parse().

  3. MDDatestamp.parse() — trestle/core/jinja/tags.py:198-201: Date string is re-parsed; lower risk because the date string is internally generated from strftime() rather than user input.

All three paths share the identical root cause: data that should be treated as plain text is passed to Parser.parse() and executed as Jinja2 code in an un-sandboxed Environment.

Attack vectors:

  • Path A (Markdown include): Attacker places a malicious .md file with embedded Jinja2 payload in the trestle workspace. When {% md_clean_include "malicious.md" %} or {% mdsection_include %} is processed, the payload executes.
  • Path B (Data field injection — SSP/LUT): Attacker crafts an SSP document or YAML LUT where a data field value (e.g., metadata.title) contains {{ namespace.__init__.__globals__.os.system('id') }}. When rendered into a trusted template, if the output subsequently flows through any re-parsing code path, the payload executes.

The same __globals__.os.system() RCE technique demonstrated in the previously-fixed render_template vulnerability applies to the remaining re-parsing paths.

Workarounds

  1. Disable vulnerable tags: Remove MDCleanInclude and MDSectionInclude from the Jinja2 extensions list in trestle/core/jinja/ext.py:32 if markdown includes are not required.
  2. Audit included Markdown files: Review all Markdown files referenced by {% md_clean_include %} and {% mdsection_include %} tags for unexpected Jinja2 syntax ({{ }}, {% %}, {# #}).
  3. Scan data sources: Scan SSP documents, YAML LUT files, and any other data sources rendered into templates for Jinja2 syntax patterns.
  4. Restrict workspace write access: Ensure only trusted users can add or modify files in trestle workspace directories.
  5. Pre-commit hook: Add a pre-commit hook to scan .md, .json, .yaml files for Jinja2 syntax…
Record
PYSEC-2026-3817
CVSS 3.1
7.8 HighCVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
compliance-trestle
PyPI
through 3.12.3
3.12.4
compliance-trestle
PyPI
4.0.0 up to 4.1.0
4.1.0
compliance-trestle
PyPI
before 3.12.4, plus listed versions
0.0.20.0.30.1.00.1.10.10.0
Show 45 moreShow less
0.11.00.12.00.13.00.13.10.14.00.14.10.14.20.14.30.14.40.15.00.15.10.16.00.17.00.18.00.18.10.19.00.2.00.2.10.2.20.20.00.21.00.22.00.22.10.23.00.24.00.25.00.25.10.26.00.27.00.27.10.27.20.28.00.28.10.29.00.3.00.30.00.31.00.32.00.32.10.33.00.34.00.35.00.36.00.37.00.4.0
3.12.4
compliance-trestle
PyPI
4.0.0 up to 4.1.0, plus listed versions
4.0.14.0.24.0.3
4.1.0
compliance-trestle
PyPI
before 3.12.4, 4.0.0 up to 4.1.0, plus listed versions
0.0.20.0.30.1.00.1.10.10.0
Show 45 moreShow less
0.11.00.12.00.13.00.13.10.14.00.14.10.14.20.14.30.14.40.15.00.15.10.16.00.17.00.18.00.18.10.19.00.2.00.2.10.2.20.20.00.21.00.22.00.22.10.23.00.24.00.25.00.25.10.26.00.27.00.27.10.27.20.28.00.28.10.29.00.3.00.30.00.31.00.32.00.32.10.33.00.34.00.35.00.36.00.37.00.4.0
3.12.44.1.0

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-54757 is a high vulnerability (CVSS 7.8) in Oscal-compass Compliance-trestle, published August 25, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.36%, the 30th percentile. Fixed in compliance-trestle 3.12.4.

References

Show 5 moreShow less
This page doesn't list everything

Left out here: 101 versions and the rest of 3 source descriptions. The JSON record has them.

MoveEnter Open