Back to skill

Security audit

Fear Greed

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent crypto sentiment widget, but it relies on mutable remote code/data and includes weak validation that users should review before installing.

Install only if you are comfortable with the skill fetching data from the Strykr PRISM endpoint. Prefer the iframe embed over the direct script embed for websites, and pin or self-host reviewed JavaScript if using it in a sensitive page. The shell helper should validate the API value before arithmetic use and should use network timeouts before being trusted in automation.

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/fear-greed.sh:7
Finding
Remote API Data Is Evaluated in Bash Arithmetic Without Validation<![CDATA[ ## Vulnerability Details **File Location**: `scripts/fear-greed.sh`, lines 7-18 **Vulnerability Type**: Arithmetic injection through untrusted remote data **Risk Level**: High ### Vulnerable Code ```bash # Fetch data DATA=$(curl -s "$PRISM_URL/market/fear-greed") VALUE=$(echo "$DATA" | jq -r '.value // 50') LABEL=$(echo "$DATA" | jq -r '.label // "Neutral"') # JSON output if [ "$1" == "--json" ]; then echo "$DATA" exit 0 fi # Calculate bar BAR_FILLED=$((VALUE / 5)) BAR_EMPTY=$((20 - BAR_FILLED)) ``` ### Technical Analysis The script obtains `VALUE` from a remotely supplied JSON response and passes it directly into Bash arithmetic expansion: ```bash BAR_FILLED=$((VALUE / 5)) ``` Bash arithmetic expressions do not provide a strict numeric parsing boundary. Variable values may be recursively interpreted as arithmetic expressions, making untrusted values unsafe unless they are first validated as decimal integers. A malicious response can therefore supply arithmetic syntax rather than a number. Depending on the supplied expression and Bash evaluation behavior, this can result in unexpected expression evaluation, command substitution, or denial of service. The endpoint can also return negative or excessively large numbers. Such values make `BAR_FILLED` or `BAR_EMPTY` invalid for their subsequent use with `seq`, potentially producing errors, excessive output, or resource consumption. The risk is reachable through either compromise of the default PRISM service or configuration of `PRISM_URL` to an attacker-controlled server. The use of `curl -s` also suppresses useful error output and does not fail on HTTP error statuses, while no connection or total timeout is configured. ### Attack Path 1. An attacker gains control of the configured PRISM endpoint, compromises the default service, or causes the user to configure an attacker-controlled `PRISM_URL`. 2. The attacker returns valid JSON whose `.value` field contains a crafted arithmetic expressi ...[truncated 1106 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Require the extracted JSON value to be a JSON number and validate it before arithmetic use: ```bash if ! VALUE=$(jq -er '.value | select(type == "number" and floor == . and . >= 0 and . <= 100)' <<<"$DATA"); then printf '%s\n' "Error: API returned an invalid fear-and-greed value." >&2 exit 1 fi ``` 2. Alternatively, apply a strict shell-level decimal validation and range check: ```bash if [[ ! $VALUE =~ ^[0-9]+$ ]] || (( VALUE < 0 || VALUE > 100 )); then printf '%s\n' "Error: value must be an integer from 0 to 100." >&2 exit 1 fi ``` 3. Convert validated input explicitly as base 10 before using it: ```bash VALUE_NUM=$((10#$VALUE)) BAR_FILLED=$((VALUE_NUM / 5)) BAR_EMPTY=$((20 - BAR_FILLED)) ``` 4. Harden network handling with failure detection and time limits: ```bash if ! DATA=$(curl --fail --silent --show-error \ --connect-timeout 5 --max-time 15 \ "$PRISM_URL/market/fear-greed"); then printf '%s\n' "Error: failed to retrieve market data." >&2 exit 1 fi ``` 5. Validate `.label` as a string and constrain its length before displaying it. Consider using a locally derived label based on the validated numeric value rather than trusting remote display content. 6. Add automated tests covering strings, objects, arrays, null values, negative values, values above 100, extremely large integers, and crafted arithmetic expressions. ]]>

T08 · Insecure Dependencies

Error
Location
SKILL.md:103
Finding
Documentation Recommends Executing Unpinned Third-Party JavaScript<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 103-110 **Vulnerability Type**: Unpinned remote JavaScript dependency without integrity verification **Risk Level**: High ### Vulnerable Code ```html <div id="fear-greed-widget"></div> <script src="https://cdn.strykr.com/fear-greed.js"></script> <script> StrykrWidget.FearGreed({ element: '#fear-greed-widget', theme: 'dark', variant: 'gauge' }); </script> ``` ### Technical Analysis The documented HTML integration loads executable JavaScript directly from a mutable third-party URL. The URL contains no immutable version identifier, and the script element provides no Subresource Integrity hash. As a result, the code reviewed today is not necessarily the code that consumers will execute later. Anyone able to modify the CDN object, deployment pipeline, hosting account, DNS resolution, or origin service could replace `fear-greed.js` while retaining the same URL. Unlike an iframe, a normal external script executes in the security context of the embedding page. It can access page content, browser storage available to that origin, non-`HttpOnly` cookies, DOM input, and authenticated same-origin endpoints accessible to the page. HTTPS protects transport against ordinary interception but does not protect consumers if the authorized upstream asset itself is changed or compromised. ### Attack Path 1. A consumer follows the documented integration instructions and embeds `https://cdn.strykr.com/fear-greed.js`. 2. An attacker compromises the CDN asset, its deployment credentials, the hosting origin, or another component capable of changing the resource served at that URL. 3. The attacker replaces the widget script with malicious JavaScript. 4. A user visits the consumer's website and the browser downloads the modified script. 5. Because no integrity hash or immutable version is specified, the browser accepts and executes the modified resource. 6. The payload runs with the JavaScript ...[truncated 746 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Publish the browser asset under immutable, version-specific URLs, for example: ```html <script src="https://cdn.strykr.com/fear-greed/1.1.1/fear-greed.min.js" integrity="sha384-REPLACE_WITH_PUBLISHED_HASH" crossorigin="anonymous"></script> ``` 2. Generate and publish a Subresource Integrity hash for each immutable release. Never modify an asset after publishing its version and hash. 3. Provide a self-hosting option so consumers can review, pin, and serve the JavaScript from their own controlled infrastructure. 4. Publish source code and reproducible build instructions for the distributed browser artifact so consumers can verify that the CDN file corresponds to the reviewed source. 5. Protect the release pipeline and CDN with least-privilege credentials, multi-factor authentication, restricted deployment identities, audit logs, and release approval controls. 6. Recommend an appropriate Content Security Policy. Where practical, isolate the widget in a sandboxed iframe with only the minimum required sandbox permissions instead of executing third-party JavaScript in the host page's origin. 7. Document update and integrity-hash rotation procedures so consumers deliberately approve new dependency versions rather than automatically receiving mutable code. ]]>
Vulnerability Patterns
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (3)

Tp4

High
Category
MCP Tool Poisoning
Confidence
91% confidence
Finding
The skill is described as a drop-in React/HTML widget, but the documented behavior includes a shell CLI and outbound access to a remote endpoint, creating a meaningful description-behavior mismatch. This is dangerous because reviewers or agents may grant trust based on the benign-looking widget description while the actual usage pattern introduces execution and network-fetch behavior not transparently declared.

Lp3

Medium
Category
MCP Least Privilege
Confidence
85% confidence
Finding
The skill advertises executable shell usage (`./fear-greed.sh`) but declares no `permissions` or `allowed-tools`, which weakens the trust boundary for agent environments that rely on manifest-scoped tool restrictions. In an agent context, undeclared shell capability can lead to unexpected command execution and make downstream review or sandboxing ineffective.

Vague Triggers

Medium
Confidence
89% confidence
Finding
The trigger phrase "crypto sentiment" is broad enough to match many ordinary finance-related prompts, which can cause this skill to activate when the user did not explicitly request it. In an agent ecosystem, over-broad activation increases the chance of unintended tool use, confusing responses, or unnecessary data access/network calls tied to the skill.

Static analysis

No suspicious patterns detected.