{"record":{"id":"58d15b3172f0365b","repo":"langchain-ai/deepagents","slug":"temporary-artifact-is-not-owned-by-this-user","errorCode":null,"errorMessage":"temporary artifact is not owned by this user","messagePattern":"temporary artifact is not owned by this user","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/auto_mode.py","lineNumber":1059,"sourceCode":") -> AutoTempArtifact:\n    data = content.encode(\"utf-8\")\n    temp_root = Path(tempfile.gettempdir()).absolute()\n    file_descriptor, raw_path = tempfile.mkstemp(\n        prefix=_TEMP_ARTIFACT_PREFIX,\n        suffix=suffix,\n        dir=temp_root,\n    )\n    file_path = Path(raw_path)\n    complete = False\n    try:\n        file_stat = _write_temp_artifact_bytes(file_descriptor, data)\n        if not stat.S_ISREG(file_stat.st_mode):\n            msg = \"temporary artifact is not a regular file\"\n            raise OSError(msg)\n        getuid = getattr(os, \"getuid\", None)\n        if callable(getuid) and file_stat.st_uid != getuid():\n            msg = \"temporary artifact is not owned by this user\"\n            raise OSError(msg)\n        if os.name != \"nt\" and stat.S_IMODE(file_stat.st_mode) & 0o077:\n            msg = \"temporary artifact permissions are too broad\"\n            raise OSError(msg)\n        artifact = AutoTempArtifact(\n            allocation_id=uuid4().hex,\n            file_path=str(file_path),\n            thread_key=thread_key,\n            turn_id=turn_id,\n            created_by_tool_call_id=tool_call_id,\n            file_device=file_stat.st_dev,\n            file_inode=file_stat.st_ino,\n        )\n        complete = True\n        return artifact\n    finally:\n        with contextlib.suppress(OSError):\n            os.close(file_descriptor)\n        if not complete:","sourceCodeStart":1041,"sourceCodeEnd":1077,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/auto_mode.py#L1041-L1077","documentation":"Raised by `_allocate_temp_artifact` when the freshly created temp artifact's `st_uid` does not match the current process's `os.getuid()`. The library throws this to prevent trusting (and later deleting) a file that was swapped in by another local user — a classic TOCTOU hardening check on the shared temp directory.","triggerScenarios":"Calling `create_temp_artifact` where the `mkstemp` result is owned by a different uid — only possible on multi-user POSIX systems if the temp directory permits it (e.g. a sticky-bit directory with hostile content, uid changes via setuid, or a symlink attack replacing the file).","commonSituations":"Running the agent under sudo/setuid where uid flips mid-run; a shared/writable `/tmp` where another user races the mkstemp; `TMPDIR` pointing at a world-writable directory without the sticky bit; tests monkeypatching `os.getuid` inconsistently.","solutions":["Ensure the process does not change uid between creating and stat-ing the file (avoid setuid helpers mid-run)","Point `TMPDIR` at a directory owned by and writable only by the current user (e.g. a private run dir) so no other uid can race it","Check the temp directory has the sticky bit (`ls -ld /tmp` shows `drwxrwxrwt`) and correct ownership","If it appears in tests, verify any `os.getuid` monkeypatching matches the artifact's `st_uid`"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import os, tempfile, stat\ntmp = tempfile.gettempdir()\nst = os.stat(tmp)\nif os.name == \"posix\":\n    assert st.st_uid == os.getuid() or (st.st_mode & stat.S_ISVTX), \"temp dir not sticky-bit protected\"\n    assert not (st.st_mode & 0o002 and not (st.st_mode & stat.S_ISVTX)), \"world-writable temp dir without sticky bit\"","typeGuard":null,"tryCatchPattern":"try:\n    artifact = create_temp_artifact(content=content, suffix=\".txt\")\nexcept OSError as exc:\n    if \"not owned by this user\" in str(exc):\n        switch_to_private_tmpdir_and_retry()\n    else:\n        raise","preventionTips":["Avoid setuid/sudo transitions during an agent run","Use a per-user private temp directory instead of a shared world-writable one","Confirm /tmp (or TMPDIR) has the sticky bit on multi-user systems","Keep the agent process uid constant from tool call to cleanup"],"tags":["filesystem","permissions","security","temp-file","toctou"],"backgroundTag":"file-ownership-mismatch","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}