Back to skill

Security audit

Nexus Sentinel

Security checks for vulnerabilities and agentic risk

Overview

This SRE skill is mostly coherent with its stated purpose, but it asks for powerful system, file, service-control, and outbound-network capabilities without enough scoping or safeguards.

Install only in a controlled SRE environment after limiting it to specific services, paths, and destinations. Require explicit approval before cleanup, restart, backup, or sending log-derived content externally, and add redaction plus content-based secret detection before enabling WhatsApp or cloud backup features.

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 (3)

T09 · Insecure Skill Coding Practices

Warning
Location
sentinel.py:35
Finding
Unredacted notification content may disclose sensitive information to an external service## Vulnerability Details **File Location**: `sentinel.py`, lines 35–45 **Vulnerability Type**: Unfiltered transmission of potentially sensitive diagnostic data **Risk Level**: Medium ```python def notify(message): """Sends notification via the configured channel.""" target = os.getenv("NEXUS_REPORT_CHANNEL") api_key = os.getenv("MATON_API_KEY") if not target or not api_key: print(f"NOTIFY_STDOUT: {message}") return # We use Maton API for secure relay payload = {"to": target, "message": f"[NEXUS] {message}"} try: requests.post(f"{API_GATEWAY}/whatsapp/send", json=payload, headers={"Authorization": f"Bearer {api_key}"}, timeout=10) ``` ### Technical Analysis The function sends caller-controlled `message` content to `https://gateway.maton.ai/whatsapp/send` without redaction, classification, or explicit approval. The request also includes the configured WhatsApp destination and the `MATON_API_KEY` bearer credential. Sending a bearer token to the API endpoint is necessary for the documented WhatsApp integration and is not, by itself, evidence of malicious exfiltration. However, the unrestricted message field creates a sensitive-data disclosure channel. Service logs and diagnostic output commonly contain credentials, authorization headers, connection strings, personal information, and internal infrastructure details. The current command-line entry point does not invoke `notify()`, so this package does not presently demonstrate an automatic path from log collection to network transmission. Exploitation requires another caller to pass sensitive content to the function. ### Attack Path 1. A monitored Docker or PM2 service emits a credential, token, connection string, or other confidential value in its logs. 2. Diagnostic logic or another caller obtains that content and passes it to `notify()`. 3. The function places the complete content in the JSON `message` ...[truncated 829 chars]
Remediation
## Remediation Suggestions - Apply a centralized redaction function before constructing the notification payload. - Detect and remove API keys, bearer tokens, passwords, private keys, connection strings, cookies, and authorization headers. - Prefer structured, allowlisted notification fields over arbitrary log or exception text. - Require explicit user approval before sending log-derived content externally. - Reject messages containing suspected secrets rather than relying solely on substitution. - Limit message length and avoid transmitting full stack traces or raw logs. - Validate the destination and restrict outbound access to the documented Maton HTTPS endpoint. - Check the HTTP response and report failures securely rather than suppressing every exception. - Ensure fallback output does not print secrets to terminals or centralized process logs.

T09 · Insecure Skill Coding Practices

Warning
Location
sentinel.py:48
Finding
Backup sensitivity control checks filenames but not file contents## Vulnerability Details **File Location**: `sentinel.py`, lines 48–56 **Vulnerability Type**: Inadequate secret detection and authorization enforcement **Risk Level**: Medium ```python def backup_file(file_path): """Incremental backup of non-sensitive config files.""" if any(p in file_path.lower() for p in SENSITIVE_PATTERNS): return {"error": "Manual authorization required for sensitive files"} # Logic to tar and push to GDrive via Maton # ... (Simplified for the skill demo) return {"status": "ready_for_upload", "file": file_path} ``` ### Technical Analysis The documented policy prohibits uploading files containing secrets without explicit `/approve` authorization. The implementation only compares sensitive keywords against the textual file path. It never inspects the file's contents and does not implement or verify an approval state. Consequently, an innocuously named file such as `config.yaml` could contain passwords or tokens and still be marked `ready_for_upload`. The substring approach also produces false positives; for example, a benign path containing the characters `key` would be blocked. No upload is implemented in the audited version, so the current function only returns an unsafe readiness decision. The vulnerability becomes directly exploitable if a downstream uploader trusts that result, as implied by the documented Google Drive backup functionality. ### Attack Path 1. A secret is stored in a file whose path does not contain `.env`, `key`, `password`, `secret`, or `token`. 2. The file path is passed to `backup_file()`. 3. The filename-based check finds no matching substring. 4. The function returns `{"status": "ready_for_upload", ...}` without inspecting the content or verifying approval. 5. A downstream backup component trusts this status and uploads the file to cloud storage. 6. Anyone with access to the target storage or relay infrastructure can obtain the s ...[truncated 606 chars]
Remediation
## Remediation Suggestions - Enforce secret detection inside the final upload operation rather than treating a preliminary status as authorization. - Inspect file contents using well-tested secret-detection rules for credentials, tokens, private keys, and connection strings. - Use explicit allowlists for approved configuration roots, extensions, and file types. - Reject symbolic links and verify canonical paths to prevent path-policy bypasses. - Apply file-size limits and avoid scanning or uploading special device files. - Implement a cryptographically or session-bound approval record that identifies the exact file, content hash, destination, and expiration time. - Require explicit approval whenever secret detection is uncertain. - Encrypt backups in transit and at rest and restrict access to the destination folder. - Record security-relevant backup decisions without writing secret values to logs.

T08 · Insecure Dependencies

Note
Location
SKILL.md:18
Finding
Python dependencies are installed without version or integrity pinning## Vulnerability Details **File Location**: `SKILL.md`, lines 18–21 **Vulnerability Type**: Unpinned third-party dependencies **Risk Level**: Low ```markdown ## 🚀 Installation & Dépendances Ce skill nécessite : - `docker`, `pm2`, `tar`, `curl` sur le système hôte. - Les librairies Python `psutil` et `requests`. Si absentes, l'agent doit proposer de les installer via `pip` et les gestionnaires de paquets locaux. ``` The same unpinned package declarations also appear in `_meta.json`: ```json "requirements": { "binaries": ["docker", "pm2", "tar", "curl"], "pythonPackages": ["psutil", "requests"], "env": ["NEXUS_REPORT_CHANNEL", "NEXUS_BACKUP_PATH", "MATON_API_KEY"] } ``` ### Technical Analysis The Skill instructs the agent to offer installation of `psutil` and `requests` through `pip`, but it specifies neither reviewed versions nor package hashes. Package resolution therefore depends on mutable repository state at installation time. The package names are established dependencies, are not apparent typos, and no untrusted package index is explicitly configured. The finding is therefore a supply-chain hardening weakness rather than evidence that a malicious dependency is currently included. ### Attack Path 1. The required Python packages are absent from the host. 2. The agent proposes or performs installation using the unpinned package names. 3. The package index resolves whatever release is current at that time. 4. A compromised, malicious, or unexpectedly incompatible release is downloaded. 5. Package installation or import executes unintended behavior with the privileges of the installing or running process. ### Impact Assessment Impact depends on the privileges used for installation and execution. A compromised dependency could access environment variables, including `MATON_API_KEY`, inspect data readable by the process, issue outbound requests, or execute local code. If installation ...[truncated 239 chars]
Remediation
## Remediation Suggestions - Pin each Python dependency to a reviewed version or tightly controlled version range. - Use a lockfile or requirements file with cryptographic hashes. - Install only from explicitly trusted package indexes over authenticated HTTPS. - Review dependency updates before changing pinned versions. - Avoid automatic installation and require informed user confirmation. - Install dependencies in an isolated virtual environment under a non-administrative account. - Apply equivalent version controls to external binaries where the deployment environment supports them. - Add software-composition analysis and vulnerability scanning to the release process.
Vulnerability Patterns
  • 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
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Behavioral ASTexec() Call, eval() Call, Dynamic Import
Findings (13)

Tainted flow: 'payload' from os.getenv (line 43, credential/environment) → requests.post (network output)

Critical
Category
Data Flow
Content
# We use Maton API for secure relay
    payload = {"to": target, "message": f"[NEXUS] {message}"}
    try:
        requests.post(f"{API_GATEWAY}/whatsapp/send", json=payload, headers={"Authorization": f"Bearer {api_key}"}, 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.

Credential Access

High
Category
Privilege Escalation
Content
import datetime

# --- CONFIGURATION ---
SENSITIVE_PATTERNS = [".env", "key", "password", "secret", "token"]
API_GATEWAY = "https://gateway.maton.ai"

def get_system_report():
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Natural-Language Policy Violations

Medium
Confidence
95% confidence
Finding
The entire skill description and operational instructions are presented only in French, with no indication that the user can choose another language or that the skill is intentionally region-specific. This can violate language/locale policy when a specific language is imposed without opt-in.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The README advertises actions that can modify the host system, including log rotation, temp-file cleanup, and service recovery with restart, but it does not clearly warn users that these operations may be destructive or disruptive. In an autonomous SRE context, undocumented cleanup and restart behavior increases the risk of accidental data loss, service interruption, or unsafe execution by users who may assume the commands are read-only.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
Le document décrit la rotation des logs, le nettoyage des fichiers temporaires et la récupération d'un service avec redémarrage, qui peuvent affecter des données utilisateur ou l'intégrité du système. Aucune mise en garde explicite n'indique ces impacts potentiels, les prérequis, ni les risques associés à ces actions.

Vague Triggers

Medium
Confidence
90% confidence
Finding
The manifest describes the skill as an 'Autonomous SRE Agent' that performs 'Proactive monitoring' and 'smart service recovery' without defining clear activation boundaries, approval requirements, or scope limits. In a skill that also requests filesystem write access, outbound network access, and service-control commands, this ambiguity increases the chance of unsupervised or overbroad actions affecting live systems.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The manifest requests filesystem read/write access, outbound network access, and operational commands such as docker, pm2, and tar, but it does not present a clear user-facing warning about these capabilities or their risks. Because the skill is positioned for autonomous SRE activity, missing disclosure can lead operators to enable a powerful skill without understanding it can modify files, interact with services, create archives, and send data externally.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
try:
        if service_name.startswith("docker:"):
            container = service_name.split(":")[1]
            res = subprocess.run(["docker", "logs", "--tail", str(lines), container], capture_output=True, text=True)
            return res.stdout + res.stderr
        else:
            res = subprocess.run(["pm2", "logs", service_name, "--lines", str(lines), "--nostream"], capture_output=True, text=True)
Confidence
70% confidence
Finding
subprocess module calls execute external commands. Without careful input validation, this enables command injection.

subprocess module call

Medium
Category
Dangerous Code Execution
Content
res = subprocess.run(["docker", "logs", "--tail", str(lines), container], capture_output=True, text=True)
            return res.stdout + res.stderr
        else:
            res = subprocess.run(["pm2", "logs", service_name, "--lines", str(lines), "--nostream"], capture_output=True, text=True)
            return res.stdout
    except:
        return "Log extraction failed."
Confidence
83% confidence
Finding
The code passes a user-controlled service_name directly to pm2 logs, which can expose arbitrary process logs available to the executing user. While this is not shell injection, it can enable unauthorized log access and disclosure of secrets present in application logs.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The notify function sends messages to an external API with no user confirmation, audit prompt, or content classification. In this skill context, messages may contain system state or log-derived data, so silent outbound transmission increases the chance of unreviewed data leakage.

External Transmission

Medium
Category
Data Exfiltration
Content
# We use Maton API for secure relay
    payload = {"to": target, "message": f"[NEXUS] {message}"}
    try:
        requests.post(f"{API_GATEWAY}/whatsapp/send", json=payload, headers={"Authorization": f"Bearer {api_key}"}, timeout=10)
    except:
        pass
Confidence
90% confidence
Finding
This code performs external network transmission to a third-party gateway. In an operational diagnostics skill, outbound messaging is not inherently malicious, but it becomes security-relevant because the transmitted message may contain sensitive operational details and the transfer is silent on failure and success.

Intent-Code Divergence

Medium
Confidence
94% confidence
Finding
The docstring claims only non-sensitive config files are backed up, but the implementation merely checks for a few substrings in the path. This is easy to bypass and can misclassify both sensitive and non-config files, creating a path to unintended backup or later exfiltration of confidential data.

Natural-Language Policy Violations

Low
Confidence
95% confidence
Finding
Tout le contenu descriptif et les consignes utilisateur sont rédigés exclusivement en français, sans mention d'une option de langue ou d'une contrainte régionale justifiée. Cela constitue une contrainte linguistique implicite pouvant contrevenir à une politique de neutralité linguistique sans opt-in utilisateur.

Static analysis

No suspicious patterns detected.