Back to skill

Security audit

Website Phone Number Finder (Apify)

Security checks for vulnerabilities and agentic risk

Overview

The skill is mostly coherent for running an Apify website contact scraper, but it defaults toward personal-data collection and has credential-handling and install-supply-chain risks users should review before installing.

Install only if you are comfortable sending submitted websites and scraped contact results to Apify. Use a narrowly scoped Apify token, prefer APIFY_TOKEN over --apify-token, set a budget guard, and disable personal-data collection unless you have a clear lawful reason to collect it.

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

Warning
Location
scripts/website_phone_number_finder_actor.py:173
Finding

Apify API Token Embedded in Request URL

Content
View full analysis

Vulnerability Details

File Location: scripts/website_phone_number_finder_actor.py, lines 173-185
Vulnerability Type: Credential exposure through URL query parameters
Risk Level: Medium

Vulnerable Code

python
def run_actor(token: str, actor_id: str, payload: dict[str, Any], timeout_sec: int, budget_usd: float | None) -> dict[str, Any]:
    params: dict[str, str | int | float] = {
        "token": token,
        "timeout": timeout_sec,
        "clean": "true",
    }
    if budget_usd is not None:
        if budget_usd <= 0:
            raise SkillError("--budget-usd must be > 0.")
        params["maxTotalChargeUsd"] = budget_usd

    actor_path = urllib.parse.quote(actor_id, safe="")
    url = f"https://api.apify.com/v2/acts/{actor_path}/run-sync-get-dataset-items?{urllib.parse.urlencode(params)}"

Technical Analysis

The Apify API token is inserted into the request URL as the token query parameter. Although HTTPS encrypts the request in transit, URLs are frequently captured by local debugging tools, reverse proxies, HTTP monitoring systems, telemetry platforms, exception reports, and infrastructure access logs.

Query-string authentication therefore increases the likelihood that the credential will be retained outside the process's intended security boundary. Anyone who obtains a complete logged URL can extract and reuse the token.

The outbound request itself is necessary for the Skill's declared hosted Apify workflow, and no undisclosed destination was identified. The vulnerability concerns the authentication transport mechanism rather than the legitimacy of the network request.

Attack Path

  1. A user runs the Skill with a valid Apify token.
  2. The runner constructs a URL containing token=<credential>.
  3. A proxy, debugger, monitoring agent, telemetry integration, or verbose network log records the complete URL.
  4. An attacker with access to that record extrac ...[truncated 558 chars]
Remediation
View remediation

Remediation Suggestions

  • Authenticate through an HTTP authorization header instead of a query parameter where supported:

    python
    request = urllib.request.Request(
        url,
        data=json.dumps(payload).encode("utf-8"),
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {token}",
        },
        method="POST",
    )
    
  • Keep non-secret options such as timeout and budget in the query string, but remove token.

  • Redact authentication values from exceptions, diagnostics, and request logging.

  • Use a narrowly scoped Apify token where the platform supports token scoping.

  • Rotate any token that may already have appeared in URL or proxy logs.

T09 · Insecure Skill Coding Practices

Note
Location
scripts/website_phone_number_finder_actor.py:40
Finding

Apify Token Can Be Supplied Through a Command-Line Argument

Content
View full analysis

Vulnerability Details

File Location: scripts/website_phone_number_finder_actor.py, lines 40-44 and line 222
Vulnerability Type: Credential exposure through process arguments
Risk Level: Low

Vulnerable Code

python
def resolve_token(explicit: str | None) -> str:
    token = explicit or os.getenv("APIFY_TOKEN", "")
    if not token:
        raise SkillError("Apify token missing. Pass --apify-token or set APIFY_TOKEN.")
    return token
python
def add_common_run_args(parser: argparse.ArgumentParser) -> None:
    parser.add_argument("--actor-id", default=DEFAULT_ACTOR_ID)
    parser.add_argument("--apify-token")
    parser.add_argument("--budget-usd", type=float)
    parser.add_argument("--timeout-sec", type=int, default=DEFAULT_TIMEOUT_SEC)

Technical Analysis

The runner accepts the Apify credential through --apify-token. Secrets supplied as command-line arguments may become visible in shell history, process inspection utilities, operating-system audit records, CI/CD logs, orchestration metadata, and terminal session recordings.

The documentation recommends APIFY_TOKEN, which reduces normal exposure, but the command-line interface still offers and advertises the less secure credential path.

Attack Path

  1. A user invokes the script with --apify-token followed by a real credential.
  2. The shell records the command, or a process-monitoring system captures its argument vector.
  3. Another local user, administrator, monitoring operator, or attacker with access to retained logs reads the token.
  4. The token is reused against the Apify API.

Impact Assessment

The exposed credential may permit unauthorized use of the associated Apify account within the token's assigned permissions. Potential consequences include actor execution, access to authorized resources, and consumption of paid account capacity.

Exploitation requires access to process metadata, shell ...[truncated 90 chars]

Remediation
View remediation

Remediation Suggestions

  • Remove the --apify-token option and obtain the token only from APIFY_TOKEN or an approved credential manager.

  • Revise the missing-token error so it does not recommend a command-line secret:

    python
    def resolve_token() -> str:
        token = os.getenv("APIFY_TOKEN", "")
        if not token:
            raise SkillError("Apify token missing. Set APIFY_TOKEN securely.")
        return token
    
  • For interactive use, optionally read the credential with getpass.getpass() so it is not echoed or stored in command history.

  • Configure CI/CD systems to inject the token through protected secret variables rather than command arguments.

  • Avoid printing environment values or including them in diagnostic output.

T08 · Insecure Dependencies

Note
Location
README.md:67
Finding

Documentation Recommends Unpinned Third-Party Installation Commands

Content
View full analysis

Vulnerability Details

File Location: README.md, lines 67-83
Vulnerability Type: Unpinned installation-time supply-chain dependency
Risk Level: Low

Vulnerable Code

bash
npx skills add hundevmode/apify-website-phone-number-finder-agent-skill \
  --skill website-phone-number-finder-apify
bash
npx skills add hundevmode/apify-website-phone-number-finder-agent-skill \
  --skill website-phone-number-finder-apify \
  --agent codex \
  -y
bash
npx skills add hundevmode/apify-website-phone-number-finder-agent-skill --list

Technical Analysis

These commands invoke npx skills without pinning the CLI package to a reviewed version. They also identify the Skill source by repository name rather than an immutable commit or verified release artifact.

Consequently, the package and repository content resolved when a user executes the command can differ from the content covered by this audit. If the package registry account, upstream package, repository, or release process is compromised, installation may retrieve altered instructions or code.

No malicious dependency or remote payload was found in the audited project itself. This finding concerns the mutability and trust model of the documented installation path.

Attack Path

  1. An attacker compromises the relevant package publication account, upstream repository, or release channel.
  2. The attacker publishes a modified CLI package or changes the repository content.
  3. A user executes the unpinned npx skills add command from the README.
  4. npx resolves the current package version, and the installer resolves current upstream Skill content.
  5. The altered installer or Skill content executes or is installed under the invoking user's permissions.

Impact Assessment

Impact depends on the behavior of the compromised upstream component and the permissions of the account running npx. Potential scope includes modif ...[truncated 364 chars]

Remediation
View remediation

Remediation Suggestions

  • Pin the skills CLI to a reviewed, exact package version rather than relying on the current registry release.
  • Pin the Skill source to an immutable commit hash or signed release tag where the installation tool supports it.
  • Publish and verify checksums or signatures for release artifacts.
  • Document the exact audited CLI version and Skill revision.
  • Prefer lockfiles or equivalent integrity metadata for automated installation workflows.
  • In high-assurance environments, download and inspect the fixed artifact before executing installation tooling.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (15)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
9. Run `scripts/website_phone_number_finder_actor.py` or call the Apify API directly.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
9. Run `scripts/website_phone_number_finder_actor.py` or call the Apify API directly.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
9. Run `scripts/website_phone_number_finder_actor.py` or call the Apify API directly.

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

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

md
9. Run `scripts/website_phone_number_finder_actor.py` or call the Apify API directly.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

The README instructs users to run npx skills add ... without pinning an exact package version. npx will fetch the latest matching package at execution time, so a compromised upstream package, dependency, or account could cause arbitrary code to run on the user's machine during installation.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
90% confidence
Finding

This command again relies on npx skills without a pinned version, which means execution depends on whatever package version is current at runtime. If the package or its supply chain is hijacked, users could execute attacker-controlled code simply by following the README instructions.

Content

No source excerpt is available for this finding.

Rp1

Medium
Category
MCP Rug Pull
Confidence
88% confidence
Finding

Even though this example only lists skills, npx skills still downloads and executes an unpinned package. The skill context increases exposure because users of agent tooling may routinely copy-paste setup commands, making supply-chain compromise a practical attack vector.

Content

No source excerpt is available for this finding.

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
89% confidence
Finding

The skill clearly expects access to environment secrets, local files, and outbound network access, but it does not declare an explicit tool scope such as permissions or allowed-tools. That creates an avoidable least-privilege gap: a host agent may grant broader capabilities than intended, making misuse of the Apify token or unexpected file/network access harder to govern and audit.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill supports extracting optional emails and personal-profile data, and even documents includePersonalData and extractEmails, but it does not present a clear upfront privacy warning in the main description or user-facing guidance. This can lead operators to collect personal data without informed consent, policy review, or jurisdiction-specific legal checks, increasing privacy, compliance, and reputational risk.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The contract explicitly supports extracting optional emails, social profiles, and even personal LinkedIn URLs or person-like emails, but it does not pair that capability with any privacy, consent, or acceptable-use warning. In a lead-generation scraping context, this increases the risk of collecting personal data beyond business contact details and enables downstream misuse or non-compliant processing of personal information.

Content

No source excerpt is available for this finding.

Description-Behavior Mismatch

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The skill’s stated purpose is finding public business phone numbers, but the default-capable payload also enables email, social profile, and personal data extraction. That creates unnecessary data collection beyond the narrow business need, increasing privacy and misuse risk if operators submit broad target lists or individuals’ sites.

Content

No source excerpt is available for this finding.

Context-Inappropriate Capability

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The code sets includePersonalData to True by default, which authorizes collection of personal data without a clear need for the advertised task of finding public business phone numbers. In an agent skill context, this is especially risky because users may invoke it expecting business-only contact discovery while the tool silently broadens collection scope.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The script transmits the full scraping payload and receives scraped contact/PII-related results through a third-party Apify service, but there is no user-facing disclosure, consent flow, or minimization step. In a security-sensitive agent environment, undisclosed external processing of contact and personal data increases privacy, compliance, and data handling risk.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
60% 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 · scripts/website_phone_number_finder_actor.py (reported line 185)May include surrounding context.

python
params["maxTotalChargeUsd"] = budget_usd

    actor_path = urllib.parse.quote(actor_id, safe="")
    url = f"https://api.apify.com/v2/acts/{actor_path}/run-sync-get-dataset-items?{urllib.parse.urlencode(params)}"
    request = urllib.request.Request(
        url,
        data=json.dumps(payload).encode("utf-8"),

Scope Creep

Low
Category
Excessive Agency
Confidence
70% confidence
Finding

Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.

Content

Scanner excerpt · LICENSE (reported line 12)May include surrounding context.

text
permit persons to whom the Software is furnished to do so.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE

Static analysis

No suspicious patterns detected.