Back to skill

Security audit

Felo Web Extract

Security checks for vulnerabilities and agentic risk

Overview

This skill does what it claims, but it can send a Felo API key and requested URLs to an environment-selected API host, which users should review before installing.

Review before installing. Use the bundled script where possible, keep FELO_API_BASE unset unless you fully trust the destination, avoid extracting private or tokenized URLs, and treat FELO_API_KEY as a credential that should be scoped, protected, and rotated if exposed. Avoid the optional global npm install unless you have verified the exact package version and provenance.

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)

T09 · Insecure Skill Coding Practices

Error
Location
scripts/run_web_extract.mjs:161
Finding
Bearer API Credential Can Be Redirected to an Arbitrary Endpoint## Vulnerability Details **File Location**: `scripts/run_web_extract.mjs:161, 177-190` **Vulnerability Type**: Unrestricted credential-bearing endpoint override **Risk Level**: High **Vulnerable Code**: ```javascript const apiBase = (process.env.FELO_API_BASE?.trim() || DEFAULT_API_BASE).replace(/\/$/, ''); const shortUrl = args.url.length > 45 ? args.url.slice(0, 42) + '...' : args.url; const spinnerId = startSpinner(`Fetching ${shortUrl}`); try { const body = { url: args.url, output_format: args.format, crawl_mode: args.crawlMode, with_readability: args.readability, timeout: args.timeoutMs, }; if (args.targetSelector) body.target_selector = args.targetSelector; if (args.waitForSelector) body.wait_for_selector = args.waitForSelector; const payload = await fetchJson( `${apiBase}/v2/web/extract`, { method: 'POST', headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json', }, ``` The corresponding endpoint override is documented in `SKILL.md:130`: ```markdown - **Base URL**: `https://openapi.felo.ai`. Override with `FELO_API_BASE` env if needed. ``` ### Technical Analysis The script reads `FELO_API_BASE` from the process environment without validating its URL scheme, hostname, port, or trust relationship. It then sends the value of `FELO_API_KEY` as a bearer credential to the resulting endpoint. The default network request to Felo is necessary for the declared hosted webpage-extraction functionality. The unrestricted endpoint override is not necessary for the standard workflow and exceeds the minimum trust boundary required by that functionality. It permits credential-bearing requests to arbitrary HTTPS hosts and even plaintext HTTP endpoints. Although exploitation requires influence over the process environment or launch configuration, such influence ma ...[truncated 1493 chars]
Remediation
## Remediation Suggestions 1. Remove `FELO_API_BASE` support if custom service endpoints are not an essential requirement. 2. If an override is required, parse it with the standard `URL` API and reject malformed values. 3. Require the `https:` scheme and reject plaintext HTTP, embedded credentials, fragments, and unexpected ports. 4. Restrict credential-bearing requests to an explicit hostname allowlist, preferably only `openapi.felo.ai`. 5. Do not forward the production `FELO_API_KEY` to custom endpoints. Require a distinct environment variable for non-Felo services. 6. Make custom endpoint use an explicit command-line opt-in and display the destination hostname before sending credentials. 7. Document that requested URLs and extraction parameters are sent to the remote provider. 8. Use narrowly scoped, revocable API keys and rotate any key that may have been sent to an untrusted endpoint.

T08 · Insecure Dependencies

Warning
Location
SKILL.md:52
Finding
Documentation Recommends Installing an Unpinned Global npm Package## Vulnerability Details **File Location**: `SKILL.md:52-56` and `README.md:46-50` **Vulnerability Type**: Unpinned and unaudited global dependency installation **Risk Level**: Medium **Vulnerable Documentation in `SKILL.md`**: ```markdown **Packaged CLI** (after `npm install -g felo-ai`): same options, with short forms allowed: ```bash felo web-extract -u "https://example.com" [options] ``` ``` **Vulnerable Documentation in `README.md`**: ```markdown After `npm install -g felo-ai`, you can run: ```bash felo web-extract --url "https://example.com" ``` ``` ### Technical Analysis The installation command does not pin a reviewed package version, provide an integrity hash, reference a lockfile, or specify verified package provenance. It therefore installs whichever release is current when the command is executed. A global npm installation can place executable files in shared command locations and may execute package lifecycle scripts during installation. The `felo-ai` package source is not included in this project, so its behavior could not be audited as part of the supplied artifact. This finding does not establish that the current package is malicious. The risk arises because the instructions create an unnecessary mutable supply-chain dependency when an in-repository script is already available. ### Attack Path 1. The npm package, publisher account, release process, or dependency chain is compromised, or a future release introduces unsafe behavior. 2. A user follows the documented `npm install -g felo-ai` command. 3. npm retrieves the latest available package rather than a specifically reviewed version. 4. Package installation or lifecycle code executes with the privileges of the user running npm and installs a globally accessible command. 5. Malicious code can inspect user-accessible files and environment variables, including `FELO_API_KEY`, or alter subsequent CLI behavior. 6. The user later inv ...[truncated 794 chars]
Remediation
## Remediation Suggestions 1. Prefer the bundled, reviewed `scripts/run_web_extract.mjs` implementation and remove global installation from the primary instructions. 2. If the external CLI remains supported, pin an explicitly reviewed package version rather than installing the latest release. 3. Provide verifiable package provenance and integrity information. 4. Use a project-local dependency with a committed lockfile instead of a global installation. 5. Review the package's lifecycle scripts and transitive dependencies before recommending it. 6. Avoid running npm installation commands with administrative privileges. 7. Document that the packaged CLI is external to this repository and was not part of the bundled script's security review. 8. Establish a release-review process before updating the documented pinned version.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (5)

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The README instructs users to send arbitrary URLs to the Felo Web Extract API but does not disclose that both the requested URL and potentially the fetched page content are transmitted to a third-party service. This can cause unintentional disclosure of sensitive internal URLs, private documents, or regulated data if users assume extraction happens locally.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill invokes environment-variable access and outbound network access but does not declare any tool scope or permission boundaries. That omission can cause the agent runtime or users to underestimate what the skill is capable of, increasing the risk of unintended secret use or external data transmission.

Missing User Warnings

Medium
Confidence
93% confidence
Finding
The skill encourages sending arbitrary user-supplied URLs and extracted page content to a third-party API but does not clearly warn that requested URLs, page contents, and possibly sensitive query parameters will be transmitted off-platform. In practice this can expose private intranet URLs, tokenized links, or confidential page contents to the external provider without informed user consent.

External Transmission

Medium
Category
Data Exfiltration
Content
node felo-web-extract/scripts/run_web_extract.mjs --url "https://example.com" --target-selector "#content" --format text
```

### Option B: Call API with curl

```bash
curl -X POST "https://openapi.felo.ai/v2/web/extract" \
Confidence
91% confidence
Finding
This skill explicitly posts user-provided URLs to an external service, which is a genuine external transmission path. While that is core to the feature rather than obviously malicious behavior, it remains security-relevant because it can disclose sensitive targets and retrieved content to a third party.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The README tells users to place a live API key in an environment variable but provides no guidance on secure handling, storage, or avoiding accidental disclosure. While environment variables are common, omitting basic precautions increases the chance of credential leakage through shell history, screenshots, shared terminals, logs, or committed config files.

Static analysis

Detected: suspicious.env_credential_access

Environment variable access combined with network send.

Critical
Code
suspicious.env_credential_access
Location
scripts/run_web_extract.mjs:164