Back to skill

Security audit

RedditRank

Security checks for vulnerabilities and agentic risk

Overview

The skill mostly matches its Reddit marketing purpose, but it needs review because it stores and displays API keys insecurely and sends user/product data to an external service.

Review before installing. Use it only if you are comfortable sending your email, API key, product descriptions, URLs, and Reddit thread context to the RedditRank service. Run setup as a normal user, avoid sharing setup logs or screenshots because they may contain the full API key, and consider manually restricting ~/.redditrank/config.json permissions after setup. Generated replies should be reviewed and posted transparently by the user, not used for covert or spammy promotion.

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

Warning
Location
redditrank_tui/config.py:29
Finding
API Key Persisted Without Explicit Restrictive File Permissions<![CDATA[ ## Vulnerability Details **File Location**: `redditrank_tui/config.py:29-39`; `setup.sh:190-195` **Vulnerability Type**: Plaintext credential storage with permissions inherited from the process umask **Risk Level**: Medium ### Vulnerable Code `redditrank_tui/config.py:29-39`: ```python def save_api_key(key: str): """Save API key to config file.""" CONFIG_DIR.mkdir(parents=True, exist_ok=True) data = {} if CONFIG_FILE.exists(): try: data = json.loads(CONFIG_FILE.read_text()) except Exception: pass data["api_key"] = key CONFIG_FILE.write_text(json.dumps(data, indent=2)) ``` `setup.sh:190-195`: ```bash mkdir -p "$RR_DIR" if $HAS_JQ; then echo "{\"api_key\": \"$API_KEY\"}" | jq . > "$RR_CONFIG" else echo "{\"api_key\": \"$API_KEY\"}" > "$RR_CONFIG" fi ``` The setup script also exposes the complete credential in terminal output at `setup.sh:185` and `setup.sh:200`: ```bash echo -e " Key: ${CYAN}$API_KEY${NC}" ... echo -e " ${DIM}export REDDITRANK_API_KEY=$API_KEY${NC}" ``` ### Technical Analysis The application stores the RedditRank API key as plaintext in `~/.redditrank/config.json`. Neither the Python implementation nor the shell setup script explicitly creates the configuration directory with mode `0700` or the credential file with mode `0600`. Consequently, access permissions depend on the user's current umask and any pre-existing directory or file permissions. Under a permissive umask or an incorrectly permissioned existing configuration path, another local user may be able to read the API key. Printing the complete key to the terminal additionally exposes it to terminal recording, screenshots, copied logs, or surrounding automation that captures standard output. ### Attack Path 1. A user runs `setup.sh` or completes TUI onboarding, causing the API key to be written to `~/.redditrank/config.json`. 2. The process runs under a permissive umask, or the configuration direct ...[truncated 925 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Create the configuration directory with owner-only permissions: ```python CONFIG_DIR.mkdir(mode=0o700, parents=True, exist_ok=True) os.chmod(CONFIG_DIR, 0o700) ``` 2. Write the credential atomically to a temporary file opened with mode `0600`, then replace the destination: ```python import os import tempfile CONFIG_DIR.mkdir(mode=0o700, parents=True, exist_ok=True) os.chmod(CONFIG_DIR, 0o700) fd, temp_path = tempfile.mkstemp(dir=CONFIG_DIR, prefix=".config-", text=True) try: os.fchmod(fd, 0o600) with os.fdopen(fd, "w") as handle: json.dump(data, handle, indent=2) handle.flush() os.fsync(handle.fileno()) os.replace(temp_path, CONFIG_FILE) os.chmod(CONFIG_FILE, 0o600) finally: if os.path.exists(temp_path): os.unlink(temp_path) ``` 3. Harden the shell implementation before writing: ```bash umask 077 install -d -m 700 "$RR_DIR" printf '%s\n' "{\"api_key\": \"$API_KEY\"}" > "$RR_CONFIG" chmod 600 "$RR_CONFIG" ``` 4. Do not display the complete API key after creation. Show only a masked value and the configuration path. 5. Prefer an operating-system credential store or keyring where available. 6. On startup, detect and warn about configuration files that are readable or writable by group or other users. ]]>

T08 · Insecure Dependencies

Note
Location
requirements.txt:1
Finding
Dependency Installation Uses Mutable Version Ranges Without Integrity Hashes<![CDATA[ ## Vulnerability Details **File Location**: `requirements.txt:1-3`; `setup.sh:62-63` **Vulnerability Type**: Unlocked and unhashed third-party dependency installation **Risk Level**: Low ### Vulnerable Code `requirements.txt:1-3`: ```text textual>=1.0.0,<2.0.0 httpx>=0.27.0,<1.0.0 pyperclip>=1.8.0,<2.0.0 ``` `setup.sh:62-63`: ```bash pip install -q --upgrade pip 2>/dev/null || true pip install -q -r "$SCRIPT_DIR/requirements.txt" ``` ### Technical Analysis The setup process installs packages from a package index using broad version ranges. Exact direct and transitive versions are not locked, and package artifacts are not protected by expected cryptographic hashes. As a result, identical project source can install different dependency versions at different times. If an upstream maintainer account, package release, package index, or dependency resolution path is compromised, a malicious package version satisfying the declared range could be selected during setup. The dynamic pip upgrade adds another mutable package retrieval operation before application dependencies are installed. This is a supply-chain hardening issue; the audit found no evidence that the currently named packages are typosquatted or intentionally malicious. ### Attack Path 1. An attacker compromises an upstream package publisher, relevant dependency, or configured Python package index. 2. The attacker publishes or serves a malicious package version that satisfies one of the declared ranges. 3. A user runs `bash setup.sh`. 4. Pip resolves the mutable range to the attacker-controlled release and installs it without checking a project-supplied expected hash. 5. Malicious package installation or import-time code executes with the privileges of the user running setup. Successful exploitation depends on an upstream or package-index compromise, or a hostile package-index configuration. The code does not independently retrieve and execute an explicit malicious payload. ### Impact A ...[truncated 637 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Generate a reviewed lock file containing exact direct and transitive dependency versions. 2. Record cryptographic hashes for every permitted distribution and enforce them during installation: ```bash python -m pip install --require-hashes -r requirements.lock ``` 3. Use a controlled dependency update process that includes: - Release-note review. - Vulnerability scanning. - Package provenance review. - Automated tests. - Explicit lock-file approval. 4. Avoid upgrading pip implicitly during routine setup. Pin and document a tested installer version, or perform installer upgrades as a separate, explicit maintenance operation. 5. Use the intended package index explicitly and avoid untrusted extra indexes. 6. Document that setup must run as an unprivileged user rather than with `sudo` or administrator rights. ]]>
Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
Findings (19)

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description promises a marketing workflow: discover Reddit threads ranking on Google and generate contextual replies. This code chunk does none of that. Its primary purpose is a settings UI. It reads and masks an API key, shows API base information, calls backend methods to retrieve usage/tier and validate the key, and can open a pricing page in the browser. Those behaviors are materially different from the declared functionality, so this is a clear description-behavior mismatch.

Credential Access

High
Category
Privilege Escalation
Content
TIER=$(parse_json "$VERIFY_RESP" "tier")

if [ -z "$API_KEY" ]; then
  echo -e "${RED}  Failed to extract API key from response.${NC}"
  echo "  Raw response: $VERIFY_RESP"
  exit 1
fi
Confidence
81% confidence
Finding
On parse failure, the script prints the full raw verification response, which may include the issued API key or other sensitive account data. Error paths are commonly overlooked, but they can leak secrets into terminal logs, CI logs, support screenshots, or captured setup transcripts just as easily as normal output.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill requests access patterns that imply network, shell, environment, and file capabilities, but it does not declare any explicit tool scope restrictions. That leaves the agent with broader-than-necessary authority, increasing the chance of unintended command execution, local file access, or secret exposure during normal use or prompt-injection scenarios.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The skill explicitly sends product descriptions, URLs, thread contents, and comments to an external service, but it does not provide a clear privacy or data-sharing warning. Users may unknowingly transmit sensitive business information, customer context, or proprietary messaging data to a third party, creating confidentiality and compliance risks.

Vague Triggers

Medium
Confidence
87% confidence
Finding
The workflow and example prompts are broad enough to activate on generic marketing or traffic-growth requests, which can cause the agent to invoke this skill outside clearly intended user consent boundaries. In practice, overly broad routing increases the risk of unnecessary data transmission to the third-party API and can steer users into spammy or manipulative outreach behavior without a precise opt-in.

Missing User Warnings

Medium
Confidence
85% confidence
Finding
This code sends account usage, session history, draft history, email addresses, verification codes, API tokens, thread URLs, product URLs, and product descriptions to remote endpoints via HTTP requests and SSE POST streams. While network access is the purpose of an API client, this file provides no print/log/comment/docstring disclosure that user-provided or credential data will be transmitted off-system.

Missing User Warnings

Medium
Confidence
81% confidence
Finding
This code persists a credential via save_api_key(key), which is a sensitive operation involving credential storage. In this file there is no confirmation prompt, user-facing notice, or explanatory comment/docstring telling the user that their API key will be stored locally before the write occurs.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The code persists the API key in a plaintext JSON file under the user's home directory without setting restrictive file permissions or providing any warning about local secret storage. If the host is multi-user, compromised by other low-privilege processes, or included in backups/log collection, the key can be exposed and abused to access the associated service.

Ssd 2

Medium
Confidence
88% confidence
Finding
The onboarding text explicitly promotes generating 'stealth replies that drive traffic,' which is evasion-oriented language encouraging deceptive promotional conduct. In the context of this skill, that messaging materially increases risk because it frames the tool's intended use as covert manipulation, potentially facilitating spam, social engineering, or policy-violating campaigns.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The registration flow collects an email address and transmits it to a remote API without any notice, consent language, or explanation of how the data will be used. While sending an email for account creation is functionally expected, the lack of transparency increases privacy risk and can violate user expectations or policy requirements, especially in a first-run onboarding context.

External Transmission

Medium
Category
Data Exfiltration
Content
if [ -n "$EXISTING_KEY" ]; then
  echo -e "  Found existing API key. Validating..."
  VALIDATE=$(curl -s -X POST "$API_BASE/auth/validate" \
    -H "Content-Type: application/json" \
    -d "{\"token\": \"$EXISTING_KEY\"}" 2>/dev/null || echo "{}")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
echo ""
echo -e "  Sending verification code to ${CYAN}$EMAIL${NC}..."

REGISTER_RESP=$(curl -s -X POST "$API_BASE/auth/register" \
  -H "Content-Type: application/json" \
  -d "{\"email\": \"$EMAIL\"}")
Confidence
70% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
96% confidence
Finding
The script prints the newly issued API key directly to the terminal and suggests exporting it on the command line, which can expose the credential through terminal scrollback, shell history, screen sharing, logs, or process inspection. This is not necessary for normal setup because the key is already being written to a config file, so the extra disclosure increases the chance of accidental credential leakage.

Missing User Warnings

Low
Confidence
80% confidence
Finding
This code performs HTTP/API operations via `api.get_usage()` and `api.list_sessions()` to retrieve account usage and recent session information, but the file contains no confirmation prompt or explicit user-facing notice that data will be transmitted or retrieved over the network. For code files, network operations can warrant a finding when there is no visible disclosure in code comments, docstrings, or UI messaging and the warning is not otherwise evident here.

Missing User Warnings

Low
Confidence
86% confidence
Finding
This code transmits the user's entered URL or product description via `api.discover_stream(**kwargs)`, which is a network/API operation. In this file there is no confirmation prompt, explicit notice, or comment/docstring warning the user that their input will be sent to a remote service.

Missing User Warnings

Low
Confidence
78% confidence
Finding
The code copies the generated draft to the system clipboard, which is a user-data-affecting write operation. While it shows a notification after success, there is no prior warning, comment, or docstring disclosing that activating this action will place content on the system clipboard.

Missing User Warnings

Low
Confidence
82% confidence
Finding
The screen automatically calls `api.list_sessions(limit=50)` on mount, which transmits data to or retrieves data from a remote service. In this file there is no confirmation prompt, user-facing notice, or comment/docstring explaining that opening the history screen will contact the backend.

Description-Behavior Mismatch

Low
Confidence
92% confidence
Finding
The user-facing description in the onboarding header claims content-generation and traffic-driving behavior, while the actual code here is limited to credential collection, key validation, and registration. This is a semantic mismatch between what the screen says the skill does and what this file actually performs.

Unverifiable Dependency: httpx has 2 known advisory(ies) (CVE-2021-41945 (Improper Input Validation in httpx); CVE-2021-41945 (Encode OSS httpx <=1.0.0.beta0 is affected by improper input validation in `http)), but the manifest does not pin a version, so it is unknown whether the installed release is affected

Low
Category
Supply Chain
Confidence
82% confidence
Finding
The dependency specification allows any httpx version from 0.27.0 up to, but not including, 1.0.0, and it does not pin an exact release. Because the finding references known advisories in some httpx versions, this creates supply-chain uncertainty: the resolved package may vary by install time and environment, making it hard to verify whether a vulnerable release is installed.

Static analysis

No suspicious patterns detected.