infiniflow/ragflow · error · RuntimeError
Artifact symlinks are not allowed: {relative_path}
Error message
Artifact symlinks are not allowed: {relative_path} What it means
Raised during artifact collection when an entry under artifacts/ is a symbolic link. Symlinks are rejected as a security measure: untrusted code could link to files outside the sandbox workspace (escape) or construct cycles; the check uses entry.is_symlink when populated plus the stat mode bits (stat.S_ISLNK) as the reliable fallback.
Source
Thrown at agent/sandbox/providers/tenki.py:466
errors = self._tenki_errors()
try:
entries = sandbox.fs.list(current_dir)
except errors.FileNotFoundError:
return
except FileNotFoundError:
return
# fs.list returns each entry's basename in `.path`, not an absolute
# path, so join it onto the directory being listed.
for entry in sorted(entries, key=lambda item: item.path):
name = posixpath.basename(entry.path)
remote_path = posixpath.join(current_dir, name)
relative_path = posixpath.join(relative_dir, name) if relative_dir else name
# Reject symlinks. `is_symlink` is not populated by every SDK
# release, so also inspect the stat mode bits as the reliable check.
if getattr(entry, "is_symlink", False) or stat.S_ISLNK(entry.mode or 0):
raise RuntimeError(f"Artifact symlinks are not allowed: {relative_path}")
if entry.is_dir:
self._collect_artifacts_recursive(sandbox, remote_path, relative_path, artifacts, depth + 1)
continue
if len(artifacts) >= self.max_artifacts:
raise RuntimeError(f"Tenki execution produced more than {self.max_artifacts} artifacts.")
size = int(entry.size or 0)
if size > self.max_artifact_bytes:
raise RuntimeError(f"Artifact exceeds {self.max_artifact_bytes} bytes: {relative_path}")
ext = os.path.splitext(name)[1].lower()
if ext not in ALLOWED_ARTIFACT_EXTENSIONS:
raise RuntimeError(f"Unsupported artifact type: {relative_path}")
content = sandbox.fs.read_bytes(remote_path)
artifacts.append(
{View on GitHub (pinned to 554fb1133a)
Solutions
- Change the script to copy real files (shutil.copy) into artifacts/ instead of symlinking.
- Treat this error in agent flows as a suspicious-code signal: reject or sanitize the generated program.
- Do not attempt to whitelist specific link targets — the provider rejects all symlinks by design.
Example fix
# before
# script: os.symlink('/etc/passwd', 'artifacts/passwd')
# after
# script: shutil.copyfile('/etc/passwd', 'artifacts/passwd') # only if that file is legitimately accessible Defensive patterns
Strategy: try-catch
Validate before calling
# in generated code, never place symlinks in artifacts:
# assert no os.path.islink(p) for p in pathlib.Path('artifacts').rglob('*') Try / catch
try:
result = provider.execute_code(instance_id, code)
except RuntimeError as exc:
if "symlinks are not allowed" in str(exc):
flag_untrusted_code(code) # potential sandbox escape attempt
raise Prevention
- Generate copy-based scripts (shutil.copyfile), not symlink-based ones.
- Treat symlink artifacts as a security signal from untrusted/LLM code; reject the program.
When it happens
Trigger: Executed script runs os.symlink('/etc/passwd', 'artifacts/leak') or creates symlink cycles inside the artifacts directory; artifact collection then aborts before reading any linked target.
Common situations: Adversarial or prompt-injected code trying to exfiltrate sandbox-external files via artifacts; build-style scripts that legitimately create symlinks (npm link patterns) and are surprised by the rejection.
Related errors
- Artifact symlinks are not allowed: {path.name}
- Artifact symlinks are not allowed: {relative_path}
- Artifact directory nesting exceeds {MAX_ARTIFACT_DEPTH} leve
- Artifact symlinks are not allowed: {relative_path}
- Tenki execution produced more than {self.max_artifacts} arti
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/5a57e6045cdd6f8c.
Report an issue: GitHub.