Back to skill

Security audit

Sync DeBox Docs

Security checks for vulnerabilities and agentic risk

Overview

The skill generally matches its stated DeBox documentation-sync purpose, but it can make broad outbound requests from the user's environment based on links and images found in the docs.

Use this skill only with a dedicated empty output folder and preferably in an environment without access to private networks, localhost admin services, or cloud metadata endpoints. It does not ask for credentials and does not install packages, but it will write and refresh local documentation files and may make outbound requests beyond docs.debox.pro while checking documentation links and images.

Vulnerability Patterns
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sync_debox_docs.py:426
Finding

Server-Side Request Forgery Through Untrusted Documentation Resources

Content
View full analysis
str | None: if urlsplit(url).scheme not in {"http", "https"}: return None try: url = urlunsplit((*urlsplit(url)[:4], "")) request = Request(request_url(url), method="HEAD", headers={"User-Agent": USER_AGENT}) with urlopen(request, timeout=TIMEOUT) as response: if response.status >= 400: return f"{url}: HTTP {response.status}" return None except HTTPError as exc: if exc.code in {403, 405}: try: request = Request(request_url(url), headers={"User-Agent": USER_AGENT, "Range": "bytes=0-0"}) with urlopen(request, timeout=TIMEOUT): return None ``` Image URLs extracted from documentation are also fetched without destination validation: ```python for parser in parsed_pages.values(): for source, alt in parser.images: image_usage.setdefault(source, set()).add(parser.base_url) if alt: image_alts.setdefault(source, set()).add(alt) if source in image_sources: continue try: data, content_type = fetch(source, MAX_IMAGE_BYTES, "image/*") if not content_type.startswith("image/"): raise ValueError(f"expected image but received {content_type}") image_sources[source] = (data, content_type) except Exception as exc: # noqa: BLE001 broken_images.append(f"{source}: {exc}") ``` All HTTP and HTTPS links extracted from document articles are checked concurrently: ```python check_urls = sorted({ urlunsplit((*urlsplit(url)[:4], "")) for url in all_links if urlsplit(url).scheme in {"http", ...[truncated 2941 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/sync_debox_docs.py:409
Finding

Path Traversal and Arbitrary File Write Through Unvalidated Manifest Paths

Content
View full analysis
dict: path = output / "manifest.json" if not path.exists(): return {"pages": {}, "images": {}} value = json.loads(path.read_text(encoding="utf-8-sig")) if value.get("schema_version") != SCHEMA_VERSION: raise ValueError("manifest schema version is not supported by this script") return value ``` Existing image paths are copied directly from the persisted manifest: ```python image_files = {source: entry["file"] for source, entry in old.get("images", {}).items()} image_files.update({ source: image_file(source, content_type) for source, (_data, content_type) in image_sources.items() }) ``` Those persisted paths are then joined to the staging directory and written without containment validation: ```python for source, (data, content_type) in image_sources.items(): target = stage / image_files[source] target.parent.mkdir(parents=True, exist_ok=True) target.write_bytes(data) new_images[source] = { "file": image_files[source], "content_type": content_type, "sha256": sha256(data), "used_by": sorted(image_usage.get(source, set())), "alt_texts": sorted(image_alts.get(source, set())), } ``` ### Technical Analysis The `file` fields in an existing `manifest.json` are treated as trusted filesystem paths. The implementation does not verify that these values: - Are strings. - Are relative paths. - Do not contain `..` traversal components. - Remain under the expected `images/` or `markdown/` managed roots. - Resolve beneath the temporary staging directory. - Avoid symlink-based escapes. With `path ...[truncated 3323 chars]
Remediation
View remediation
Path: candidate_path = Path(relative) if candidate_path.is_absolute() or ".." in candidate_path.parts: raise ValueError("unsafe manifest path") if not candidate_path.parts or candidate_path.parts[0] != required_prefix: raise ValueError("manifest path is outside the required managed root") resolved_root = root.resolve() resolved_candidate = (resolved_root / candidate_path).resolve() if resolved_candidate != resolved_root and resolved_root not in resolved_candidate.parents: raise ValueError("manifest path escapes the managed root") return resolved_candidate ``` 6. Reject symlinks within managed output and staging paths, or perform file operations through directory file descriptors with no-follow semantics where supported. 7. Recompute deterministic local paths from source URLs instead of trusting path values persisted in the previous manifest. 8. Validate all old page and image records before calculating unchanged files, local links, or stale-file deletions. 9. Write manifest and report files atomically to reduce corruption and partial-state risks. 10. Add tests for absolute paths, `../` traversal, nested traversal, Windows drive paths, UNC paths, symlink escapes, malformed record types, and paths using unexpected managed-root prefixes. ]]>
Vulnerability Patterns
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (3)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 24)May include surrounding context.

md
Resolve the script path relative to this `SKILL.md`. Find a working Python command, preferring

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
95% confidence
Finding

The skill instructs the agent to read and write local files and access a public website, but it does not declare any explicit tool scope such as allowed-tools or permissions. That creates an authorization ambiguity where a host system may grant broader capabilities than intended, increasing the risk of unintended file access, overwrites, or network retrieval beyond the minimally necessary operations.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
75% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · SKILL.md (reported line 20)May include surrounding context.

md
3. Does the current model support image understanding? Offer exactly two choices, localized
   to the user's language: `supports image understanding` or `does not support image understanding`.

Do not reuse answers from an earlier run without asking again.

## Run

Static analysis

No suspicious patterns detected.