Back to skill

Security audit

AEGIS

Security checks for vulnerabilities and agentic risk

Overview

The skill largely matches emergency monitoring, but needs review because it handles credentials and safety-related location data with weak scoping and incomplete disclosure.

Review before installing. Use local-only mode where possible, avoid entering cloud LLM or NewsAPI keys unless you accept plaintext local storage, verify file permissions under ~/.openclaw, and only configure Telegram if you are comfortable sending alert content and monitoring context to that channel. Treat the current country support as UAE/Dubai-focused unless you have reviewed and adapted the profiles and scripts for another location.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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 (4)

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/aegis_onboard.py:113
Finding
API credentials are stored in a plaintext configuration file without enforced restrictive permissions<![CDATA[ ## Vulnerability Details **File Location**: `scripts/aegis_onboard.py:113-153` and `scripts/aegis_onboard.py:168-173` **Vulnerability Type**: Plaintext credential storage and secret disclosure **Risk Level**: Medium ### Vulnerable Code ```python elif llm_choice == "2": llm_endpoint = input(" API base URL (e.g. https://openrouter.ai/api): ").strip() llm_model = input(" Model name (e.g. meta-llama/llama-3-8b-instruct): ").strip() llm_key = input(" API key: ").strip() if llm_endpoint and llm_model: llm_config = {"enabled": True, "provider": "openai", "endpoint": llm_endpoint, "model": llm_model, "api_key": llm_key} else: print(" ⚠️ Missing endpoint or model — LLM disabled.") print("\n🔑 API KEYS (optional — press Enter to skip)") newsapi_key = input(" NewsAPI.org key (free at newsapi.org/register): ").strip() or None config = { "version": "1.1.0", "location": { "country": country, "country_name": country_name, "city": city, "timezone": tz }, "language": lang, "alerts": { "critical_instant": True, "high_batch_minutes": int(batch_min), "medium_digest_hours": int(digest_hrs) }, "briefings": { "morning": morning, "evening": evening }, "scan_interval_minutes": int(interval), "llm": llm_config, "api_keys": {} } if newsapi_key: config["api_keys"]["newsapi"] = newsapi_key # Save CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True) with open(CONFIG_PATH, 'w') as f: json.dump(config, f, indent=2) ``` The same file also prints the complete configuration, including stored credentials: ```python def show_config(): """Display current configuration.""" if not CONFIG_PATH.exists(): print("No AEGIS configuration found. Run setup first.") return with open(CONFIG_PATH) as f: config = json.load(f) print(json.dumps(config, indent=2)) ``` ### Technical Analysis Th ...[truncated 1954 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Store API keys in a dedicated operating-system secret manager or the existing OpenClaw secret service rather than in the general JSON configuration. 2. If file-based storage is unavoidable, create the file atomically with owner-only permissions: ```python import os fd = os.open(CONFIG_PATH, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o600) with os.fdopen(fd, "w") as f: json.dump(config, f, indent=2) ``` 3. Apply and verify mode `0600` on existing configuration files before reading secrets from them. 4. Use `getpass.getpass()` rather than `input()` when collecting credentials. 5. Redact known secret fields in `show_config()`: ```python display = copy.deepcopy(config) display.get("llm", {}).pop("api_key", None) for key in display.get("api_keys", {}): display["api_keys"][key] = "<redacted>" if "telegram" in display: display["telegram"]["bot_token"] = "<redacted>" ``` 6. Document credential storage, rotation, and revocation procedures. ]]>

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/aegis_channel.py:24
Finding
The Telegram publisher loads unrelated credentials from the shared OpenClaw secret store<![CDATA[ ## Vulnerability Details **File Location**: `scripts/aegis_channel.py:24-70` **Vulnerability Type**: Overbroad secret access and environment propagation **Risk Level**: Medium ### Vulnerable Code ```python def _load_openclaw_dotenv(): """Best-effort loader for decrypted secrets from tmpfs. Reads from /run/user/<uid>/openclaw-secrets/.env (decrypted by openclaw-secrets.service) with fallback to ~/.openclaw/.env for development. Also resolves simple ${VAR} and $VAR references. """ import pwd uid = os.getuid() # Primary: tmpfs-decrypted secrets (production) env_path = Path(f'/run/user/{uid}/openclaw-secrets/.env') if not env_path.exists(): # Fallback: direct .env (development only) env_path = Path(Path.home() / '.openclaw' / '.env') if not env_path.exists(): return {} out = {} # first pass: parse for line in env_path.read_text().splitlines(): line = line.strip() if not line or line.startswith('#') or '=' not in line: continue k, v = line.split('=', 1) k = k.strip() v = v.strip().strip('"').strip("'") if k and v: out[k] = v # second pass: resolve ${VAR} and $VAR using values from out and os.environ import re pattern = re.compile(r"\$(?:\{([^}]+)\}|(\w+))") def resolve_val(val, depth=0): if depth>5 or not isinstance(val,str): return val def repl(m): name = m.group(1) or m.group(2) return out.get(name, os.environ.get(name, '')) new = pattern.sub(repl, val) if new==val: return new return resolve_val(new, depth+1) for k in list(out.keys()): out[k]=resolve_val(out[k]) # do not override existing environment variables for k,v in list(out.items()): if k not in os.environ: # put into os.environ temporarily for other code paths os.environ[k]=v return out `` ...[truncated 2037 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse only `AEGIS_BOT_TOKEN` and `AEGIS_CHANNEL_ID`; discard all other entries. 2. Do not copy loaded values into the global `os.environ`. Return the two required values directly to `load_env()`. 3. Use a dedicated AEGIS secret file or secret-manager namespace rather than the shared OpenClaw environment file. 4. Remove the plaintext `~/.openclaw/.env` fallback in production, or require an explicit development-only option before using it. 5. Verify that any file-based secret source is owned by the current user and has mode `0600`. 6. Avoid launching child processes after secret loading. Where child processes are required, provide a minimal explicit environment rather than inheriting `os.environ`. 7. Consider a narrow implementation such as: ```python allowed = {"AEGIS_BOT_TOKEN", "AEGIS_CHANNEL_ID"} result = {} for line in env_path.read_text().splitlines(): if "=" not in line: continue key, value = line.split("=", 1) key = key.strip() if key in allowed: result[key] = value.strip().strip('"').strip("'") return result ``` ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/aegis_scanner.py:396
Finding
NewsAPI credentials are exposed in curl process arguments and request URLs<![CDATA[ ## Vulnerability Details **File Location**: `scripts/aegis_scanner.py:396-410` **Vulnerability Type**: Credential exposure through command-line arguments and URL query strings **Risk Level**: Low ### Vulnerable Code ```python def fetch_json_api(url_template, config, source): """Fetch from JSON API endpoint.""" try: country = config.get("location", {}).get("country", "") city = config.get("location", {}).get("city", "") lang = config.get("language", "en") query = f"{city} {country} conflict security" api_keys = config.get("api_keys", {}) key = api_keys.get(source.get("key_name", ""), "") url = url_template.format(query=query, lang=lang, key=key, country=country, city=city) result = subprocess.run( ["curl", "-sL", "--max-time", "15", "-H", "User-Agent: AEGIS/1.0", url], capture_output=True, text=True, timeout=20 ) ``` The relevant registry template contains the key in the query string: ```json "url_template": "https://newsapi.org/v2/everything?q={query}&sortBy=publishedAt&language={lang}&apiKey={key}" ``` ### Technical Analysis The NewsAPI key is interpolated into the URL and passed to `curl` as a command-line argument. While the process is running, the complete URL may be observable through process listings, process-accounting tools, endpoint monitoring, or diagnostic telemetry. Credentials in URLs are also more likely to be retained by HTTP access logs, proxies, monitoring systems, browser-like diagnostics, or error reports. TLS protects the URL in transit after connection establishment, but it does not prevent local command-line disclosure or logging by the client and server infrastructure. The subprocess call uses an argument array rather than a shell, so this is not a shell-command injection issue. ### Attack Path 1. The user configures a NewsAPI key. 2. A scan reaches the NewsAPI regi ...[truncated 868 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Use Python's standard HTTP client instead of launching `curl`, keeping credentials out of the process argument vector. 2. Use an authorization header if the API provider supports it rather than placing the key in a URL query string. 3. Ensure application, proxy, and server logs redact credential-bearing query parameters. 4. Avoid printing or persisting constructed URLs containing secrets. 5. If `curl` must be retained, supply sensitive configuration through a protected file descriptor or temporary configuration file with mode `0600`, then remove it immediately after use. 6. Rotate the existing NewsAPI credential if process or request logs may already contain it. ]]>

T09 · Insecure Skill Coding Practices

Note
Location
scripts/aegis_scanner.py:551
Finding
LLM bearer tokens are exposed in curl process arguments<![CDATA[ ## Vulnerability Details **File Location**: `scripts/aegis_scanner.py:551-566` **Vulnerability Type**: Bearer-token exposure through command-line arguments **Risk Level**: Low ### Vulnerable Code ```python elif llm_cfg["provider"] == "openai": # OpenAI-compatible chat completions API payload = json.dumps({ "model": llm_cfg["model"], "messages": [{"role": "user", "content": user_msg}], "max_tokens": 50, "temperature": 0.0 }) headers = ["-H", "Content-Type: application/json"] if llm_cfg["api_key"]: headers += ["-H", f"Authorization: Bearer {llm_cfg['api_key']}"] cmd = [ "curl", "-s", "--max-time", str(timeout), f"{llm_cfg['endpoint']}/v1/chat/completions", *headers, "-d", payload ] result = sp.run(cmd, capture_output=True, text=True, timeout=timeout + 5) ``` ### Technical Analysis The LLM API key is placed directly in a `curl` header argument. The operating system stores this value in the child process's argument vector for the lifetime of the request. Depending on platform configuration, process arguments can be observed by same-user processes, administrators, process-accounting services, diagnostic tools, or endpoint monitoring software. The request also places fetched news titles and descriptions, source names, and the configured target country into the request body sent to the user-selected OpenAI-compatible endpoint. That transmission is functionally relevant to optional cloud-based LLM verification, but `SKILL.md` should explicitly include custom LLM endpoints in its outbound-connection disclosure. There is no shell interpolation because the command is passed as an argument list, so no command injection was identified in this path. ### Attack Path 1. A user enables the OpenAI-compatible LLM provider and configures an API key. 2. A non-government source produces a candidate classified as CRITICAL. 3. `_llm_verify_critical()` constructs a `curl` co ...[truncated 870 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Replace the `curl` subprocess with `urllib.request`, `http.client`, or another audited HTTP client so the authorization header remains in process memory rather than the command line. 2. If an external client is unavoidable, pass secret-bearing configuration through a protected file descriptor or mode-`0600` configuration file rather than through `argv`. 3. Never include bearer tokens in error messages, command traces, or diagnostic output. 4. Rotate provider tokens if process-monitoring systems may already have collected historical command lines. 5. Restrict provider keys to the minimum models, spending limits, and API operations required by verification. 6. Update the outbound-connections documentation to disclose that enabling a cloud LLM sends the candidate news title, description, source name, and configured country to the user-selected endpoint. ]]>
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Rogue AgentSelf-Modification, Session Persistence
Findings (66)

Tainted flow: 'req' from os.environ.get (line 109, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
req = urllib.request.Request(url, data=payload, headers={"Content-Type": "application/json"})
    try:
        resp = urllib.request.urlopen(req, timeout=15)
        result = json.loads(resp.read())
        
        # Auto-pin if requested
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'pin_req' from os.environ.get (line 123, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
}).encode()
            pin_req = urllib.request.Request(pin_url, data=pin_payload, headers={"Content-Type": "application/json"})
            try:
                urllib.request.urlopen(pin_req, timeout=10)
            except Exception:
                pass  # Pin failure is non-critical
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'req2' from os.environ.get (line 138, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
"disable_web_page_preview": True
            }).encode()
            req2 = urllib.request.Request(url, data=payload2, headers={"Content-Type": "application/json"})
            resp2 = urllib.request.urlopen(req2, timeout=15)
            return json.loads(resp2.read())
        except Exception as e2:
            print(f"[AEGIS] Send failed: {e2}", file=sys.stderr)
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tainted flow: 'pin_req' from os.environ.get (line 330, credential/environment) → urllib.request.urlopen (network output)

Critical
Category
Data Flow
Content
}).encode()
            pin_req = urllib.request.Request(pin_url, data=pin_payload, headers={"Content-Type": "application/json"})
            try:
                urllib.request.urlopen(pin_req, timeout=10)
            except:
                pass
Confidence
90% confidence
Finding
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.

Tp4

High
Category
MCP Tool Poisoning
Confidence
95% confidence
Finding
The code is broadly related to the declared emergency threat-monitoring purpose, but the description overstates its scope and generality. This chunk does not implement a generic 'conflict zones' intelligence system; it is a cron orchestration script specialized for UAE/Dubai alert text and behavior. It runs another scanner, logs/saves results, applies cooldown and corroboration logic, and posts critical alerts through Telegram. Those behaviors support the declared purpose, but the hard-coded UAE/Dubai targeting is a material mismatch from the description's broad, location-agnostic framing.

Tp4

High
Category
MCP Tool Poisoning
Confidence
93% confidence
Finding
The description presents a broad automated emergency geopolitical intelligence system for civilians in conflict zones, suitable for monitoring any location, assessing threat levels, configuring alerts, generating briefings, and preparedness planning. The code is much narrower: it specifically filters for UAE/Gulf relevance, scrapes World Monitor and LiveUAMap, deduplicates event text, assigns coarse urgency labels, and posts batched updates to a Telegram channel. That supports part of the declared alerting/monitoring concept, but it does not implement several major claimed uses such as general location setup, comprehensive security briefings, emergency preparedness planning, or broad civilian safety analysis. It also uses undeclared external network resources and Telegram posting. Therefore the code only partially matches the description and is materially narrower/different in purpose and capability.

Tp4

High
Category
MCP Tool Poisoning
Confidence
96% confidence
Finding
The declared description presents a full emergency geopolitical intelligence and civilian safety alerting system focused on monitoring, threat analysis, briefing generation, and preparedness workflows. The provided code does not perform monitoring, intelligence gathering, threat assessment, alert delivery, briefing generation, or preparedness planning. Instead, it is a narrow operational script for toggling a single cron-based live feed on or off and checking its status. While this may support a larger AEGIS system, the actual code chunk’s primary purpose is infrastructure/task scheduling control, which is materially different from the declared end-user functionality.

Credential Access

High
Category
Privilege Escalation
Content
def _load_openclaw_dotenv():
    """Best-effort loader for decrypted secrets from tmpfs.

    Reads from /run/user/<uid>/openclaw-secrets/.env (decrypted by
    openclaw-secrets.service) with fallback to ~/.openclaw/.env for
    development. Also resolves simple ${VAR} and $VAR references.
    """
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _load_openclaw_dotenv():
    """Best-effort loader for decrypted secrets from tmpfs.

    Reads from /run/user/<uid>/openclaw-secrets/.env (decrypted by
    openclaw-secrets.service) with fallback to ~/.openclaw/.env for
    development. Also resolves simple ${VAR} and $VAR references.
    """
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
def _load_openclaw_dotenv():
    """Best-effort loader for decrypted secrets from tmpfs.

    Reads from /run/user/<uid>/openclaw-secrets/.env (decrypted by
    openclaw-secrets.service) with fallback to ~/.openclaw/.env for
    development. Also resolves simple ${VAR} and $VAR references.
    """
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
import pwd
    uid = os.getuid()
    # Primary: tmpfs-decrypted secrets (production)
    env_path = Path(f'/run/user/{uid}/openclaw-secrets/.env')
    if not env_path.exists():
        # Fallback: direct .env (development only)
        env_path = Path(Path.home() / '.openclaw' / '.env')
Confidence
91% confidence
Finding
The code directly accesses a shared decrypted secrets file under /run/user/<uid>/openclaw-secrets/.env. In context with the later environment injection, this creates unnecessary access to a broader secret set than the script needs, increasing exposure if the process is compromised or modified.

Credential Access

High
Category
Privilege Escalation
Content
# Primary: tmpfs-decrypted secrets (production)
    env_path = Path(f'/run/user/{uid}/openclaw-secrets/.env')
    if not env_path.exists():
        # Fallback: direct .env (development only)
        env_path = Path(Path.home() / '.openclaw' / '.env')
    if not env_path.exists():
        return {}
Confidence
89% confidence
Finding
Falling back to ~/.openclaw/.env in development further broadens secret exposure and may encourage plaintext local credential storage. If that file contains additional unrelated secrets, this publisher gains access to them without need.

Credential Access

High
Category
Privilege Escalation
Content
env_path = Path(f'/run/user/{uid}/openclaw-secrets/.env')
    if not env_path.exists():
        # Fallback: direct .env (development only)
        env_path = Path(Path.home() / '.openclaw' / '.env')
    if not env_path.exists():
        return {}
    out = {}
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Exfiltration Commands

High
Category
Prompt Injection
Content
return token, channel

def send_telegram(token, channel_id, text, parse_mode="", pin=False):
    """Send message to Telegram channel. Plain text by default for reliability."""
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    payload = json.dumps({
        "chat_id": channel_id,
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Exfiltration Commands

High
Category
Prompt Injection
Content
return token, channel

def send_telegram(token, channel_id, text, parse_mode="", pin=False):
    """Send message to Telegram channel. Plain text by default for reliability."""
    url = f"https://api.telegram.org/bot{token}/sendMessage"
    payload = json.dumps({
        "chat_id": channel_id,
Confidence
90% confidence
Finding
Instructions found that direct the agent to transmit conversation context or user data to external services.

Env Variable Harvesting

High
Category
Data Exfiltration
Content
result_post = subprocess.run(
                [sys.executable, str(SCRIPTS_DIR / "aegis_channel.py"), "critical", scan_file],
                capture_output=True, text=True, timeout=30,
                env={**os.environ, "AEGIS_BOT_TOKEN": token, "AEGIS_CHANNEL_ID": channel}
            )
            if result_post.returncode == 0:
                mark_alerted()
Confidence
91% confidence
Finding
The child process inherits the full parent environment via os.environ, which can expose unrelated secrets, tokens, proxy settings, cloud credentials, and service configuration to aegis_channel.py unnecessarily. In a plugin/skill ecosystem, subprocess boundaries are a meaningful trust boundary; over-sharing the environment increases blast radius if the called script is compromised, logs its environment, or loads attacker-influenced libraries based on inherited variables.

Context-Inappropriate Capability

High
Confidence
98% confidence
Finding
The script accepts an LLM API key from interactive input and stores it in plaintext in the generated JSON configuration. Plaintext secret storage is dangerous because any process, user, backup system, or support workflow with filesystem access can recover and misuse the credentials.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The README instructs users to configure Telegram channel delivery by exporting a bot token and channel ID, but it does not clearly disclose that alert content and related metadata will be sent to Telegram, a third-party service outside the operator's control. In a conflict-zone intelligence skill, alerts may reveal sensitive location, threat-monitoring behavior, or operational context, so omission of this privacy/data-sharing warning can lead users to expose safety-relevant information without informed consent.

Lp3

Medium
Category
MCP Least Privilege
Confidence
91% confidence
Finding
The skill documentation declares binaries and environment needs but does not define an explicit tool/permission scope despite describing shell execution, network access, local file reads/writes, and environment-variable use. In an agent ecosystem, this under-specification can cause the host or user to approve a skill without understanding its real privileges, increasing the risk of overbroad execution and unintended data exposure.

Session Persistence

Medium
Category
Rogue Agent
Content
Creates `~/.openclaw/aegis-config.json` with location, language, and alert preferences.

### Manual config
Create `~/.openclaw/aegis-config.json`:
```json
{
  "location": {
Confidence
84% confidence
Finding
The skill stores persistent local configuration and operational state, including user location, alert preferences, scan history, and potentially Telegram configuration. In the context of a conflict-zone safety tool, this data can be sensitive: unauthorized local access could reveal whereabouts, habits, and communication channels, creating privacy and physical-safety risk.

External Transmission

Medium
Category
Data Exfiltration
Content
1. URLs listed in `references/source-registry.json` (RSS feeds, news sites, government pages)
2. `https://world-monitor.com/api/signal-markers` (World Monitor public API)
3. LiveUAMap regional pages (e.g., `https://iran.liveuamap.com`)
4. Telegram Bot API (`https://api.telegram.org/bot.../sendMessage`) — only if channel delivery is configured

No telemetry. No analytics. No phone-home.
Confidence
88% confidence
Finding
The skill transmits data to external services, including Telegram, and the transmitted content may include sensitive location-specific threat context, alert content, or metadata derived from the user's configuration. Even though Telegram delivery is described as optional, external transmission creates privacy and data-handling risk, especially for users in conflict zones where channel exposure, bot-token misuse, or misdirected posting could endanger people.

Natural-Language Policy Violations

Medium
Confidence
83% confidence
Finding
The briefing format explicitly states updates are provided 'in plain English,' which is a language constraint in the skill's natural-language behavior. Although the config example includes a language field earlier, this section does not present language choice for generated briefings and reads as a fixed requirement.

Missing User Warnings

Medium
Confidence
95% confidence
Finding
The documentation presents a cloud LLM configuration that sends alert content to a third-party API endpoint, but it does not explicitly warn users that potentially sensitive safety-monitoring data may leave the local device and be processed by an external provider. In the AEGIS context, alerts may include location, threat context, and user-specific monitoring scope, so the omission can lead to unintentional data exposure and poor privacy decisions by users.

Natural-Language Policy Violations

Medium
Confidence
91% confidence
Finding
This JSON template sets "language": "en" as a fixed default, which can encode a language preference across all generated country profiles. Because the file provides no user choice, opt-in mechanism, or documented region-specific justification, it may violate language/locale policy requirements.

Natural-Language Policy Violations

Medium
Confidence
94% confidence
Finding
This section switches into UAE-specific evacuation routes and assumptions without prominently scoping the document as UAE-only or requiring the user to confirm location. In an emergency-preparedness skill, users may overgeneralize these routes, border assumptions, and airport options to other regions, which can cause dangerous misrouting, border denial, or movement into less safe areas during a crisis.

Static analysis

No suspicious patterns detected.