T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/main_flightmapify.py:73- Finding
Arbitrary Termination of Unrelated Processes During Port Conflict Resolution
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
FlightMapify appears to be a real flight-map tool, but it includes risky local process, server, workspace, and credential handling that users should review before installing.
Review this skill carefully before installing. Use it only in a constrained workspace, avoid running it with elevated privileges, do not point it at ports used by important services, and avoid exposing sensitive workspace files while its HTTP server is running. Prefer a version that removes automatic kill -9 behavior, serves only generated map assets, pins the FlyAI dependency, and passes only the required FlyAI credential to subprocesses.
scripts/main_flightmapify.py:73Arbitrary Termination of Unrelated Processes During Port Conflict Resolution
scripts/main_flightmapify.py:124Entire OpenClaw Workspace Exposed Through a General-Purpose HTTP File Server
scripts/main_flightmapify.py:164HTML and DOM Injection Through Unescaped CLI and Flight Provider Data
SKILL.md:176Unpinned Global Installation and Over-Privileged Execution of the FlyAI CLI
The skill behavior reportedly includes killing processes on occupied ports via lsof/kill -9, starting background servers, and writing into the workspace, none of which are transparently conveyed by the advertised purpose. Arbitrary process termination is especially dangerous because it can disrupt unrelated local applications or developer tooling and may be abused as a destructive side effect.
The skill behavior reportedly includes killing processes on occupied ports via lsof/kill -9, starting background servers, and writing into the workspace, none of which are transparently conveyed by the advertised purpose. Arbitrary process termination is especially dangerous because it can disrupt unrelated local applications or developer tooling and may be abused as a destructive side effect.
Support for .env files and multiple credential sources increases the chance that API keys are loaded from local secrets stores without clear minimization or isolation. In combination with shell execution and local config access, this broadens opportunities for accidental credential exposure, misuse, or propagation into logs and subprocess environments.
- ✅ Implemented OpenClaw skill configuration with user-configurable API Key
- ✅ Added automatic fallback to default FlyAI API Key when not configured
- ✅ Updated server manager to use Flask-based server
- ✅ Enhanced server management with .env file support
- ✅ Fixed API Key configuration issues (trial limit errors)
- ✅ Improved error handling and user feedback
- ✅ Removed flight-search-server-simple.py (now using Flask-based server exclusively)
Code enumerates, copies, or searches environment variables for secrets. Bulk environment access can collect credentials unrelated to the skill's stated purpose.
"""
try:
# Set FlyAI API key as environment variable
env = os.environ.copy()
# Explicitly set home directory for config access
env['HOME'] = os.path.expanduser('~')
The skill includes logic to identify and forcibly terminate any local process that happens to occupy its preferred port, even though flight map generation does not require killing unrelated software. In skill context, this is more dangerous because users reasonably expect a travel tool, not local process control with destructive behavior.
The code kills the process on the occupied port automatically and only prints a status message, without obtaining consent or warning about the consequences. This makes accidental disruption very likely and increases the risk of stopping unrelated development tools, databases, or user applications without notice.
Accessing a .env file in a parent directory is a credential-access pattern because such files commonly contain API keys and other secrets. In this skill context, reading those secrets is only justified if narrowly required, and here they are later forwarded wholesale to a subprocess, which makes the handling more dangerous.
return False, default_port
try:
# Load environment variables from .env file
env = os.environ.copy()
env_path = os.path.join(os.path.dirname(self.script_dir), '.env')
if os.path.exists(env_path):
Copying the full parent environment into a child process can expose tokens, API keys, and system secrets to code that does not need them. In a skill that starts another Python service, this unnecessarily expands access to sensitive data and increases the consequences if the child process is compromised or behaves unexpectedly.
try:
# Load environment variables from .env file
env = os.environ.copy()
env_path = os.path.join(os.path.dirname(self.script_dir), '.env')
if os.path.exists(env_path):
with open(env_path, 'r') as f:
Opening and parsing the .env file directly confirms credential access behavior and contributes to unnecessary secret propagation into the child server process. This is especially risky because the manifest describes flight search and mapping, not generalized secret handling or process orchestration, so the secret exposure is broader than the user-facing purpose suggests.
try:
# Load environment variables from .env file
env = os.environ.copy()
env_path = os.path.join(os.path.dirname(self.script_dir), '.env')
if os.path.exists(env_path):
with open(env_path, 'r') as f:
for line in f:
The skill documentation indicates capabilities to read environment variables, access files, use the network, and invoke shell commands, yet it declares no explicit permission or allowed-tools scope. This creates an over-privileged, poorly bounded execution model where users and platforms cannot easily assess or constrain what the skill may access.
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.
---
name: flightmapify
version: 1.4.6
description: Find cheapest flights and create interactive flight route maps with real-time flight search.
author: rudy2steiner
license: MIT
tags: [flights, maps, routing, flyai, travel, interactive]
Code scans file system directories looking for sensitive files. This could be reconnaissance for credential theft.
Verify file locations:
ls -la ~/.openclaw/workspace/*.html
Check port availability:
This file contains multiple user-visible strings in Chinese, such as the airline/journey label and booking CTA, with no indication that the user can choose a language or that the skill is region-specific. That creates a natural-language policy concern because the interface effectively enforces one locale for all users.
The code sends itinerary search data to an HTTP endpoint on localhost, which means the request is not protected by transport security. In environments where localhost is proxied, tunneled, container-bridged, or exposed through a local companion service, an attacker or malicious local process could observe or tamper with travel query data, and the UI gives users no warning that sensitive travel details are being transmitted insecurely.
User-facing labels and messages are hardcoded in Chinese, and the map configuration explicitly sets lang: 'zh_cn'. This enforces a specific locale without opt-in or explanation, which matches the language/locale policy violation criteria.
The UI opens flight.bookingUrl from backend-provided data directly with window.open(..., '_blank') and performs no allowlisting, scheme validation, or user warning. If the local backend is compromised or returns untrusted data, users can be redirected to phishing pages or dangerous destinations outside the expected flight-search workflow.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
try:
# Execute the main script
result = subprocess.run(cmd)
sys.exit(result.returncode)
except KeyboardInterrupt:
print("\nOperation cancelled by user", file=sys.stderr)
The server reads API credentials from the user's environment and ~/.flyai/config.json even though the HTTP endpoint only exposes flight search functionality. This broad credential access increases exposure of secrets to the skill runtime and any downstream subprocesses, violating least-privilege and creating unnecessary secret-handling risk.
The code silently harvests a FlyAI API key from environment variables or a config file in the user's home directory without any user-facing disclosure or consent flow. Even if used only for flight search, undisclosed secret access is dangerous because it normalizes opaque credential use and could expose private tokens to logs, subprocesses, or future code changes.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
logger.info(f"Running direct flight search: {' '.join(cmd_direct)}")
result_direct = subprocess.run(
cmd_direct,
capture_output=True,
text=True,
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
logger.info(f"Running connecting flight search: {' '.join(cmd_connecting)}")
result_connecting = subprocess.run(
cmd_connecting,
capture_output=True,
text=True,
The code hard-codes Chinese-language values for user-visible fields such as journey type (for example, 直达 and 中转). This imposes a specific language on all users without offering any locale choice or documenting a justified region-specific constraint.
subprocess module calls execute external commands. Without careful input validation, this enables command injection.
"""Kill the process using the specified port"""
try:
# Find the process using the port
result = subprocess.run(
['lsof', '-ti', f':{port}'],
capture_output=True,
text=True
This code forcefully kills whatever process is using the requested port via kill -9, without verifying ownership, purpose, or whether the process belongs to the user’s current task. That can terminate unrelated applications or developer services and creates both denial-of-service and data-loss risk, especially because SIGKILL prevents graceful shutdown.
for pid in pids:
if pid:
print(f"Killing process {pid} on port {port}...")
subprocess.run(['kill', '-9', pid], capture_output=True)
return True
except Exception as e:
print(f"Error killing process on port {port}: {e}")
Starting a generic HTTP server from the detected workspace exposes a broader directory tree than needed for the advertised function of generating and viewing a flight map. Since workspace discovery includes environment-based and fallback paths, the served content may unintentionally include sensitive or unrelated local files.
No suspicious patterns detected.