Skip to content

ECOPROJECT-4719 | fix: Prevent symlink-based path traversal in VDDK tarball extraction#256

Merged
AvielSegev merged 1 commit into
kubev2v:mainfrom
AvielSegev:fix/ECOPROJECT-4719-vddk-symlink-path-traversal
Jun 7, 2026
Merged

ECOPROJECT-4719 | fix: Prevent symlink-based path traversal in VDDK tarball extraction#256
AvielSegev merged 1 commit into
kubev2v:mainfrom
AvielSegev:fix/ECOPROJECT-4719-vddk-symlink-path-traversal

Conversation

@AvielSegev

@AvielSegev AvielSegev commented Jun 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes critical path traversal vulnerability in VDDK tarball extraction (CVE-level security issue)
  • Blocks chained symlink attacks that could write arbitrary files outside extraction directory
  • Preserves support for legitimate VDDK .so version symlinks

Security Impact

Severity: High - Unauthenticated LAN-adjacent arbitrary file write as UID 1001

Vulnerability Details

The PUT /inspector/vddk endpoint extracts gzip'd tarballs using extractTarGz(). The existing path traversal protection used lexical checks (filepath.Clean + HasPrefix) that don't resolve symlinks already on disk.

Attack scenario:

  1. Attacker crafts tarball with symlink: a/x → .. (passes lexical validation)
  2. Then writes: a/x/evil.sh which follows the live symlink
  3. File actually lands at: dest/../evil.sh (outside destDir)

Real impact:

  • Write to /var/lib/agent/config.json (config manipulation)
  • Write to /app/.cache/malicious.py (persistent code execution)
  • Agent runs with vCenter admin credentials → full infrastructure compromise

Fix Implementation

Before creating files/directories, resolve parent directory symlinks with filepath.EvalSymlinks and verify the resolved path is still inside destDir. This prevents the attack while maintaining support for legitimate VDDK internal symlinks (e.g., libvixDiskLib.so → libvixDiskLib.so.8.0.3).

Summary by CodeRabbit

  • Bug Fixes

    • Improved archive extraction validation to detect and reject symlink-based path-escape and path-traversal attempts (including absolute and relative targets, and traversals using ../), preventing files from being written outside the intended extraction root while still permitting legitimate internal symlinks that resolve within the extraction root.
  • Tests

    • Added comprehensive tests validating chained symlink escapes, absolute/relative traversal cases, ../ usage, and acceptance of valid internal symlinks.

@AvielSegev AvielSegev requested a review from a team as a code owner June 1, 2026 09:29
@AvielSegev AvielSegev requested review from ronenav and tupyy and removed request for a team June 1, 2026 09:29
@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 240dec9d-8672-4bae-898b-657e2fd835fd

📥 Commits

Reviewing files that changed from the base of the PR and between ef99c9b and 08de5b2.

📒 Files selected for processing (2)
  • internal/services/vddk.go
  • internal/services/vddk_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • internal/services/vddk.go
  • internal/services/vddk_test.go

📝 Walkthrough

Walkthrough

This PR hardens tar.gz extraction security by adding symlink-escape detection to extractTarGz. Before creating tar entries, the function resolves symlinks in parent directories and rejects extraction if the resolved parent would escape the destination directory. Tests validate rejection of multiple traversal patterns and acceptance of legitimate internal symlinks.

Changes

Symlink Escape Detection

Layer / File(s) Summary
Symlink escape detection in tar extraction
internal/services/vddk.go
extractTarGz resolves symlinks in entry parent directories and returns explicit symlink escape detected errors when resolution would place the parent outside destDir, blocking creation before the existing switch handling.
Path traversal prevention test coverage
internal/services/vddk_test.go
A new Security: Path Traversal Prevention block adds five test cases verifying Upload rejects chained symlinks, absolute targets, relative escapes, and ../../ traversal, and accepts legitimate internal VDDK symlinks while checking created link targets.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • tupyy
  • ronenav
  • nirarg

Poem

🐰 I hop through tarball threads with care,
I sniff each symlink, check each lair.
No secret path will let me stray,
Extraction stays the honest way.
Cheer the code — keep dangers bare.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main security fix: preventing symlink-based path traversal in VDDK tarball extraction, which aligns perfectly with the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@AvielSegev AvielSegev force-pushed the fix/ECOPROJECT-4719-vddk-symlink-path-traversal branch 3 times, most recently from f54d7dc to ef99c9b Compare June 3, 2026 09:29
@ronenav

ronenav commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

/approve

…arball extraction

Resolves CVE vulnerability where chained symlinks could write files outside
the extraction directory. An attacker could craft a tarball with:
1. a/x → .. (symlink passes lexical validation)
2. a/x/evil.sh (follows symlink, writes to ../evil.sh outside destDir)

This enables arbitrary file write as UID 1001, allowing:
- Config file overwrites in /var/lib/agent/
- Persistent code execution via /app/.cache
- Exfiltration of vCenter admin credentials

Fix: Before creating files/directories, resolve parent path symlinks with
filepath.EvalSymlinks and verify the resolved path remains inside destDir.
Legitimate VDDK .so version symlinks are still supported.

Signed-off-by: Aviel Segev <asegev@redhat.com>
@AvielSegev AvielSegev force-pushed the fix/ECOPROJECT-4719-vddk-symlink-path-traversal branch from ef99c9b to 08de5b2 Compare June 4, 2026 06:58
Comment thread internal/services/vddk.go
// to prevent chained symlink attacks (e.g., a/x -> .., then a/x/evil)
if header.Typeflag == tar.TypeDir || header.Typeflag == tar.TypeReg || header.Typeflag == tar.TypeSymlink {
parentDir := filepath.Dir(targetPath)
if parentDir != destDir {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to clean these directories from slashes?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you scroll up a bit, you will see:

targetPath := filepath.Clean(filepath.Join(destDir, header.Name))
and parentDir := filepath.Dir(targetPath)

Regarding destDir, expected from the caller to pass clean path.

@amalimov

amalimov commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@AvielSegev AvielSegev enabled auto-merge (rebase) June 7, 2026 06:12
@AvielSegev

AvielSegev commented Jun 7, 2026

Copy link
Copy Markdown
Collaborator Author

/lgtm

can you please approve the PR using the regular Approve pull request?

@amalimov amalimov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@AvielSegev AvielSegev merged commit bcae043 into kubev2v:main Jun 7, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants