Security checks for vulnerabilities and agentic risk
Overview
The skill does what it claims, but its output handling can overwrite or delete files the user did not intend to touch.
Review this skill before installing. Use it only in a dedicated empty output directory, choose a simple PDF filename, and avoid enabling cleanup if you need to inspect intermediate images or if the output folder may contain existing files.
The value used by this operation is accepted directly from the command line:
python
parser.add_argument("--pdf-name", type=str,
default="output.pdf", help="Name of the output PDF file.")
# ...
slice_and_generate_pdf(
source_image_path=args.source,
output_dir=args.out_dir,
output_pdf_name=args.pdf_name,
slice_height=args.slice_height,
overlap=args.overlap,
images_per_row=args.cols,
images_per_col=args.rows,
layout=args.layout,
cleanup=args.cleanup
)
Technical Analysis
The --pdf-name argument is treated as a trusted filename and joined directly to the selected output directory. No validation restricts it to a simple filename, checks its extension, rejects absolute paths, or prevents parent-directory traversal.
With pathlib, joining a path to an absolute second operand causes the original output directory to be discarded. Relative values containing .. can similarly resolve outside the intended output directory. The resulting path is passed to ReportLab's document builder, which can create or truncate the destination file.
Consequently, the output directory is not an effective security boundary. This is an arbitrary writable-file overwrite vulnerability rather than merely an output naming issue.
Attack Path
The attacker influences the command arguments used to invoke the skill.
The attacker supplies a valid source image and a writable output directory.
The attacker sets --pdf-name to an absolute path or a traversal path, such as:
text
--pdf-name ../../target-file
or:
te
...[truncated 822 chars]
Remediation
View remediation
Remediation Suggestions
Require --pdf-name to be a simple filename rather than a path.
Reject absolute paths, path separators, . and .. components.
Enforce an expected .pdf suffix.
Resolve the final destination and verify that it remains beneath the resolved output directory.
Refuse to overwrite an existing file unless the user explicitly enables a dedicated overwrite option.
Where feasible, create the file using exclusive creation semantics to reduce race conditions.
Example containment validation:
python
requested_name = Path(output_pdf_name)
if requested_name.is_absolute() or requested_name.name != output_pdf_name:
raise ValueError("--pdf-name must be a simple filename")
if requested_name.suffix.lower() != ".pdf":
raise ValueError("--pdf-name must use the .pdf extension")
output_root = output_path.resolve()
pdf_path = (output_root / requested_name.name).resolve()
if output_root not in pdf_path.parents:
raise ValueError("PDF destination escapes the output directory")
if pdf_path.exists():
raise FileExistsError(f"Refusing to overwrite existing file: {pdf_path}")
T09 · Insecure Skill Coding Practices
Warning
Location
scripts/slice_and_pdf.py:69
Finding
Predictable intermediate slice names can overwrite and delete unrelated files
Content
View full analysis
Vulnerability Details
File Location: scripts/slice_and_pdf.py, lines 69-75 and 165-171 Vulnerability Type: Unsafe temporary-file handling and destructive filename collision Risk Level: Medium
The predictable files are subsequently removed when cleanup is enabled:
python
deleted_count = 0
if cleanup:
for img_p in sliced_image_paths:
try:
Path(img_p).unlink(missing_ok=True)
deleted_count += 1
except Exception as e:
print(
f"Warning: Failed to delete intermediate file {img_p}: {e}")
Technical Analysis
Intermediate images are created directly inside the caller-selected output directory using deterministic names such as slice_0000.png. The script does not verify that these paths are absent, does not use exclusive file creation, and does not isolate temporary artifacts in a private directory.
If a matching file already exists, Pillow can overwrite it without warning. When --cleanup is enabled, the script then unlinks the path, causing the original file to be replaced and the replacement to be deleted.
Predictable paths also expose a time-of-check/time-of-use and symlink risk in shared or attacker-writable directories. An attacker able to create a matching symbolic link may cause the image write to follow that link and corrupt another writable file. Cleanup removes the link path afterward but does not restore the corrupted target.
Attack Path
A filename-collision attack can proceed as follows:
The selected output directory already contains an unrelated file named slice_0000.png, or an attacker places such a file there
...[truncated 1133 chars]
Remediation
View remediation
Remediation Suggestions
Store intermediate slices in a private temporary subdirectory created with tempfile.TemporaryDirectory.
Generate randomized names rather than deterministic names in the user-selected output directory.
Ensure temporary directories are accessible only to the invoking user.
Refuse to follow symbolic links and avoid writing to pre-existing paths.
Track and delete only artifacts successfully created by the current invocation.
Keep the final PDF separate from the temporary slice directory.
Use a finally block or the temporary-directory context manager to provide reliable cleanup after success or failure.
Example hardening pattern:
python
import tempfile
with tempfile.TemporaryDirectory(
prefix="long-image-slices-",
dir=str(output_path)
) as temporary_directory:
slice_directory = Path(temporary_directory)
slice_filename = f"slice_{slice_index:04d}{save_suffix}"
slice_output_path_obj = slice_directory / slice_filename
if slice_output_path_obj.exists() or slice_output_path_obj.is_symlink():
raise FileExistsError(
f"Refusing to overwrite slice path: {slice_output_path_obj}"
)
slice_img.save(slice_output_path_obj, format=save_format)
The PDF must be completely built before the temporary-directory context ends because ReportLab reads the slice files during document generation.
The skill instructs the agent to always add --cleanup by default, which causes automatic deletion of intermediate files without explicit user confirmation. This is a form of autonomous destructive decision-making: while limited to generated slices, it can still remove artifacts the user may need for verification, debugging, or recovery, especially if the script's cleanup scope is broader than expected.
Content
Scanner excerpt · SKILL.md (reported line 37)May include surrounding context.
md
* `--cols`: Number of columns in the PDF (default: `2`).
* `--rows`: Number of rows in the PDF (default: `2`).
* `--layout`: Arrangement sequence, either `grid` (left-to-right) or `column` (top-to-bottom) (default: `grid`).
* `--cleanup`: Add this flag to automatically delete the intermediate image slices after the PDF is created. (Highly recommended to save disk space unless the user explicitly asks to keep the sliced images).
## ⚠️ Important Instructions for the Agent (Guardrails)
1. **Always apply `--cleanup`** by default, unless the user specifically says "I want the sliced pictures too". Users generally only care about the final PDF.