argoproj/argo-workflows · error
illegal symlink target: %s -> %s
Error message
illegal symlink target: %s -> %s
What it means
When a tar entry is a symlink, the executor resolves its target (relative to the link's directory) and verifies the cleaned target stays inside the destination directory. A symlink pointing outside dest would let extraction redirect writes, so it is rejected with 'illegal symlink target'.
Source
Thrown at workflow/executor/executor.go:1153
return nil
case err != nil:
return err
case header == nil:
continue
}
target := filepath.Join(dest, filepath.Clean(header.Name))
if !strings.HasPrefix(target, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("illegal file path: %s", header.Name)
}
switch header.Typeflag {
case tar.TypeSymlink:
// Validate symlink target before creating it
linkTarget := header.Linkname
if !filepath.IsAbs(linkTarget) {
linkTarget = filepath.Join(filepath.Dir(target), header.Linkname)
}
if !strings.HasPrefix(filepath.Clean(linkTarget), filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("illegal symlink target: %s -> %s", header.Name, header.Linkname)
}
// Create parent directory if needed
if err := os.MkdirAll(filepath.Dir(target), 0o755); err != nil {
return err
}
err := os.Symlink(header.Linkname, target)
if err != nil {
return err
}
case tar.TypeDir:
if err := os.MkdirAll(target, 0o755); err != nil {
return err
}
case tar.TypeReg:
// Before writing the file, check if the parent directory resolves outside dest
parentDir := filepath.Dir(target)
// Resolve the destination directoryView on GitHub (pinned to 35bff19146)
Solutions
- Repackage the artifact so symlinks are relative and stay within the archive root
- Inspect the tarball (tar -tvf) and remove/fix offending symlinks before uploading
- Avoid loading untrusted archives as input artifacts
- If the symlink legitimately points elsewhere, copy the real file into the archive instead of linking
Example fix
# before (packaging escape symlink) ln -s /etc/passwd out.tar member # after (relative, in-root) ln -s ./realfile member && tar -C root -cf out.tar .
Defensive patterns
Strategy: try-catch
Validate before calling
// Check archive symlinks before uploading: // tar -tvf artifact.tar | grep '^l' # list symlink members // tar -tvf artifact.tar | grep -E 'l.*/' # links with absolute targets
Try / catch
if err := loadArtifacts(ctx); err != nil {
if strings.Contains(err.Error(), "illegal symlink target") {
// archive contains an escaping symlink: repackage with relative links
}
} Prevention
- Package symlinks as relative and pointing within the archive root
- Copy real files instead of symlinks when distributing artifacts
- Inspect archives (tar -tvf) for symlink members from untrusted producers
- Extract to a clean destination directory
When it happens
Trigger: A tarball member of type TypeSymlink whose Linkname points outside the extraction root, e.g. link name 'x' with target '../../etc/passwd' or an absolute path like '/etc/passwd'.
Common situations: Malicious or careless artifact packaging that includes escape symlinks; archives generated on other systems containing absolute symlinks; supply-chain-poisoned third-party artifacts.
Related errors
- illegal file path after symlink resolution: %s resolves outs
- illegal file path: %s
- artifact key %q must not contain '..'
- %s: Illegal file path
- failed to stat artifact path %q at %s: %w
AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03).
Data as JSON: /api/errors/00080764a8b08246.
Report an issue: GitHub.