Back to skill

Security audit

redis-tools

Security checks for vulnerabilities and agentic risk

Overview

This Redis helper mostly does what it says, but it handles Redis passwords in a way that can expose them locally.

Review before installing if you may connect to real or production Redis instances. Avoid passing sensitive Redis passwords on the command line; prefer a temporary low-privilege Redis ACL user, non-production endpoints, or a safer authentication method outside shell history and process arguments.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (1)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/script.sh:474
Finding

Redis Credentials Exposed Through Positional Arguments and Process Command Lines

Content
View full analysis

Vulnerability Details

File Location: scripts/script.sh, lines 474–482; invoked at lines 499 and 562
Vulnerability Type: Insecure credential handling
Risk Level: Medium

The script accepts the Redis password as a positional command-line argument and incorporates it into a command string using the redis-cli -a option.

bash
build_redis_cmd() {
  local host="$1"
  local port="$2"
  local pass="$3"
  local cmd="redis-cli -h $host -p $port"
  if [[ -n "$pass" ]]; then
    cmd="$cmd -a $pass --no-auth-warning"
  fi
  echo "$cmd"
}

The generated string is subsequently assigned and executed in both connection-testing and monitoring operations:

bash
RCMD="$(build_redis_cmd "$host" "$port" "$pass")"

# Test PING
PONG="$($RCMD PING 2>&1 || true)"
bash
RCMD="$(build_redis_cmd "$host" "$port" "$pass")"

# Test connection first
PONG="$($RCMD PING 2>&1 || true)"

Technical Analysis

Supplying a secret as a positional argument exposes it in multiple places:

  1. The original invocation, such as bash script.sh test host 6379 password, may be retained in the user's shell history.
  2. The password is passed to redis-cli using -a, making it part of the child process's argument vector. Depending on operating-system process visibility and hardening settings, other local users or monitoring tools may inspect it while the command is running.
  3. The command is assembled as a scalar string and executed through unquoted expansion. This causes shell word splitting and pathname expansion. Passwords, hostnames, or ports containing whitespace or glob characters may therefore be divided or expanded into unintended arguments.

The use of --no-auth-warning only suppresses the warning emitted by redis-cli; it does not prevent credential disclosure.

Attack Path

  1. A user invokes the connection or monitoring feature with a Redis password: `bash script ...[truncated 1271 chars]
Remediation
View remediation

Remediation Suggestions

  1. Stop accepting passwords as positional command-line arguments. Prompt interactively with input echo disabled or retrieve the secret from an appropriately protected secret manager or file descriptor:

    bash
    read -r -s -p "Redis password: " REDIS_PASSWORD
    echo
    
  2. Pass authentication through REDISCLI_AUTH rather than redis-cli -a, and remove it from the environment immediately after use:

    bash
    redis_cmd=(redis-cli -h "$host" -p "$port")
    
    if [[ -n "$REDIS_PASSWORD" ]]; then
      export REDISCLI_AUTH="$REDIS_PASSWORD"
    fi
    
    pong="$("${redis_cmd[@]}" PING 2>&1 || true)"
    unset REDISCLI_AUTH REDIS_PASSWORD
    

    Environment variables can still be exposed in some environments, so a protected secret source and short variable lifetime remain important.

  3. Construct commands using Bash arrays rather than scalar command strings. Arrays preserve argument boundaries and prevent word splitting and pathname expansion:

    bash
    redis_cmd=(redis-cli -h "$host" -p "$port")
    info="$("${redis_cmd[@]}" INFO server 2>&1 || true)"
    
  4. Validate the port as an integer in the valid TCP port range and reject control characters in endpoint input.

  5. Update SKILL.md and usage output so examples do not encourage entering plaintext passwords directly on the command line.

  6. Recommend Redis ACL users with only the commands and key patterns required for testing or monitoring, reducing the impact of any credential compromise.

Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (6)

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

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

bash
# Debian/Ubuntu
sudo apt install redis-tools

# macOS
brew install redis

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
97% confidence
Finding

The script accepts a Redis password as a positional CLI argument and then passes it via redis-cli -a, which exposes the secret to shell history, process listings, audit logs, and possibly other local users. This is especially risky in multi-user systems, CI environments, or when command invocations are logged.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
75% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

Scanner excerpt · scripts/script.sh (reported line 296)May include surrounding context.

sh
Return the type of a key: string, list, hash, set, zset, stream.

OBJECT ENCODING key
  Show internal encoding (e.g., ziplist, listpack, hashtable).

SCAN cursor [MATCH pattern] [COUNT n] [TYPE type]
  Iteratively scan all keys safely (preferred over KEYS in prod).

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/script.sh (reported line 466)May include surrounding context.

sh
if ! command -v redis-cli &>/dev/null; then
    echo -e "${YELLOW}⚠️  redis-cli not found.${RESET}"
    echo "Install with:"
    echo "  Ubuntu/Debian : sudo apt install redis-tools"
    echo "  macOS         : brew install redis"
    echo "  Alpine        : apk add redis"
    return 1

Sudo/Root Execution

Medium
Category
Privilege Escalation
Confidence
70% confidence
Finding

Commands invoke sudo or root privileges. Verify this elevated access is necessary and justified.

Content

Scanner excerpt · scripts/script.sh (reported line 510)May include surrounding context.

sh
if ! command -v redis-cli &>/dev/null; then
    echo -e "${YELLOW}⚠️  redis-cli not found.${RESET}"
    echo "Install with:"
    echo "  Ubuntu/Debian : sudo apt install redis-tools"
    echo "  macOS         : brew install redis"
    echo "  Alpine        : apk add redis"
    return 1

Intent-Code Divergence

Low
Category
Not specified by scanner
Confidence
91% confidence
Finding

The header comments advertise a 'key monitor', which ordinarily implies observing ongoing key operations or changes. However, the implemented monitor command only runs INFO keyspace, INFO memory, and DBSIZE to print per-DB key counts and average TTLs, with no streaming or live monitoring behavior.

Content

No source excerpt is available for this finding.