CVE-2026-57171
Trestle is vulnerable to arbitrary file write via path traversal in author generate commands (Incomplete fix of CVE-2026-46345)
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, the catalog-generate, profile-generate, and ssp-generate author commands write generated Markdown to an attacker-influenced output path without path-traversal validation, allowing arbitrary file write outside the Trestle workspace. These commands join the user-supplied output argument onto the Trestle root and write to the result, but guard it only with an is_directory_name_allowed() task-name-collision check rather than the PathSecurityValidator.validate_local_path() guard used by the jinja command, so an absolute path or one containing traversal sequences escapes the workspace and writes files under an attacker-chosen location as the invoking process owner. The security boundary is crossed when a trusted CI job, shared service, or wrapper derives the output argument from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting output to stay inside the workspace. When --force-overwrite is used, the selected output directory is first recursively deleted, extending the primitive to destruction of an attacker-chosen directory tree and enabling indirect code execution by overwriting files a pipeline later runs. 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
- None
What an attacker can affect
- Confidentiality
- None
- Integrity
- High
- Availability
- High
Exploit likelihood
What each source reports
CVE List Score used
7.7
Trestle is vulnerable to arbitrary file write via path traversal in author generate commands (Incomplete fix of CVE-2026-46345)
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, the catalog-generate, profile-generate, and ssp-generate author commands write generated Markdown to an attacker-influenced output path without path-traversal validation, allowing arbitrary file write outside the Trestle workspace. These commands join the user-supplied output argument onto the Trestle root and write to the result, but guard it only with an is_directory_name_allowed() task-name-collision check rather than the PathSecurityValidator.validate_local_path() guard used by the jinja command, so an absolute path or one containing traversal sequences escapes the workspace and writes files under an attacker-chosen location as the invoking process owner. The security boundary is crossed when a trusted CI job, shared service, or wrapper derives the output argument from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting output to stay inside the workspace. When --force-overwrite is used, the selected output directory is first recursively deleted, extending the primitive to destruction of an attacker-chosen directory tree and enabling indirect code execution by overwriting files a pipeline later runs. This issue is fixed in versions 3.12.4 and 4.1.0.
- Record
CVE-2026-57171- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H - Weakness
- CWE-22
- Updated
- 2026-11-02
EUVDEUVD-2026-66225
7.7
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, the catalog-generate, profile-generate, and ssp-generate author commands write generated Markdown to an attacker-influenced output path without path-traversal validation, allowing arbitrary file write outside the Trestle workspace. These commands join the user-supplied output argument onto the Trestle root and write to the result, but guard it only with an is_directory_name_allowed() task-name-collision check rather than the PathSecurityValidator.validate_local_path() guard used by the jinja command, so an absolute path or one containing traversal sequences escapes the workspace and writes files under an attacker-chosen location as the invoking process owner. The security boundary is crossed when a trusted CI job, shared service, or wrapper derives the output argument from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting output to stay inside the workspace. When --force-overwrite is used, the selected output directory is first recursively deleted, extending the primitive to destruction of an attacker-chosen directory tree and enabling indirect code execution by overwriting files a pipeline later runs. This issue is fixed in versions 3.12.4 and 4.1.0.
- Record
EUVD-2026-66225- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-r4vp-3vw6-r2x5
8.4
Trestle is vulnerable to arbitrary file write via path traversal in author generate commands (Incomplete fix of CVE-2026-46345)
At a glance
-
Actor: attacker who controls the -o/--output argument to trestle author {catalog,profile,ssp}-generate (e.g. via a CI pipeline that derives the output directory from repository-controlled data)
-
Primitive: attacker-controlled --output value reaches trestle_root / args.output write sink with only is_directory_name_allowed() (parts[0]-only task-name-collision check), not the PathSecurityValidator.validate_local_path() guard added by the CVE-2026-46345 fix
-
Impact: arbitrary-location file write outside the trestle workspace as the process owner (8.4 High; conservative C:N variant 7.7, still High); with --force-overwrite, the attacker-chosen directory is first recursively deleted shutil.rmtree)
-
Precondition: attacker influences the -o argument in a CI/automation pipeline or multi-tenant trestle workspace running these generate subcommands
-
Fix: call PathSecurityValidator.validate_local_path(markdown_path, trestle_root) immediately after building markdown_path in catalog.py, ssp.py, and prof.py, mirroring the existing jinja fix
Overview
The remediation for CVE-2026-46345 / GHSA-4q5v-7g7x-j79w ("Arbitrary File Write via Path Traversal in compliance-trestle – jinja") added a new PathSecurityValidator.validate_local_path() guard and wired it into the jinja command's output path. The identical output = trestle_root / args.output write pattern in the sibling author commands — catalog-generate, profile-generate, and ssp-generate — was not updated. Those commands instead rely on is_directory_name_allowed(), a task-name-collision check that does not stop path traversal: an absolute --output or a --output whose first component is innocuous subdir/../../../...) escapes the trestle workspace and writes generated markdown under an attacker-chosen output root outside the workspace, subject to the invoking process's filesystem permissions.
Impact
Threat model. This is not a claim that a local user harms themselves by intentionally choosing an unsafe -o. The security boundary is crossed when a trusted automation job, CI workflow, shared trestle service, or wrapper invokes one of these subcommands and derives --output from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting trestle to keep generated output inside the workspace. The attacker does not need local shell access to the trestle host; they only need influence over the data that the trusted automation maps into the --output argument.
Primary claim (confirmed): Such an invocation writes control-markdown files outside the trestle workspace — arbitrary-location file write as the process owner. This is runtime-confirmed for catalog-generate: catalog-generate -o /tmp/TRESTLE_ESCAPE_ABS produced files outside the workspace on a v4.0.3 install while the same install blocked the equivalent jinja -o with a Security violation error. profile-generate and ssp-generate are source-confirmed siblings (identical trestle_root / args.output join, the same is_directory_name_allowed-only gate, no validate_local_path call); see Runtime-confirmed scope in the End-to-end verification below.
Destructive variant --force-overwrite, source-confirmed): before generating, the force-overwrite path clears the selected output directory via clear_folder(...) trestle/core/commands/common/cmd_utils.py), which performs shutil.rmtree on that directory. Because clear_folder early-returns unless the target is an existing directory, the primitive is recursive deletion of an attacker-selected directory tree outside the workspace (e.g. wiping a directory the process owner can write), not pinpoint deletion of an arbitrary single file. This is the integrity + availability impact behind I:HA:H.
Secondary (conditional) escalation: The affected population extends to every consumer that runs these generate subcommands in a CI/automation pipeline, shared/multi-tenant trestle workspace, or wrapper that…
- Record
GHSA-r4vp-3vw6-r2x5- CVSS 3.1
- 8.4 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-22
- Updated
- 2026-11-02
NVD
7.7
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, the catalog-generate, profile-generate, and ssp-generate author commands write generated Markdown to an attacker-influenced output path without path-traversal validation, allowing arbitrary file write outside the Trestle workspace. These commands join the user-supplied output argument onto the Trestle root and write to the result, but guard it only with an is_directory_name_allowed() task-name-collision check rather than the PathSecurityValidator.validate_local_path() guard used by the jinja command, so an absolute path or one containing traversal sequences escapes the workspace and writes files under an attacker-chosen location as the invoking process owner. The security boundary is crossed when a trusted CI job, shared service, or wrapper derives the output argument from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting output to stay inside the workspace. When --force-overwrite is used, the selected output directory is first recursively deleted, extending the primitive to destruction of an attacker-chosen directory tree and enabling indirect code execution by overwriting files a pipeline later runs. This issue is fixed in versions 3.12.4 and 4.1.0.
- Record
CVE-2026-57171- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H - Weakness
- CWE-22
- Updated
- 2026-11-02
OSV
7.7
Trestle is vulnerable to arbitrary file write via path traversal in author generate commands (Incomplete fix of CVE-2026-46345)
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, the catalog-generate, profile-generate, and ssp-generate author commands write generated Markdown to an attacker-influenced output path without path-traversal validation, allowing arbitrary file write outside the Trestle workspace. These commands join the user-supplied output argument onto the Trestle root and write to the result, but guard it only with an is_directory_name_allowed() task-name-collision check rather than the PathSecurityValidator.validate_local_path() guard used by the jinja command, so an absolute path or one containing traversal sequences escapes the workspace and writes files under an attacker-chosen location as the invoking process owner. The security boundary is crossed when a trusted CI job, shared service, or wrapper derives the output argument from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting output to stay inside the workspace. When --force-overwrite is used, the selected output directory is first recursively deleted, extending the primitive to destruction of an attacker-chosen directory tree and enabling indirect code execution by overwriting files a pipeline later runs. This issue is fixed in versions 3.12.4 and 4.1.0.
- Record
CVE-2026-57171- CVSS 3.1
- 7.7 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVGHSA-r4vp-3vw6-r2x5
8.4
Trestle is vulnerable to arbitrary file write via path traversal in author generate commands (Incomplete fix of CVE-2026-46345)
At a glance
-
Actor: attacker who controls the -o/--output argument to trestle author {catalog,profile,ssp}-generate (e.g. via a CI pipeline that derives the output directory from repository-controlled data)
-
Primitive: attacker-controlled --output value reaches trestle_root / args.output write sink with only is_directory_name_allowed() (parts[0]-only task-name-collision check), not the PathSecurityValidator.validate_local_path() guard added by the CVE-2026-46345 fix
-
Impact: arbitrary-location file write outside the trestle workspace as the process owner (8.4 High; conservative C:N variant 7.7, still High); with --force-overwrite, the attacker-chosen directory is first recursively deleted shutil.rmtree)
-
Precondition: attacker influences the -o argument in a CI/automation pipeline or multi-tenant trestle workspace running these generate subcommands
-
Fix: call PathSecurityValidator.validate_local_path(markdown_path, trestle_root) immediately after building markdown_path in catalog.py, ssp.py, and prof.py, mirroring the existing jinja fix
Overview
The remediation for CVE-2026-46345 / GHSA-4q5v-7g7x-j79w ("Arbitrary File Write via Path Traversal in compliance-trestle – jinja") added a new PathSecurityValidator.validate_local_path() guard and wired it into the jinja command's output path. The identical output = trestle_root / args.output write pattern in the sibling author commands — catalog-generate, profile-generate, and ssp-generate — was not updated. Those commands instead rely on is_directory_name_allowed(), a task-name-collision check that does not stop path traversal: an absolute --output or a --output whose first component is innocuous subdir/../../../...) escapes the trestle workspace and writes generated markdown under an attacker-chosen output root outside the workspace, subject to the invoking process's filesystem permissions.
Impact
Threat model. This is not a claim that a local user harms themselves by intentionally choosing an unsafe -o. The security boundary is crossed when a trusted automation job, CI workflow, shared trestle service, or wrapper invokes one of these subcommands and derives --output from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting trestle to keep generated output inside the workspace. The attacker does not need local shell access to the trestle host; they only need influence over the data that the trusted automation maps into the --output argument.
Primary claim (confirmed): Such an invocation writes control-markdown files outside the trestle workspace — arbitrary-location file write as the process owner. This is runtime-confirmed for catalog-generate: catalog-generate -o /tmp/TRESTLE_ESCAPE_ABS produced files outside the workspace on a v4.0.3 install while the same install blocked the equivalent jinja -o with a Security violation error. profile-generate and ssp-generate are source-confirmed siblings (identical trestle_root / args.output join, the same is_directory_name_allowed-only gate, no validate_local_path call); see Runtime-confirmed scope in the End-to-end verification below.
Destructive variant --force-overwrite, source-confirmed): before generating, the force-overwrite path clears the selected output directory via clear_folder(...) trestle/core/commands/common/cmd_utils.py), which performs shutil.rmtree on that directory. Because clear_folder early-returns unless the target is an existing directory, the primitive is recursive deletion of an attacker-selected directory tree outside the workspace (e.g. wiping a directory the process owner can write), not pinpoint deletion of an arbitrary single file. This is the integrity + availability impact behind I:HA:H.
Secondary (conditional) escalation: The affected population extends to every consumer that runs these generate subcommands in a CI/automation pipeline, shared/multi-tenant trestle workspace, or wrapper that…
- Record
GHSA-r4vp-3vw6-r2x5- CVSS 3.1
- 8.4 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Weakness
- CWE-22
- Updated
- 2026-11-02
OSVPYSEC-2026-4030
8.4
Trestle is vulnerable to arbitrary file write via path traversal in author generate commands (Incomplete fix of CVE-2026-46345)
At a glance
-
Actor: attacker who controls the -o/--output argument to trestle author {catalog,profile,ssp}-generate (e.g. via a CI pipeline that derives the output directory from repository-controlled data)
-
Primitive: attacker-controlled --output value reaches trestle_root / args.output write sink with only is_directory_name_allowed() (parts[0]-only task-name-collision check), not the PathSecurityValidator.validate_local_path() guard added by the CVE-2026-46345 fix
-
Impact: arbitrary-location file write outside the trestle workspace as the process owner (8.4 High; conservative C:N variant 7.7, still High); with --force-overwrite, the attacker-chosen directory is first recursively deleted shutil.rmtree)
-
Precondition: attacker influences the -o argument in a CI/automation pipeline or multi-tenant trestle workspace running these generate subcommands
-
Fix: call PathSecurityValidator.validate_local_path(markdown_path, trestle_root) immediately after building markdown_path in catalog.py, ssp.py, and prof.py, mirroring the existing jinja fix
Overview
The remediation for CVE-2026-46345 / GHSA-4q5v-7g7x-j79w ("Arbitrary File Write via Path Traversal in compliance-trestle – jinja") added a new PathSecurityValidator.validate_local_path() guard and wired it into the jinja command's output path. The identical output = trestle_root / args.output write pattern in the sibling author commands — catalog-generate, profile-generate, and ssp-generate — was not updated. Those commands instead rely on is_directory_name_allowed(), a task-name-collision check that does not stop path traversal: an absolute --output or a --output whose first component is innocuous subdir/../../../...) escapes the trestle workspace and writes generated markdown under an attacker-chosen output root outside the workspace, subject to the invoking process's filesystem permissions.
Impact
Threat model. This is not a claim that a local user harms themselves by intentionally choosing an unsafe -o. The security boundary is crossed when a trusted automation job, CI workflow, shared trestle service, or wrapper invokes one of these subcommands and derives --output from repository-controlled, tenant-controlled, or otherwise untrusted data while expecting trestle to keep generated output inside the workspace. The attacker does not need local shell access to the trestle host; they only need influence over the data that the trusted automation maps into the --output argument.
Primary claim (confirmed): Such an invocation writes control-markdown files outside the trestle workspace — arbitrary-location file write as the process owner. This is runtime-confirmed for catalog-generate: catalog-generate -o /tmp/TRESTLE_ESCAPE_ABS produced files outside the workspace on a v4.0.3 install while the same install blocked the equivalent jinja -o with a Security violation error. profile-generate and ssp-generate are source-confirmed siblings (identical trestle_root / args.output join, the same is_directory_name_allowed-only gate, no validate_local_path call); see Runtime-confirmed scope in the End-to-end verification below.
Destructive variant --force-overwrite, source-confirmed): before generating, the force-overwrite path clears the selected output directory via clear_folder(...) trestle/core/commands/common/cmd_utils.py), which performs shutil.rmtree on that directory. Because clear_folder early-returns unless the target is an existing directory, the primitive is recursive deletion of an attacker-selected directory tree outside the workspace (e.g. wiping a directory the process owner can write), not pinpoint deletion of an arbitrary single file. This is the integrity + availability impact behind I:HA:H.
Secondary (conditional) escalation: The affected population extends to every consumer that runs these generate subcommands in a CI/automation pipeline, shared/multi-tenant trestle workspace, or wrapper that…
- Record
PYSEC-2026-4030- CVSS 3.1
- 8.4 High
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H - Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
compliance-trestlePyPI |
before 3.12.4 | 3.12.4 |
compliance-trestlePyPI |
4.0.0 up to 4.1.0 | 4.1.0 |
compliance-trestlePyPI |
before 3.12.4, plus listed versions 0.0.20.0.30.1.00.1.10.10.0 Show 45 moreShow less0.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-trestlePyPI |
4.0.0 up to 4.1.0, plus listed versions 4.0.14.0.24.0.3 |
4.1.0 |
compliance-trestlePyPI |
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 less0.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
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-57171 is a high vulnerability (CVSS 7.7) 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.22%, the 12th percentile. Fixed in compliance-trestle 3.12.4.
References
github.com/oscal-compass/compliance-trestle/security/advisories/GHSA-r4vp-3vw6-r2x5
github.com/oscal-compass/compliance-trestle/security/advisories/GHSA-4q5v-7g7x-j79w
github.com/oscal-compass/compliance-trestle/commit/37ed44f5f2e074202c8eb7c2f203c05d19461cdc
github.com/oscal-compass/compliance-trestle/releases/tag/v4.1.0
nvd.nist.gov/vuln/detail/CVE-2026-57171
github.com/oscal-compass/compliance-trestle/pull/2270
Show 6 moreShow less
github.com/oscal-compass/compliance-trestle/commit/5335ff873a2a68eb7de43df029bea09cadff22fd
github.com/oscal-compass/compliance-trestle/releases/tag/v3.12.4
github.com/advisories/GHSA-r4vp-3vw6-r2x5
github.com/CVEProject/cvelistV5/tree/main/cves/2026/57xxx/CVE-2026-57171.json
github.com/oscal-compass/compliance-trestle
pypi.org/project/compliance-trestle
Left out here: 101 versions and the rest of 3 source descriptions. The JSON record has them.