← Back to issue list

Directory traversal issue when organizing a part

View original Github issue

Metadata

Project
craft-parts
Number
#1525
Type
issue
State
closed
Author
lengau
Labels
Status: Triaged Type: Bug
Created
Updated
Closed

Current evaluation

Fixed via PR #1562. Added validation to reject organize source paths escaping the part install directory, blocking directory traversal and absolute path misuse. Merged and closed.

Suggested action:

No scores available.

Issue body

### Bug Description When organizing a part, it's possible to organize from any directory, not just subdirectories of the install directory. ### To Reproduce Run `python -m craft_parts` on the parts.yaml file below. Note how the contents of `/etc/apt` get placed into the prime directory. It's also possible to use directory traversal strings to get a relative directory. ### part yaml ```shell parts: a: plugin: nil organize: /etc/apt: '' ``` ### Relevant log output ```shell DEBUG:craft_parts.packages:get repository attribute: attr=configure, repository:<class 'craft_parts.packages.deb.Ubuntu'> DEBUG:craft_parts.utils.os_utils:is_snap: False, SNAP_NAME set to None DEBUG:craft_parts.sequencer:process a:1 DEBUG:craft_parts.sequencer:add action a:1(0) DEBUG:craft_parts.sequencer:process a:2 DEBUG:craft_parts.sequencer:add action a:2(0) DEBUG:craft_parts.sequencer:process a:3 DEBUG:craft_parts.sequencer:add action a:3(0) DEBUG:craft_parts.sequencer:process a:4 DEBUG:craft_parts.sequencer:add action a:4(0) DEBUG:craft_parts.sequencer:process a:5 DEBUG:craft_parts.sequencer:add action a:5(0) INFO:craft_parts.executor.executor:Installing build-packages DEBUG:craft_parts.packages:get repository attribute: attr=install_packages, repository:<class 'craft_parts.packages.deb.Ubuntu'> DEBUG:craft_parts.executor.executor:verify plugin environment for part 'a' DEBUG:craft_parts.packages:set repository attribute: attr=stage_packages_filters, value=None, repo:<class 'craft_parts.packages.deb.Ubuntu'> Execute: Pull a DEBUG:craft_parts.executor.executor:execute action a:Action(part_name='a', step=Step.PULL, action_type=ActionType.RUN, reason=None, project_vars=ProjectVarInfo(root={}), properties=ActionProperties(changed_files=None, changed_dirs=None)) Execute: Overlay a DEBUG:craft_parts.executor.executor:execute action a:Action(part_name='a', step=Step.OVERLAY, action_type=ActionType.RUN, reason=None, project_vars=ProjectVarInfo(root={}), properties=ActionProperties(changed_files=None, changed_dirs=None)) Execute: Build a DEBUG:craft_parts.executor.executor:execute action a:Action(part_name='a', step=Step.BUILD, action_type=ActionType.RUN, reason=None, project_vars=ProjectVarInfo(root={}), properties=ActionProperties(changed_files=None, changed_dirs=None)) DEBUG:craft_parts.state_manager.states:load state file: /home/lengau/Work/Code/craft-parts/parts/a/state/pull DEBUG:craft_parts.packages:get repository attribute: attr=unpack_stage_packages, repository:<class 'craft_parts.packages.deb.Ubuntu'> DEBUG:craft_parts.executor.part_handler:remove directory /home/lengau/Work/Code/craft-parts/parts/a/build DEBUG:craft_parts.executor.step_handler:Executing PosixPath('/home/lengau/Work/Code/craft-parts/parts/a/run/build.sh') DEBUG:craft_parts.executor.part_handler:Run pre-organize callbacks DEBUG:craft_parts.packages:get repository attribute: attr=get_installed_packages, repository:<class 'craft_parts.packages.deb.Ubuntu'> DEBUG:urllib3.connectionpool:http://localhost:None "GET /v2/snaps HTTP/1.1" 200 None Execute: Stage a DEBUG:craft_parts.executor.executor:execute action a:Action(part_name='a', step=Step.STAGE, action_type=ActionType.RUN, reason=None, project_vars=ProjectVarInfo(root={}), properties=ActionProperties(changed_files=None, changed_dirs=None)) Execute: Prime a DEBUG:craft_parts.executor.executor:execute action a:Action(part_name='a', step=Step.PRIME, action_type=ActionType.RUN, reason=None, project_vars=ProjectVarInfo(root={}), properties=ActionProperties(changed_files=None, changed_dirs=None)) ```

Evaluation history

Date Model Scores Action Summary
qwen/qwen3.6-35b-a3b Fixed via PR #1562. Added validation to reject organize source paths escaping the part install directory, blocking directory traversal and absolute path misuse. Merged and closed.
qwen/qwen3.6-35b-a3b Fixed and merged via PR #1562. The update rejects organize source paths that escape the part install directory, including absolute paths and directory traversal strings. This resolves the bug by validating paths before processing.
qwen/qwen3.6-35b-a3b Fixed via PR #1562. The organize step now rejects source paths escaping the part install directory, preventing directory traversal and absolute path vulnerabilities. Merged as a bugfix.
qwen3.6-35b-a3b-mtp-q6
Staleness: 10
Complexity: 30
Confidence: 95
Support Request: 0
keep open Directory traversal bug in craft-parts allows organize paths to escape the install directory. Triaged. A pull request has been opened to validate and reject out-of-bounds paths, awaiting review.

Update history

No update history recorded yet.

Related issues

Issue Project State Summary Similarity
#689 fix(organize): use the part's install directories craft-parts merged Merged fix for organize_files() which incorrectly used relative paths, organizing files in cwd instead of base_dir. The function now accepts the part's install directories directly. Approved by two reviewers and passed CI.
74%
#1562 fix(organize): reject sources outside install dir craft-parts merged Merged fix preventing the organize step from processing sources outside the part install directory. Blocks absolute paths and directory traversal while preserving symlink behavior. Unrelated CI failures did not block the merge.
73%
#690 fix(organize): use the part's install directories (#689) craft-parts merged Merged fix for organize_files() using the current working directory instead of the project base directory. The function now accepts the part's install directories directly, eliminating relative path redefinition.
72%