T08 · Insecure Dependencies
- Location
README.md:62- Finding
Unpinned third-party package execution through npx
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill largely matches its stated writing-voice purpose, but its install and privacy safeguards are under-scoped for private writing data.
Review before installing. Prefer cloning or copying the reviewed repository instead of the unpinned `npx` command, and add/verify `.gitignore` rules before using real writing samples. Use only consented subject-authored sources, keep manifests and context packs outside Git, and remember that any agent/model that reads the context pack may process those excerpts.
README.md:62Unpinned third-party package execution through npx
scripts/validate_package.py:12Missing Git ignore rules can expose private voice data
The declared description is about constructing and using a local writing-voice digital twin for drafting and revision. The actual code does not build a voice model, process subject-authored writing, generate or revise text, or implement consent/provenance workflows directly. Instead, it performs repository/package validation and safety/compliance checks for the Doppel package. While these checks may support the broader project, this code chunk’s primary purpose is materially different from the declared end-user functionality, so this is a clear description-behavior mismatch.
The README instructs users to run npx skills add AntreasAntoniou/doppel without pinning a specific package version. Because npx resolves and executes code from the registry at install time, a future compromised, malicious, or simply breaking release of the referenced package/tooling could be executed on a user's machine, creating a supply-chain risk.
Without declared permissions the skill's intent is opaque and cannot be validated.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
def tracked_files(root: Path = ROOT) -> list[Path]:
result = subprocess.run(
["git", "ls-files"], cwd=root, check=False, capture_output=True, text=True
)
if result.returncode == 0:
The manifest describes building a consent-first, provenance-aware local writing-voice context pack from subject-authored material. The separate --hash mode lets a caller compute the SHA-256 of any local file path, which is a general-purpose file utility not clearly justified by drafting or revising text with a voice Doppel.
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.
raise SystemExit("--hash cannot be combined with context-building arguments")
print(sha256_file(args.hash.resolve()))
return 0
missing = [name for name in ("manifest", "task", "audience", "output") if getattr(args, name) is None]
if missing:
raise SystemExit(f"Missing required arguments: {', '.join('--' + item for item in missing)}")
if not safe_local_output_name(args.output):
No suspicious patterns detected.