Back to skill

Security audit

AWS CloudWatch

Security checks for vulnerabilities and agentic risk

Overview

This CloudWatch metric skill is mostly purpose-aligned, but its wrapper can execute the wrong local script and enables shell execution on Windows, which creates avoidable code-execution risk around AWS credentials.

Review before installing. Use only short-lived or role-based AWS credentials with read-only CloudWatch permissions, avoid running the wrapper from untrusted directories, and be especially cautious on Windows until shell execution and path resolution are fixed. Expect text summaries, not rendered charts.

Vulnerability Patterns
  • Tool Hijacking and SpoofingModifies or replaces tools so legitimate-looking calls execute attacker logic
  • 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 (2)

T07 · Tool Hijacking and Spoofing

Error
Location
src/skill.mjs:4
Finding
Working-Directory Executable Hijacking in Skill Wrapper## Vulnerability Details **File Location**: `src/skill.mjs`, lines 4-7 **Vulnerability Type**: Working-directory script hijacking **Risk Level**: High ### Vulnerable Code ```js const result = spawnSync("node", ["./src/cli.mjs", ...args], { stdio: "inherit", shell: process.platform === "win32", }); ``` ### Technical Analysis The wrapper starts `./src/cli.mjs` using a path relative to the process's current working directory. It does not resolve the script relative to the installed Skill directory represented by `import.meta.url`. Consequently, invoking the legitimate `skill.mjs` from another working directory can cause Node.js to execute a different `src/cli.mjs`. An attacker who can create files in that working directory can substitute arbitrary JavaScript without modifying the audited Skill package itself. This behavior is inconsistent with the documented entry point, which implies that execution should remain anchored to the Skill's base directory. ### Attack Path 1. An attacker identifies or controls a directory from which the Agent will invoke the Skill. 2. The attacker creates a malicious file at `src/cli.mjs` beneath that directory. 3. The Agent invokes the genuine `skill.mjs` while the attacker-controlled directory is the current working directory. 4. The relative path `./src/cli.mjs` resolves to the attacker's script. 5. Node.js executes the substituted script with the Agent process's privileges and inherited environment. ### Impact Assessment Successful exploitation provides arbitrary JavaScript execution under the operating-system account running the Agent. The malicious script inherits the wrapper's environment and may therefore access `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and other credentials available to the process. The attacker could use those credentials within their assigned IAM permissions, read or alter accessible local files, start additional processes, and make network requ ...[truncated 163 chars]
Remediation
## Remediation Suggestions Resolve `cli.mjs` relative to the wrapper's own location and invoke the current Node.js executable directly: ```js import path from "path"; import { fileURLToPath } from "url"; import { spawnSync } from "child_process"; const scriptPath = path.join( path.dirname(fileURLToPath(import.meta.url)), "cli.mjs" ); const result = spawnSync(process.execPath, [scriptPath, ...args], { stdio: "inherit", shell: false, }); if (result.error) { console.error("Failed to start CloudWatch CLI:", result.error.message); process.exit(1); } process.exit(result.status ?? 1); ``` Additional hardening measures include: - Do not depend on the caller's current working directory for executable paths. - Use `process.execPath` rather than resolving `node` through `PATH`. - Keep shell execution disabled on every platform. - Treat failure to launch the child process as an error rather than returning exit status zero. - Supply AWS credentials with only the required read-only CloudWatch permissions.

T09 · Insecure Skill Coding Practices

Error
Location
src/skill.mjs:4
Finding
Windows Command Injection Exposure Through Shell-Enabled Process Execution## Vulnerability Details **File Location**: `src/skill.mjs`, lines 4-7 **Vulnerability Type**: OS command injection **Risk Level**: High ### Vulnerable Code ```js const result = spawnSync("node", ["./src/cli.mjs", ...args], { stdio: "inherit", shell: process.platform === "win32", }); ``` ### Technical Analysis On Windows, the wrapper enables `shell` while forwarding all command-line arguments from `process.argv` to the child process. These arguments can include values such as resource names, metric names, or other user-controlled Skill parameters. Shell-enabled process execution introduces command-processor interpretation into a call that does not require shell functionality. Depending on the Node.js and Windows command-shell behavior, shell metacharacters embedded in attacker-controlled arguments may alter the intended command and append or invoke additional commands. Passing arguments as an array is not an adequate security boundary when execution is explicitly routed through a shell. The process should instead execute Node.js directly with shell processing disabled. ### Attack Path 1. An attacker gains influence over one of the arguments supplied to `skill.mjs`, such as a resource or metric value. 2. The attacker includes Windows command-shell metacharacters and a secondary command in that value. 3. The wrapper runs on Windows and sets `shell: true`. 4. The command processor interprets the crafted input rather than treating the entire value exclusively as literal application data. 5. The injected command executes under the Agent's operating-system account. Exploitation is specific to the Windows branch because non-Windows execution sets `shell` to false. ### Impact Assessment Successful exploitation can result in arbitrary command execution with the privileges of the Agent process. The injected command may access local files, inherited environment variables, and AWS credentials; launch additional pr ...[truncated 314 chars]
Remediation
## Remediation Suggestions Disable shell execution unconditionally and invoke the current Node.js runtime with an absolute script path: ```js const result = spawnSync(process.execPath, [scriptPath, ...args], { stdio: "inherit", shell: false, }); ``` Also apply the following controls: - Validate arguments against the expected formats before forwarding them. - Restrict `service` to `ecs`, `ec2`, or `rds`. - Validate numeric parameters such as `hours` and `period` as finite positive values within reasonable upper bounds. - Validate `region` against the AWS region naming format. - Avoid invoking a command processor because the wrapper requires no pipes, redirection, variable expansion, or other shell features. - Add Windows-specific tests containing shell metacharacters to verify that every argument is treated literally.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
Findings (7)

Description-Behavior Mismatch

Medium
Confidence
98% confidence
Finding
The manifest says this skill will query CloudWatch metrics and return charts. However, the README repeatedly describes text summaries to stdout and explicitly states 'Text-only output (no chart rendering),' which is a direct mismatch with the claimed chart-returning behavior.

Missing User Warnings

Medium
Confidence
94% confidence
Finding
The README tells users to set long-lived AWS access keys directly in their environment without any guidance on secure handling, rotation, or safer alternatives such as IAM roles, AWS SSO, or temporary credentials. This increases the likelihood of credential leakage through shell history, screenshots, shared terminals, CI logs, or persistent developer environments, which could lead to unauthorized AWS access.

Lp3

Medium
Category
MCP Least Privilege
Confidence
88% confidence
Finding
The skill declares required environment-based AWS credentials but does not define an explicit tool scope or permissions boundary. In an agent environment, this can lead to broader-than-necessary access to sensitive environment variables and makes it harder to enforce least privilege or reason about what the skill is allowed to access.

Intent-Code Divergence

Medium
Confidence
98% confidence
Finding
The manifest description at L03 says the skill will "return charts," while the body documentation at L08 says it returns "text summaries," and L52 explicitly states "Text-only output (no chart rendering)." These statements actively contradict each other about the skill's actual output behavior.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The documentation instructs users to supply AWS access keys but provides no guidance on secure handling, storage, or rotation of those secrets. This increases the risk of credential exposure through logs, shell history, copied examples, or insecure deployment practices, especially because the skill accesses cloud monitoring data using high-value cloud credentials.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
This code reads sensitive AWS credentials from environment variables and later uses them to make an HTTPS request to AWS CloudWatch. While missing credentials are reported as an error, there is no user-facing disclosure that the tool will access credentials and transmit resource/metric data over the network.

Description-Behavior Mismatch

Medium
Confidence
97% confidence
Finding
The manifest says the skill will 'return charts' for CloudWatch metrics, which implies chart generation or chart-formatted output. In practice, the code queries CloudWatch and emits a text summary with min/max/avg values, plus optional raw XML in debug mode, with no chart creation or chart data structure returned.

Static analysis

Detected: suspicious.dangerous_exec, suspicious.exposed_secret_literal

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
src/skill.mjs:5

File appears to expose a hardcoded API secret or token.

Critical
Code
suspicious.exposed_secret_literal
Location
src/cli.mjs:154