Back to skill

Security audit

Protect PDF with password

Security checks for vulnerabilities and agentic risk

Overview

This skill does the advertised PDF password-protection task, but it handles sensitive PDFs, passwords, and API tokens with under-scoped endpoint and command-line secret risks that warrant Review before installation.

Install only if you are comfortable sending the PDF, the chosen password, and a Solutions API bearer token to an external service. Avoid confidential PDFs or reused passwords, prefer SOLUTIONS_API_KEY over command-line tokens, do not pass secrets directly in shell commands, and do not use SOLUTIONS_BASE_URL or --base-url unless you fully trust and validate the destination.

Vulnerability Patterns
  • Insecure DependenciesIntroduces malicious components through unsafe dependency sources
  • 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
Findings (3)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/password-protect-pdf.py:193
Finding

Arbitrary API base URL permits disclosure of the PDF, password, and Bearer token

Content
View full analysis

Vulnerability Details

File Location: scripts/password-protect-pdf.py:30, 57-64, 82-86, 193-197
Vulnerability Type: Unrestricted sensitive-data transmission endpoint
Risk Level: High

Vulnerable Code

python
DEFAULT_BASE_URL = "https://api.xss-cross-service-solutions.com/solutions/solutions"
python
def create_job(
    base_url: str,
    api_key: str,
    pdf_path: str,
    password: str,
    timeout_s: int = 120,
) -> Dict[str, Any]:
    url = base_url.rstrip("/") + CREATE_PATH
    headers = make_headers(api_key)

    with open(pdf_path, "rb") as f:
        files = {"file": (os.path.basename(pdf_path), f, "application/pdf")}
        data = {"userPass": password}

        resp = requests.post(url, headers=headers, files=files, data=data, timeout=timeout_s)
python
def get_job(
    base_url: str,
    api_key: str,
    job_id: Any,
    timeout_s: int = 30,
) -> Dict[str, Any]:
    url = base_url.rstrip("/") + f"/api/{job_id}"
    headers = make_headers(api_key)

    resp = requests.get(url, headers=headers, timeout=timeout_s)
python
ap.add_argument(
    "--base-url",
    default=os.getenv("SOLUTIONS_BASE_URL", DEFAULT_BASE_URL),
    help="Base URL override",
)

Technical Analysis

Uploading the PDF and its password to the documented Solutions API is explicitly declared by the Skill and is necessary for its remote-service design. However, the implementation allows the destination to be replaced through either the SOLUTIONS_BASE_URL environment variable or the --base-url argument.

The replacement URL is not restricted to the documented service, validated against an approved hostname, or required to use HTTPS. The same Bearer token intended for the legitimate service is attached to requests sent to the replacement destination. The initial POST also contains the complete PDF and the password supplied for protecting it.

This ...[truncated 1387 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove --base-url and SOLUTIONS_BASE_URL support if alternate service instances are not a strict functional requirement.
  • Hardcode the documented HTTPS origin and construct request paths from that trusted origin.
  • If endpoint configurability is required, parse the URL and enforce:
    • The https scheme.
    • An explicit allowlist of approved hostnames.
    • An expected port.
    • No embedded credentials.
    • No redirects to unapproved origins.
  • Configure requests not to forward authorization credentials across redirects. Validate the final response origin when redirects are permitted.
  • Use separate, non-production credentials for approved development endpoints.
  • Require explicit user confirmation before uploading a document to a non-default approved environment.
  • Document that the PDF and its password are transmitted to a third-party processor and clarify the service's retention and privacy expectations.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/password-protect-pdf.py:189
Finding

PDF password and API key can be exposed through command-line arguments

Content
View full analysis

Vulnerability Details

File Location: scripts/password-protect-pdf.py:189-192; README.md:26-29
Vulnerability Type: Sensitive information exposed through process arguments and shell history
Risk Level: Medium

Vulnerable Code

python
ap = argparse.ArgumentParser(description="Password-protect a PDF via Solutions API.")
ap.add_argument("--pdf", required=True, help="Path to input PDF")
ap.add_argument("--password", required=True, help="Password for PDF (will not be echoed)")
ap.add_argument("--api-key", default=os.getenv("SOLUTIONS_API_KEY", ""), help="Solutions API key (Bearer token)")

The documented invocation encourages passing both values through the command line:

bash
python scripts/password_protect_pdf.py \
  --pdf "/path/to/file.pdf" \
  --password "YourPasswordHere" \
  --api-key "$SOLUTIONS_API_KEY"

Technical Analysis

Although the script does not intentionally print the password or API key in its JSON output, command-line arguments are outside that protection. Depending on the operating system and execution environment, arguments can be exposed through process-listing tools, process telemetry, audit systems, job-runner logs, crash diagnostics, shell history, or orchestration metadata.

Expanding an environment variable in a command such as --api-key "$SOLUTIONS_API_KEY" still places the expanded secret in the process argument vector. The claim that the password “will not be echoed” therefore does not fully describe the actual exposure.

Attack Path

  1. A user follows the documented example and supplies the password and API key as command-line arguments.
  2. The shell may retain the command in its history, including a literal password.
  3. While the process is running, another authorized local user or monitoring component reads its argument vector.
  4. Alternatively, an automation platform records the complete command in execution logs or telemetry.
  5. The obse ...[truncated 539 chars]
Remediation
View remediation

Remediation Suggestions

  • Prompt for the PDF password through getpass.getpass() rather than requiring --password.
  • Obtain the API key exclusively from a protected environment variable, secret manager, or restricted credential file.
  • Remove or deprecate --api-key and --password.
  • If non-interactive password input is required, support a file descriptor, standard input, or a restricted file rather than an argument.
  • Update the README so examples do not place secrets in the command line.
  • Warn users that environment variables may also be visible to privileged processes and should be injected through the platform's secret-management facility.
  • Avoid logging parsed arguments and ensure wrappers, CI jobs, and orchestration systems redact secret fields.

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding

Open-ended dependency constraint prevents reproducible dependency resolution

Content
View full analysis

Vulnerability Details

File Location: requirements.txt:1
Vulnerability Type: Unpinned third-party dependency
Risk Level: Low

Vulnerable Code

text
requests>=2.32.0

Technical Analysis

The lower-bound-only constraint allows any future requests release to be installed without review. This makes installations non-reproducible and expands the supply-chain trust boundary beyond the version examined during the audit.

The package name is the legitimate requests package, and no typosquatting, custom package index, or known malicious package was identified. The risk is therefore the uncontrolled acceptance of future versions rather than evidence that the current dependency is malicious.

This dependency processes requests containing a Bearer token, a sensitive PDF, and its intended password, making controlled dependency updates especially important.

Attack Path

  1. A future release satisfying requests>=2.32.0 becomes available.
  2. A new installation or build resolves that release automatically.
  3. The Skill executes dependency code that was not part of the reviewed project state.
  4. If that release is compromised or introduces a security regression, sensitive network operations may be affected.

Impact Assessment

The potential impact depends on the behavior of a future compromised or vulnerable dependency release. Because requests operates in the Skill's process, such code could theoretically access process memory, environment variables, files readable by the process, and network request contents.

No current compromise was found, and this finding does not establish an immediately exploitable vulnerability in the reviewed requests version.

Remediation
View remediation

Remediation Suggestions

  • Pin requests and its transitive dependencies to reviewed versions.
  • Generate and commit a lock file appropriate for the project's package-management workflow.
  • Use hashes for dependency artifacts, such as through pip-compile --generate-hashes.
  • Install with hash verification in controlled builds.
  • Use an automated dependency-update process that runs security checks and tests before accepting new versions.
  • Periodically review pins so reproducibility does not result in indefinitely retaining vulnerable releases.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (11)

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

This skill initiates network communication to a remote API while processing sensitive inputs, yet that capability is reportedly not covered by declared permissions. In a skill system, missing permission declarations undermine sandboxing and informed trust because the component can exfiltrate files or secrets beyond what reviewers and users expect.

Content

No source excerpt is available for this finding.

Lp1

High
Category
MCP Least Privilege
Confidence
95% confidence
Finding

This skill initiates network communication to a remote API while processing sensitive inputs, yet that capability is reportedly not covered by declared permissions. In a skill system, missing permission declarations undermine sandboxing and informed trust because the component can exfiltrate files or secrets beyond what reviewers and users expect.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The README explicitly instructs users to send a PDF, the chosen password, and an API bearer token to a third-party remote service, but it does not clearly warn that document contents and secrets are being disclosed outside the local environment. This is dangerous because users may assume the skill operates locally and may upload sensitive PDFs or reuse important passwords, exposing confidential data to an external provider.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
87% confidence
Finding

This line documents a POST request to an external API endpoint that receives the PDF and password, which constitutes transmission of sensitive content and secrets to a third party. In the context of a password-protection skill, external transmission is not inherently malicious, but it becomes security-relevant because the README does not frame the privacy and trust implications for users.

Content

Scanner excerpt · README.md (reported line 19)May include surrounding context.

md
## How it works
1) Upload PDF + password to:
   `POST https://api.xss-cross-service-solutions.com/solutions/solutions/api/32`
2) Poll:
   `GET  https://api.xss-cross-service-solutions.com/solutions/solutions/api/<job_id>`
3) Return `output.files[0].path` as the download URL

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · README.md (reported line 21)May include surrounding context.

md
1) Upload PDF + password to:
   `POST https://api.xss-cross-service-solutions.com/solutions/solutions/api/32`
2) Poll:
   `GET  https://api.xss-cross-service-solutions.com/solutions/solutions/api/<job_id>`
3) Return `output.files[0].path` as the download URL

## Script (CLI)

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The skill handles highly sensitive inputs—a PDF and its password—but does not clearly warn users in the main behavior/inputs flow that both are transmitted to an external third-party API. This creates a meaningful privacy and confidentiality risk because users may assume processing is local or agent-native and submit sensitive documents or secrets without informed consent.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
86% confidence
Finding

The skill is explicitly designed to send user-supplied files and passwords to an external service endpoint, which is a real data exfiltration surface even if it is part of intended functionality. Because the transmitted data includes document contents and the protection password itself, compromise, logging, retention, or misuse by the third party could expose sensitive material.

Content

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

md
## API endpoints
Base URL:
- `https://api.xss-cross-service-solutions.com/solutions/solutions`

Create password-protect job:
- `POST /api/32`

External Transmission

Medium
Category
Data Exfiltration
Confidence
94% confidence
Finding

The code hardcodes an external service endpoint and sends sensitive document data to it. External transmission is materially more dangerous in this skill context because the feature involves protecting confidential PDFs, yet it depends on exporting both the file and associated secret to an outside system, expanding exposure to compromise, logging, retention, and supply-chain risk.

Content

Scanner excerpt · scripts/password-protect-pdf.py (reported line 30)May include surrounding context.

python
import requests


DEFAULT_BASE_URL = "https://api.xss-cross-service-solutions.com/solutions/solutions"
CREATE_PATH = "/api/32"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The script uploads both the PDF contents and the user-chosen password to a third-party service, but at execution time it provides no explicit warning or confirmation that highly sensitive material is leaving the local environment. This is especially risky because passwords and document contents may contain confidential data, and users may assume the operation is local based on the skill name alone.

Content

No source excerpt is available for this finding.

Unpinned Dependencies

Low
Category
Supply Chain
Confidence
95% confidence
Finding

The dependency is specified as requests>=2.32.0, which allows future versions to be installed without review and makes builds non-reproducible. In a skill that uploads PDFs to a remote API and may handle sensitive documents, uncontrolled dependency resolution increases supply-chain risk and can unintentionally pull in a vulnerable or breaking release.

Content

Scanner excerpt · requirements.txt (reported line 1)May include surrounding context.

text
requests>=2.32.0

Unverifiable Dependency: requests has 16 known advisory(ies) (CVE-2014-1830 (Exposure of Sensitive Information to an Unauthorized Actor in Requests); CVE-2024-47081 (Requests vulnerable to .netrc credentials leak via malicious URLs); CVE-2024-35195 (Requests `Session` object does not verify requests after making first request wi) +13 more), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
91% confidence
Finding

Because requests is not pinned, it is not possible to verify from this manifest whether the installed version includes fixes for known advisories. Given that this skill communicates with an external service and may transmit sensitive PDF data or credentials, uncertainty about the exact HTTP client version raises supply-chain and data-exposure concerns.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.