{"record":{"id":"45fcb34c52f6b416","repo":"langchain-ai/deepagents","slug":"temporary-artifact-provenance-is-invalid","errorCode":null,"errorMessage":"temporary artifact provenance is invalid","messagePattern":"temporary artifact provenance is invalid","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/auto_mode.py","lineNumber":1116,"sourceCode":"    return Command(\n        update={\n            \"messages\": [\n                ToolMessage(\n                    content=content,\n                    name=tool_name,\n                    tool_call_id=tool_call_id,\n                    status=\"error\" if error else \"success\",\n                )\n            ]\n        }\n    )\n\n\ndef _delete_temp_artifact_file(artifact: AutoTempArtifact) -> None:\n    file_path = Path(artifact[\"file_path\"])\n    if not file_path.name.startswith(_TEMP_ARTIFACT_PREFIX):\n        msg = \"temporary artifact provenance is invalid\"\n        raise OSError(msg)\n    file_stat = file_path.lstat()\n    if (\n        not stat.S_ISREG(file_stat.st_mode)\n        or file_stat.st_dev != artifact[\"file_device\"]\n        or file_stat.st_ino != artifact[\"file_inode\"]\n    ):\n        msg = \"temporary artifact identity changed\"\n        raise OSError(msg)\n    file_path.unlink()\n\n\ndef _summarize_value(key: str, value: object, *, depth: int = 0) -> object:\n    if depth >= _MAX_ARGUMENT_DEPTH:\n        return \"[nested value omitted]\"\n    if _SECRET_KEY_RE.search(key):\n        return \"[redacted credential value]\"\n    if key.lower() in {\"content\", \"new_string\", \"old_string\", \"new_str\"} and isinstance(\n        value, str","sourceCodeStart":1098,"sourceCodeEnd":1134,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/auto_mode.py#L1098-L1134","documentation":"Raised by `_delete_temp_artifact_file` when the basename of the artifact's recorded `file_path` does not start with the library's temp-artifact prefix. This is a safety gate: `delete_temp_artifact` will only unlink files the library itself created (named with `_TEMP_ARTIFACT_PREFIX`), never arbitrary paths.","triggerScenarios":"Calling `delete_temp_artifact` with an `AutoTempArtifact` whose `file_path` was tampered with, hand-constructed, or deserialized from an older/foreign format — anything where the filename lacks the reserved prefix.","commonSituations":"Persisting artifacts to state and loading them after a library upgrade that renamed the temp prefix; manually building an `AutoTempArtifact` in tests pointing at a normal path; a hostile actor editing state to point deletion at an arbitrary file (the check is the defense).","solutions":["Only pass `AutoTempArtifact` dicts returned by `create_temp_artifact`; never hand-construct `file_path`","If artifacts were persisted across a library upgrade, re-create them with the current version instead of deleting stale records","Check state for corrupted or edited artifact entries and remove them without calling delete","Clean up stray files manually if the artifact record is unrecoverable"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"from pathlib import Path\nfrom deepagents_code.auto_mode import _TEMP_ARTIFACT_PREFIX\n\ndef is_safe_artifact(artifact) -> bool:\n    return Path(artifact[\"file_path\"]).name.startswith(_TEMP_ARTIFACT_PREFIX)","typeGuard":"def is_library_created_artifact(artifact: dict) -> bool:\n    path = artifact.get(\"file_path\")\n    return isinstance(path, str) and Path(path).name.startswith(_TEMP_ARTIFACT_PREFIX)","tryCatchPattern":"try:\n    delete_temp_artifact(artifact)\nexcept OSError as exc:\n    if \"provenance is invalid\" in str(exc):\n        drop_stale_record_without_unlink()\n    else:\n        raise","preventionTips":["Only pass AutoTempArtifact values obtained from create_temp_artifact","Never hand-construct or edit artifact file_path fields","Re-validate persisted artifacts after library upgrades (prefix may change)","Treat artifact records as opaque library data, not editable config"],"tags":["security","validation","temp-file","path-safety"],"backgroundTag":"path-traversal-guard","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}