Skip to main content

compliance-trestle EUVDEUVD-2026-58357

| CVE-2026-45774 MEDIUM
Path Traversal (CWE-22)
2026-05-28 https://github.com/oscal-compass/compliance-trestle GHSA-mj4x-vf5c-5xg8 PYSEC-2026-2426
6.9
CVSS 4.0 · Vendor: https://github.com/oscal-compass/compliance-trestle
View

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain

  1. Access
    Craft malicious OSCAL profile YAML with traversal hrefs
  2. Delivery
    Deliver profile via public catalog or direct transfer
  3. Exploit
    Victim invokes trestle profile resolution
  4. Execution
    LocalFetcher resolves ../ path without boundary check
  5. Persist
    Arbitrary file read on server filesystem
  6. Impact
    Sensitive credentials or keys exfiltrated

Vulnerability Assessment

Weakness
CWE
OWASP Top 10:2025
A01:2025 - Broken Access Control
ASVS 5.0
V5 - File Handling Path canonicalization, traversal prevention
MITRE ATT&CK

2 techniques across 2 tactics: Discovery, Collection

The technique list with ATT&CK links and the kill-chain view is part of the Basic plan and up.

Exploitation Conditions

Exploitation requires that a victim's trestle installation process an attacker-controlled OSCAL profile YAML through the Import pipeline filter - specifically, the profile must reach trestle/core/resolver/_import.py:104 where href values are passed to FetcherFactory without sanitization. The malicious href can take three forms: a trestle:// URI with ../sequences (e.g., trestle://../../etc/passwd), a bare relative path with ../ sequences (e.g., ../../etc/passwd), or a back_matter rlinks entry pointing to a traversal path. No authentication to the trestle system is required by the attacker; the attacker must only deliver the malicious YAML to the victim, which can occur via a public compliance catalog, a shared repository, or direct file transfer. Exploitation is limited to files readable by the OS user running the trestle process - cloud credential files, SSH keys, and /etc/passwd are in scope; files outside that user's permissions are not accessible. Environments that process only internally-authored OSCAL profiles with no external imports are not at risk.

Impact

CVSS score and vector are not provided for this CVE, preventing precise metrics-based quantification. No EPSS score is available and no CISA KEV listing is confirmed. Real-world risk is elevated by the presence of publicly available PoC code and the sensitivity of potentially exposed data - cloud credentials (~/.aws/credentials), SSH private keys (~/.ssh/id_rsa), /etc/shadow, and /proc/self/environ are all demonstrated targets. The primary limiting factor is the precondition: a victim must actively import or resolve an attacker-controlled OSCAL profile, which constrains opportunistic mass exploitation. However, the supply chain attack vector - publishing a malicious profile to a public compliance catalog consumed by automated pipelines - is credible and requires no direct network access to the target. Attack complexity is low once the malicious profile reaches the victim. The combination of working PoC, no patch adoption friction for upgrade, and high-value credential exposure targets represents meaningful real-world risk for compliance automation environments, particularly in cloud-hosted CI/CD pipelines running trestle.

Exploit ScenarioDerived

A threat actor publishes a malicious OSCAL profile to a public compliance catalog containing imports[].href values of trestle://../../root/.aws/credentials and trestle://../../root/.ssh/id_rsa. When a compliance engineer or automated CI/CD pipeline runs trestle profile resolution against this profile, LocalFetcher resolves the traversal paths to the actual credential files and reads their contents - exfiltrating AWS access keys and SSH private keys with no authentication required beyond the process's existing filesystem permissions. Publicly available PoC code confirms this scenario executes successfully against compliance-trestle 4.0.2.

This Month Plan within 30 days. Why: MEDIUM severity (CVSS 4.0-6.9).
Patch available 0.1% exploitation probability (EPSS)

Get an e-mail when this CVE is exploited, patched or re-scored. Free account.

Alert me

AnalysisAIv1 – May 28, 2026

Arbitrary file read in IBM's compliance-trestle Python library allows any file accessible to the running process to be extracted by supplying a malicious OSCAL profile YAML with path traversal sequences in the imports[].href field. Three confirmed attack vectors exist: via the trestle:// URI scheme, via relative href paths, and via back_matter rlinks - all exploiting the same root cause in LocalFetcher. Publicly available exploit code (PoC) exists demonstrating extraction of /etc/passwd, cloud credential files, and SSH private keys; no CISA KEV listing is confirmed at time of analysis.

RemediationAI

Upgrade compliance-trestle to version 4.0.3 (for 4.x users) or version 3.12.2 (for 3.x users) per the vendor-released patches documented in commits 5c65c5926fe7ca908b9c1d281f904e7d97ba8310 and d00a0c2f702c24f7016009fbd626036f5c46f47b. The fix adds is_relative_to(trestle_root) boundary enforcement after pathlib.Path.resolve() in LocalFetcher for both the trestle:// URI handler and the relative path handler, raising TrestleError when the resolved path escapes the workspace; it also enforces the previously dead TRESTLE_HREF_REGEX at const.py:253. For teams unable to patch immediately, the most actionable compensating control is to restrict trestle profile resolution to internally-authored OSCAL files only - explicitly block automated ingestion of externally-sourced profiles by gating pipelines on source verification. Running the trestle process under a dedicated low-privilege service account without access to cloud credential files (~/.aws, ~/.kube, ~/.ssh) limits the blast radius if exploitation occurs, though it does not eliminate the vulnerability. Advisory: https://github.com/oscal-compass/compliance-trestle/security/advisories/GHSA-mj4x-vf5c-5xg8.

Affected VersionsENISA

compliance-trestle 4.0.0, < 4.0.3
compliance-trestle < 3.12.2

Affected Packages

pypi compliance-trestle fix: 3.12.2, 4.0.3

Source: OSV (Open Source Vulnerabilities)

Affects your stack

Affects 1 package in pypi

Checking this CVE against your own stacks and servers is part of the Basic plan and up.

Technical ContextAI · show details

compliance-trestle is an IBM/OSCAL Compass Python library for managing OSCAL (Open Security Controls Assessment Language) compliance documents. The vulnerability resides in trestle/core/remote/cache.py (LocalFetcher class, lines 175-179 for trestle:// URIs and line 194 for relative paths) and trestle/core/resolver/_import.py (line 104). When processing OSCAL profile imports[].href values, LocalFetcher concatenates the URI with trestle_root and calls Python's pathlib.Path.resolve(), which canonicalizes ../ sequences and can produce absolute paths outside the workspace such as /etc/passwd. No is_relative_to(trestle_root) boundary check is performed after resolution. A validation regex TRESTLE_HREF_REGEX was defined at const.py:253 but is never enforced anywhere in the codebase, constituting dead validation code - and even if enforced, the pattern '^trestle://[^/]' would pass traversal payloads since '.' matches [^/]. The root cause class is CWE-22 (Improper Limitation of a Pathname to a Restricted Directory). Affected packages are pkg:pip/compliance-trestle versions 4.0.0 through 4.0.2 and all 3.x versions prior to 3.12.2.

Know when Python gets its next vulnerability

  • Watch products and get an email when something new is published
  • Check this CVE against your own stack and servers
  • Exploit and PoC references, threat intelligence from 22 sources

No credit card · 7-day full trial

Severity by source

Vendor (https://github.com/oscal-compass/compliance-trestle) PRIMARY 6.9 MEDIUM
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:A/VC:H/VI:N/VA:N/SC:N/SI:N/SA:N
Red Hat 7.5 HIGH

Primary rating from Vendor (https://github.com/oscal-compass/compliance-trestle).

CVSS VectorVendor: https://github.com/oscal-compass/compliance-trestle

Attack Vector
Network
Attack Complexity
Low
Attack Requirements
None
Privileges Required
None
User Interaction
Active
Vulnerable system: Confidentiality
High
Vulnerable system: Integrity
None
Vulnerable system: Availability
None
Subsequent system: Confidentiality
None
Subsequent system: Integrity
None
Subsequent system: Availability
None

Lifecycle Timeline

1
CVSS changed
Aug 13, 2026 - 20:22 NVD
6.9 (MEDIUM)

DescriptionCVE.org

Summary

The compliance-trestle library's profile import mechanism resolves trestle:// URIs and relative file paths by joining them with trestle_root and calling .resolve(), but performs no boundary check to ensure the resolved path stays within the trestle workspace. An attacker can craft a malicious OSCAL profile YAML with imports[].href containing path traversal sequences to read arbitrary files from the server filesystem.

Three attack vectors confirmed:

  1. PT-001: trestle://../../etc/passwd - via trestle:// URI scheme
  2. PT-002: ../../etc/passwd - via relative path in href
  3. PT-003: back_matter rlinks with traversal paths

Preconditions: Victim must import/resolve an attacker-controlled OSCAL profile YAML.

Affected Component

Repository: https://github.com/IBM/compliance-trestle File: trestle/core/remote/cache.py (lines 175-179) File: trestle/core/resolver/_import.py (line 104) Version: v4.0.2 (latest as of 2026-04-30)

Vulnerable Code

cache.py:175-179 - LocalFetcher (trestle:// URI handling)

python
class LocalFetcher(FetcherBase):
    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:
        super().__init__(trestle_root, uri)
# ...
        elif uri.startswith(const.TRESTLE_HREF_HEADING):
            uri = str(trestle_root / uri[len(const.TRESTLE_HREF_HEADING) :])
            self._abs_path = pathlib.Path(uri).resolve()
# ❌ NO boundary check - .resolve() follows ../
# ❌ NO is_relative_to() validation
# ❌ Result can be /etc/passwd
            self._cached_object_path = self._abs_path
            return

cache.py:194 - LocalFetcher (relative path handling)

python
# For relative paths (no trestle:// or file:// prefix):
        try:
            self._abs_path = pathlib.Path(uri).resolve()
# ❌ Same issue - resolves relative to CWD with no boundary check
        except Exception:
            raise TrestleError(...)

_import.py:73-104 - Profile import href resolution

python
class Import(Pipeline.Filter):
    def __init__(self, ...):
# Line 73-83: back_matter rlinks used directly
        if self._import.href[0] == '#':
            resource = [r for r in self._resources if r.uuid == self._import.href[1:]][0]
            self._import.href = [
                rlink.href
# ❌ rlink.href from OSCAL data - user-controlled
                for rlink in resource.rlinks
                if rlink.href.endswith('.json') or rlink.href.endswith('.yaml')
            ][0]
# Line 104: href passed directly to FetcherFactory
        fetcher = cache.FetcherFactory.get_fetcher(self._trestle_root, self._import.href)

Root Cause:

  1. Path(trestle_root / "../../etc/passwd").resolve() = /etc/passwd
  2. No is_relative_to(trestle_root) check after resolve
  3. TRESTLE_HREF_REGEX defined at const.py:253 but NEVER enforced (dead code)
  4. Even if enforced, the regex '^trestle://[^/]' would PASS traversal payloads (. is [^/])

Steps to Reproduce

Prerequisites

bash
pip install compliance-trestle==4.0.2

PoC: Malicious OSCAL Profile

yaml
# malicious_profile.yaml
profile:
  uuid: "550e8400-e29b-41d4-a716-446655440000"
  metadata:
    title: "Malicious Profile"
    version: "1.0"
    last-modified: "2024-01-01T00:00:00+00:00"
    oscal-version: "1.0.4"
  imports:
    - href: "trestle://../../../../../../etc/passwd"

PoC: Direct LocalFetcher Exploit

python
#!/usr/bin/env python3
"""PoC: trestle:// path traversal via real LocalFetcher"""
from pathlib import Path
from trestle.core.remote.cache import LocalFetcher
import tempfile

trestle_root = Path(tempfile.mkdtemp())
# Normal usage - stays within workspace
normal = LocalFetcher(trestle_root, "trestle://catalogs/test/catalog.json")
print(f"Normal: {normal._abs_path}")
# /tmp/xxx/catalogs/test/catalog.json
# Exploit - escapes workspace
evil = LocalFetcher(trestle_root, "trestle://../../../../../../etc/passwd")
print(f"Evil:   {evil._abs_path}")
# /etc/passwd
print(f"Content: {evil._abs_path.read_text().split(chr(10))[0]}")
# Output: root:x:0:0:root:/root:/bin/bash

Expected: Path traversal blocked with error Actual: /etc/passwd, /etc/shadow, /proc/self/environ read successfully

Remediation

python
class LocalFetcher(FetcherBase):
    def __init__(self, trestle_root: pathlib.Path, uri: str) -> None:
        super().__init__(trestle_root, uri)
# ...
        elif uri.startswith(const.TRESTLE_HREF_HEADING):
            uri = str(trestle_root / uri[len(const.TRESTLE_HREF_HEADING) :])
            self._abs_path = pathlib.Path(uri).resolve()
# ✅ ADD: Boundary check
            if not self._abs_path.is_relative_to(self._trestle_root):
                raise TrestleError(
                    f"Path traversal blocked: resolved path '{self._abs_path}' "
                    f"is outside trestle root '{self._trestle_root}'"
                )

            self._cached_object_path = self._abs_path
            return

Same fix needed for relative path handling at line 194.

Additionally, enforce TRESTLE_HREF_REGEX (already defined at const.py:253 but never used).

Resources

  • CWE-22: https://cwe.mitre.org/data/definitions/22.html
  • OSCAL Profile Resolution: https://pages.nist.gov/OSCAL/concepts/processing/profile-resolution/
  • compliance-trestle: https://github.com/IBM/compliance-trestle

Impact

  1. Credential Theft via OSCAL Import:
yaml
   imports:
     - href: "trestle://../../root/.aws/credentials"
     - href: "trestle://../../root/.ssh/id_rsa"
  1. System Reconnaissance:
yaml
   imports:
     - href: "trestle://../../etc/passwd"
     - href: "trestle://../../proc/self/environ"
  1. Supply Chain Attack:

Attacker publishes malicious OSCAL profile to public compliance catalog. Organizations importing it leak server files during profile resolution.

  1. Dead Code Evidence:

TRESTLE_HREF_REGEX defined at const.py:253 but never enforced anywhere - proves path validation was INTENDED but never implemented.

Threat Intelligence Overview

EPSS Score
0.1%
Top 80% exploitable
Threat Intel
1
1 source
Social Media
1
Sightings
Data Quality
6 sources
Confidence: High

How this decision was reached

The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.

SignalValue
Severity MEDIUM
CISA KEV No
Public POC No
EPSS 0.1%
Patch available Yes
Active threat No
Deciding rule
MEDIUM severity (CVSS 4.0-6.9)
What every action level means
Emergency Immediate action required. Criteria: CRITICAL + in CISA KEV (actively exploited) without patch, OR CRITICAL + EPSS > 30% without patch, OR CRITICAL + active threat signals without patch.
Act Now Prioritize within 24-48h. Criteria: in KEV with patch available, OR CRITICAL + public POC, OR HIGH + EPSS > 10%, OR CRITICAL + active threat, OR any CRITICAL severity.
This Week Schedule remediation this week. Criteria: HIGH severity (CVSS 7.0-8.9). Patch within normal change window.
This Month Plan within 30 days. Criteria: MEDIUM severity (CVSS 4.0-6.9), lower exploitation probability. Include in regular patch cycle.
Monitor Track and reassess. Criteria: LOW severity (CVSS 0.1-3.9), minimal exploitation risk. No immediate action needed.

SSVC AssessmentENISA

SSVC Decision· derived
Scheduled
Exploitation· derived
None
System Exposure· derived
Open
Automatable· derived
No
Human Impact· derived
Medium

Priority Score

34
Low Medium High Critical
KEV: 0
EPSS: 0
CVSS: +34
PoC: 0
Weaponized: 0
Threat intel: 0
Gov advisory: 0

Attack Technique

Path traversal exploits occur when applications use user-controlled input to construct file system paths without proper validation.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Vendor StatusVendor

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy