Back to skill

Security audit

Camoufox Browse

Security checks for vulnerabilities and agentic risk

Overview

This skill is a clearly disclosed anti-detection browser helper, but users should handle its dependencies and saved browser sessions carefully.

Install this only if you need anti-detection browsing for sites you are authorized to automate. Prefer disposable accounts and profiles, pin or lock Camoufox dependencies, avoid storing session-state files in shared or source-controlled locations, and get explicit approval before form submissions, bulk actions, downloads, or deletion.

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 (2)

T08 · Insecure Dependencies

Warning
Location
SKILL.md:43
Finding

Unpinned Executable Dependencies and Unverified Browser Artifacts

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:43-45, SKILL.md:97-100; duplicated in README.md:30-36
Vulnerability Type: Third-party supply-chain exposure
Risk Level: Medium

Vulnerable Code

bash
npm install playwright@1.60.0 camoufox-js

# First run auto-fetches the camoufox Firefox binary into node_modules
bash
python3 -m pip install "camoufox[geoip]" playwright==1.60.0

# Fetch the camoufox browser binary (~700 MB) + uBlock Origin addon
python3 -m camoufox fetch

Technical Analysis

Although Playwright is pinned to version 1.60.0, the camoufox-js and camoufox packages are not pinned to exact versions. Their transitive dependency trees are also not locked in the documented installation process.

The Node package automatically retrieves a Firefox artifact on first use, while the Python workflow explicitly invokes camoufox fetch. The instructions do not require verification of the downloaded browser or extension using an immutable checksum or publisher signature.

This makes the effective executable content dependent on mutable registry packages and remote artifacts available at installation time. Package installation can execute lifecycle or build logic, and the fetched browser is subsequently executed locally. This is a supply-chain weakness rather than evidence that the currently named dependencies are malicious.

Attack Path

  1. An attacker compromises a relevant package publisher, registry account, transitive dependency, or artifact distribution channel.
  2. The attacker publishes a modified release or replaces a remotely downloaded artifact.
  3. A user follows the documented unpinned installation or fetch command.
  4. The package manager installs the attacker-controlled release, or Camoufox retrieves the substituted browser artifact.
  5. Installation hooks, build logic, imported package code, or the downloaded browser executes under the installing user's accou ...[truncated 890 chars]
Remediation
View remediation

Remediation Suggestions

  1. Pin camoufox-js and camoufox to reviewed, exact versions rather than version ranges.
  2. Commit and enforce lock files for Node dependencies, using deterministic installation such as npm ci.
  3. Use a Python constraints or lock file containing hashes for all direct and transitive packages.
  4. Document the expected source, version, checksum, and signature for downloaded Firefox and extension artifacts.
  5. Verify downloaded artifacts before execution and fail closed if verification is unavailable or unsuccessful.
  6. Disable or review package lifecycle scripts where feasible.
  7. Perform installation in a sandbox, container, or restricted account without access to production credentials.
  8. Periodically review pinned versions and update them through an explicit, audited dependency-update process.

T09 · Insecure Skill Coding Practices

Warning
Location
SKILL.md:313
Finding

Browser Authentication State Written to Plaintext File Without Restrictive Permissions

Content
View full analysis

Vulnerability Details

File Location: SKILL.md:313-314
Vulnerability Type: Insecure storage of authentication material
Risk Level: Medium

Vulnerable Code

js
const state = await context.storageState();
fs.writeFileSync('/path/to/state.json', JSON.stringify(state));

The related Python example at SKILL.md:323-325 also demonstrates loading and obtaining persistent storage state:

python
async with AsyncCamoufox(headless=True) as browser:
    context = await browser.new_context(storage_state="/path/to/state.json")
    # ...
    state = await context.storage_state()  # save for next run

Technical Analysis

Playwright storage-state files can contain authentication cookies, origin storage, and tokens capable of restoring a logged-in browser session. The Node example serializes this state directly to a plaintext JSON file using the process's default permission behavior.

The example does not enforce a restrictive mode such as 0600, require a private storage directory, encrypt the file, define a retention period, or securely remove it after use. A user may also substitute a path inside a repository, shared workspace, backup location, or artifact directory.

Session persistence is relevant to the Skill's declared functionality, but retaining reusable authentication material without mandatory file protections exceeds the minimum safe implementation needed for that feature. The operational-safety warning against personal or production cookies mitigates intent but does not secure the example itself.

Attack Path

  1. The Agent signs in to a target site and receives authenticated cookies or tokens.
  2. context.storageState() exports those credentials into a JSON object.
  3. The example writes the object to /path/to/state.json without explicitly restrictive permissions.
  4. The file becomes accessible through another local account or process, a shared workspace, a backup, an upload ...[truncated 1048 chars]
Remediation
View remediation

Remediation Suggestions

  1. Create session-state files with owner-only permissions:
    js
    fs.writeFileSync(statePath, JSON.stringify(state), {
      mode: 0o600,
      flag: 'wx'
    });
    
  2. Store state in a dedicated private directory created with mode 0700.
  3. Reject paths located inside repositories, shared workspaces, temporary upload directories, or publicly synchronized folders.
  4. Add storage-state filename patterns to source-control and artifact ignore rules.
  5. Prefer disposable, least-privileged accounts and short-lived sessions.
  6. Encrypt persistent state using an operating-system credential store or a managed secret-storage service where practical.
  7. Define a short retention period and delete state immediately when persistence is no longer required.
  8. Revoke the corresponding server-side session after task completion or suspected exposure.
  9. Warn users explicitly that storage-state JSON should be treated as a reusable credential, not ordinary cache data.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (1)

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
91% confidence
Finding

The Node quick-start example hard-codes locale: 'id-ID', which imposes a specific language/locale setting in natural-language-facing behavior. The surrounding text does not present this as an opt-in choice for the user or justify why Indonesian locale is required for a region-specific use case.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.