T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/setup-server.sh:97- Finding
Docker Setup Exposes an Unauthenticated Email-Control Endpoint on All Network Interfaces
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This appears to be a real email-management skill, but its Docker and HTTP setup can expose powerful mailbox access too broadly and should be reviewed before installation.
Review this carefully before installing. Use only a trusted server, prefer read-only mailbox permissions, avoid enabling send/delete/move unless needed, keep the .env file secret, bind Docker to localhost or firewall the port, require HTTPS/authentication for any remote server, and pin or independently verify the Docker image before passing it credentials.
scripts/setup-server.sh:97Docker Setup Exposes an Unauthenticated Email-Control Endpoint on All Network Interfaces
scripts/rnoe-mail.py:36Remote Email Operations and Sensitive Message Content Can Be Transmitted over Plaintext HTTP
scripts/setup-server.sh:6Mutable Docker Image Is Pulled and Executed with Access to Mail Credentials
The documentation claims secure email operations and prompt-injection protection while also instructing the agent to deploy/manage a Docker service, read config paths, and perform health checks. This broader operational behavior materially changes the risk profile and can cause an agent to take privileged local actions that are not obvious from the declared purpose.
The documentation claims secure email operations and prompt-injection protection while also instructing the agent to deploy/manage a Docker service, read config paths, and perform health checks. This broader operational behavior materially changes the risk profile and can cause an agent to take privileged local actions that are not obvious from the declared purpose.
The workflow relies on an .env file containing account secrets and instructs the agent to pass its path into server-start commands. Even without directly printing secrets, handling credential-bearing files in agent workflows raises the risk of accidental exposure, misuse, or over-collection if the agent later inspects or transmits those files.
scripts/setup-server.sh --config ~/.config/read-no-evil-mcp/config.yaml \
--env-file ~/.config/read-no-evil-mcp/.env
Documenting server startup with a referenced .env file normalizes agent interaction with credential material during infrastructure operations. In the context of a skill that also uses shell and file capabilities, this increases the chance that credentials are exposed through logs, debugging, or unintended file access.
# Start a Docker container (all flags required, no prompts)
scripts/setup-server.sh --config ~/.config/read-no-evil-mcp/config.yaml \
--env-file ~/.config/read-no-evil-mcp/.env
# Custom port and container name
scripts/setup-server.sh --config /path/to/config.yaml \
The custom startup example continues the pattern of agent-mediated use of plaintext credential files. Because the skill is framed as secure, users may underestimate the sensitivity of these setup steps and allow broader access than appropriate.
scripts/setup-server.sh --config /path/to/config.yaml
--env-file /path/to/.env --port 9000 --name my-rnoe
## CLI Commands
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
def create_env_file(config_path, account_ids):
"""Create .env file with password placeholders. Preserves existing values."""
env_path = os.path.join(os.path.dirname(config_path), ".env")
existing_vars = {}
if os.path.exists(env_path):
Skill modifies its own code, configuration, or behavior at runtime. Self-modification enables an agent to escalate privileges, disable safety constraints, or install persistent backdoors.
# create
create_parser = subparsers.add_parser("create", help="Create config skeleton")
create_parser.add_argument("--threshold", type=float, default=0.5, help="Global protection threshold (default: 0.5)")
create_parser.add_argument("--force", action="store_true", help="Overwrite existing config")
# add
add_parser = subparsers.add_parser("add", help="Add an account")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
echo
echo "Flags:"
echo " --config Config file path (required)"
echo " --env-file .env file with credentials (required)"
echo " --port Host port to bind (default: 8000)"
echo " --name Docker container name (default: rnoe-mcp)"
exit 0
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
echo
echo "Flags:"
echo " --config Config file path (required)"
echo " --env-file .env file with credentials (required)"
echo " --port Host port to bind (default: 8000)"
echo " --name Docker container name (default: rnoe-mcp)"
exit 0
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
echo
echo "Flags:"
echo " --config Config file path (required)"
echo " --env-file .env file with credentials (required)"
echo " --port Host port to bind (default: 8000)"
echo " --name Docker container name (default: rnoe-mcp)"
exit 0
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
echo
echo "Flags:"
echo " --config Config file path (required)"
echo " --env-file .env file with credentials (required)"
echo " --port Host port to bind (default: 8000)"
echo " --name Docker container name (default: rnoe-mcp)"
exit 0
This block reads credentials from a user-supplied .env file and passes them into the container as environment variables. In containerized environments, secrets in environment variables can be exposed through process inspection, container metadata, debugging tools, crash reports, or overly broad access to Docker APIs; in this skill context, those credentials are especially sensitive because they grant email account access.
echo "Pulling $IMAGE ..."
docker pull "$IMAGE"
# --- Load credentials from .env ---
env_args=()
while IFS= read -r line || [ -n "$line" ]; do
line="${line%%#*}" # strip comments
The skill requests or implies powerful capabilities (environment access, file writes, MCP/network access, and shell execution) without declaring an explicit tool scope or permission boundary. This creates unnecessary ambiguity for an agent/runtime and increases the risk of over-privileged execution, especially because the documented workflow includes local config creation, Docker setup, and server interaction.
The instructions create persistent local configuration and an environment file storing account setup information across sessions. Persistent state is not inherently malicious, but in an agent context it can silently extend access to email resources beyond the immediate task and enlarge the blast radius of later compromise or misuse.
setup-config.py listsetup-config.py create
setup-config.py add --email user@example.com --host imap.example.com --create-env
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
**Do NOT** run `setup-config.py show` — it displays config details the user may not intend to share with the agent. If debugging is needed, tell the user to run it themselves.
**Do NOT** run `setup-config.py create --force` if config already exists without asking the user first.
## Config Commands
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.
**Do NOT** run `setup-config.py show` — it displays config details the user may not intend to share with the agent. If debugging is needed, tell the user to run it themselves.
**Do NOT** run `setup-config.py create --force` if config already exists without asking the user first.
## Config Commands
The skill documents destructive operations like moving and deleting emails without requiring an explicit confirmation step immediately before execution. In an agent setting, this increases the chance of accidental or prompt-induced destructive actions against user data.
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
# --- Health check ---
echo "Waiting for server to start..."
for i in $(seq 1 30); do
if curl -sf "http://localhost:${PORT}/mcp" -X POST \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"setup","version":"0.1.0"}}}' \
>/dev/null 2>&1; then
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.
# Merge back global options captured in the first pass (before the subcommand)
for attr in ("server", "account", "folder"):
first_pass_val = getattr(global_args, attr)
if first_pass_val != global_parser.get_default(attr):
setattr(args, attr, first_pass_val)
No suspicious patterns detected.