T09 · Insecure Skill Coding Practices
- Location
scripts/paste_rs.py:69- Finding
Predictable and Symlink-Unsafe Temporary File Creation
- Content
View full analysis
Vulnerability Details
File Location:
scripts/paste_rs.py, lines 69–73 and 80–88
Vulnerability Type: Unsafe temporary file handling
Risk Level: MediumVulnerable Code
python def _write_markdown_file(text: str, out_dir: Path) -> Path: out_dir.mkdir(parents=True, exist_ok=True) ts = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S") path = out_dir / f"paste-rs-{ts}.md" path.write_text(text, encoding="utf-8", errors="replace") return path def upload(text: str, timeout: int = 30, out_dir: str | None = None) -> tuple[str, Path]: """Write to a local .md file first, then upload its contents to paste.rs. Returns: (url, saved_path) """ if not text: raise ValueError("Refusing to upload empty content") saved_path = _write_markdown_file(text, Path(out_dir or "/tmp"))The command-line configuration also establishes
/tmpas the default destination:python p.add_argument( "--outdir", default="/tmp", help="Directory to save the .md file before uploading (default: /tmp)", )Technical Analysis
The script creates a file in the shared
/tmpdirectory using a name derived only from the current UTC timestamp with one-second precision. The resulting path is predictable, and concurrent executions during the same second use the same filename.Path.write_text()opens the selected path for writing without requesting exclusive creation and follows an existing symbolic link. A local attacker with access to the shared temporary directory can therefore pre-create the predicted path as a symbolic link. When a more privileged or different user invokes the Skill, the script may follow that link and truncate or overwrite a target file that the invoking user is authorized to modify.The implementation also leaves the local copy on disk after uploading. Its permissions depend on the process umask rather than an explicit restrictive mode, potentially allowing unintended local disclos ...[truncated 2057 chars]
- Remediation
View remediation
Remediation Suggestions
- Replace timestamp-based creation with
tempfile.NamedTemporaryFile()ortempfile.mkstemp()so the file has a cryptographically unpredictable name and is created atomically with exclusive semantics. - Create temporary files with mode
0600, independent of the caller's umask. - Prefer a private per-user temporary directory rather than writing directly into shared
/tmp. - Do not reopen the temporary file by pathname for upload. Write and read through the securely created file descriptor where practical.
- Delete the temporary file in a
finallyblock after the upload unless the user explicitly requests retention. - If persistent output is required, add an explicit option such as
--keep, use exclusive creation, and fail safely if the destination already exists. - Validate user-selected output directories and reject symbolic-link destinations where applicable.
- Handle simultaneous invocations without collisions.
A secure implementation can use the following pattern:
python import os import tempfile from pathlib import Path def _write_markdown_file(text: str, out_dir: Path) -> Path: out_dir.mkdir(parents=True, exist_ok=True) fd, raw_path = tempfile.mkstemp( prefix="paste-rs-", suffix=".md", dir=out_dir, text=True, ) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w", encoding="utf-8", errors="replace") as f: f.write(text) return Path(raw_path) except Exception: os.close(fd) Path(raw_path).unlink(missing_ok=True) raiseThe upload flow should additionally remove the file after use unless local retention was explicitly requested.
- Replace timestamp-based creation with
