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 a listed file entry has a non-None `symlink_target`. Symlinks are categorically rejected to prevent exfiltrating files outside the artifacts directory (a link pointing at /etc/passwd or another tenant's data) — a security guard, not a size limit.
Source
Thrown at agent/sandbox/providers/ucloud_agent_sandbox.py:426
"""Collect allowed files from the execution artifact directory."""
artifacts: list[dict[str, Any]] = []
self._collect_artifacts_recursive(sandbox, artifacts_dir, "", artifacts, depth=0)
return artifacts
def _collect_artifacts_recursive(self, sandbox, current_dir: str, relative_dir: str, artifacts: list[dict[str, Any]], depth: int) -> None:
"""Traverse artifact directories while enforcing type, size, and depth limits."""
if depth > MAX_ARTIFACT_DEPTH:
raise RuntimeError(f"Artifact directory nesting exceeds {MAX_ARTIFACT_DEPTH} levels: {relative_dir}")
sdk = _get_ucloud_sandbox_module()
try:
entries = sandbox.files.list(current_dir, depth=1, request_timeout=self.timeout)
except sdk.FileNotFoundException:
return
for entry in sorted(entries, key=lambda item: item.path):
name = posixpath.basename(entry.path)
relative_path = posixpath.join(relative_dir, name) if relative_dir else name
if entry.symlink_target is not None:
raise RuntimeError(f"Artifact symlinks are not allowed: {relative_path}")
if entry.type == sdk.FileType.DIR:
self._collect_artifacts_recursive(sandbox, entry.path, relative_path, artifacts, depth + 1)
continue
if len(artifacts) >= self.max_artifacts:
raise RuntimeError(f"UCloud Agent Sandbox execution produced more than {self.max_artifacts} artifacts.")
if entry.size > self.max_artifact_bytes:
raise RuntimeError(f"Artifact exceeds {self.max_artifact_bytes} bytes: {relative_path}")
extension = os.path.splitext(name)[1].lower()
if extension not in ALLOWED_ARTIFACT_EXTENSIONS:
raise RuntimeError(f"Unsupported artifact type: {relative_path}")
content = bytes(sandbox.files.read(entry.path, format="bytes", request_timeout=self.timeout))
artifacts.append(
{
"name": relative_path,
"content_b64": base64.b64encode(content).decode("ascii"),
"mime_type": mimetypes.guess_type(name)[0] or "application/octet-stream",
"size": entry.size,
}View on GitHub (pinned to 554fb1133a)
Solutions
- Copy files into the artifacts directory instead of symlinking (`shutil.copy`, not os.symlink).
- Configure build tools to emit plain files or place their symlinked dirs outside artifacts.
- Treat this error as a security signal — audit user code that tried to symlink absolute paths.
- Do not attempt to bypass by raising MAX depth/size; the check is unconditional by design.
Example fix
# before
os.symlink("/etc/passwd", "artifacts/passwd") # collection -> RuntimeError
# after
shutil.copy("input.txt", "artifacts/input.txt") Defensive patterns
Strategy: try-catch
Validate before calling
# reject symlink creation in code you send to the sandbox
if "os.symlink" in code or "ln -s" in code:
raise ValueError("symlinks are not allowed in artifacts; copy files instead") Type guard
def is_symlink_artifact_error(exc: RuntimeError) -> bool:
return "symlinks are not allowed" in str(e if (e := exc) else "") Try / catch
try:
result = provider.execute(inst, code)
except RuntimeError as e:
if "symlinks are not allowed" in str(e):
# security signal: inspect what the code tried to link before retrying
audit_and_reject(code)
raise Prevention
- Use shutil.copy/copyfile for inputs placed in the artifacts directory.
- Treat this error as potential prompt-injection/exfiltration when the link target is outside the sandbox workspace.
- Lint generated code for os.symlink/ln -s before dispatch in security-sensitive deployments.
When it happens
Trigger: Executed code creating `os.symlink('/etc/passwd', 'artifacts/secret')` or symlinking any external path into the artifacts directory; collection then aborts the whole execution result.
Common situations: Convenient-looking LLM code that symlinks inputs into the output dir; build scripts whose tooling creates relative symlinks (e.g. node .bin links) inside the artifacts tree; prompt-injection attempts trying to read host files.
Related errors
- Artifact symlinks are not allowed: {path.name}
- Artifact symlinks are not allowed: {relative_path}
- Artifact symlinks are not allowed: {relative_path}
- Artifact directory nesting exceeds {MAX_ARTIFACT_DEPTH} leve
- UCloud Agent Sandbox execution produced more than {self.max_
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/d1b3969221022a15.
Report an issue: GitHub.