Back to skill

Security audit

Civic

Security checks for vulnerabilities and agentic risk

Overview

The skill appears to be a real Civic MCP bridge, but it needs review because it gives an agent broad access to external accounts and has weak safeguards around token destination and sensitive argument logging.

Install only if you trust Civic and understand that the configured token may let the agent access connected services such as Gmail, databases, and storage. Use a least-privilege Civic profile, keep CIVIC_URL on the official HTTPS Civic endpoint, avoid passing secrets in tool arguments, review logs, and confirm sensitive or mutating actions before allowing the agent to run them.

Vulnerability Patterns
  • 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
  • Embedded Malicious CodeShips malicious scripts inside the skill and executes them locally
Findings (2)

T09 · Insecure Skill Coding Practices

Error
Location
civic-tool-runner.ts:35
Finding
Bearer Token Disclosure Through an Unvalidated MCP Endpoint<![CDATA[ ## Vulnerability Details **File Location**: `civic-tool-runner.ts`, lines 35-43 and 197-198 **Vulnerability Type**: Credential exposure through an unvalidated destination **Risk Level**: High ### Vulnerable Code ```ts constructor(url: string, token: string) { const userAgent = `openclaw/1.0.0 node/${process.version.slice(1)} (${process.platform}; ${process.arch})`; this.transport = new StreamableHTTPClientTransport(new URL(url), { requestInit: { headers: { Authorization: `Bearer ${token}`, "User-Agent": userAgent, }, }, }); ``` The destination is obtained directly from the environment: ```ts const url = process.env.CIVIC_URL ?? "https://nexus.civic.com/hub/mcp"; const token = process.env.CIVIC_TOKEN; ``` ### Technical Analysis The runner accepts `CIVIC_URL` as an arbitrary URL and unconditionally places `CIVIC_TOKEN` in the `Authorization` header. `new URL(url)` validates only that the value is syntactically a URL; it does not enforce HTTPS, verify that the destination belongs to Civic, reject embedded URL credentials, restrict ports, or establish an allowed origin. Consequently, anyone who can modify the skill environment or its OpenClaw configuration can redirect the MCP connection to an attacker-controlled endpoint. When the runner connects, the bearer token is transmitted to that endpoint. A plaintext HTTP URL would additionally expose the credential to network observers. The unsafe destination also receives subsequent MCP requests and any arguments supplied to tools advertised by that server. Endpoint control is a prerequisite; there is no evidence that an unauthenticated remote user can alter the environment through this code alone. ### Attack Path 1. An attacker gains the ability to modify the skill configuration, deployment environment, or `CIVIC_URL` value. 2. The attacker sets `CIVIC_URL` to an endpoint under their control, such as `https://attacker.example/mcp`. 3. A user or agent invokes t ...[truncated 1012 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Parse and validate `CIVIC_URL` before constructing the transport. 2. Require `url.protocol === "https:"`; reject plaintext HTTP and all non-HTTP schemes. 3. Maintain an explicit allowlist of approved Civic hostnames, preferably requiring an exact hostname such as `nexus.civic.com` rather than using a suffix check. 4. Reject URL usernames, passwords, unexpected ports, and fragments. 5. Ensure redirects cannot forward the `Authorization` header to a different origin. Disable redirects where supported or revalidate every redirect destination before attaching credentials. 6. Separate endpoint selection from credential attachment: only add the bearer token after the destination origin has passed validation. 7. Consider removing the configurable URL in production deployments or requiring an explicit opt-in for non-production endpoints with separate, non-production credentials. 8. Rotate the Civic token immediately if it may have been sent to an untrusted endpoint. 9. Apply least-privilege scopes and short token lifetimes to limit the consequences of disclosure. Example validation logic: ```ts function validateCivicUrl(value: string): URL { const url = new URL(value); if (url.protocol !== "https:") { throw new Error("CIVIC_URL must use HTTPS"); } if (url.hostname !== "nexus.civic.com") { throw new Error("CIVIC_URL must use an approved Civic hostname"); } if (url.username || url.password || (url.port && url.port !== "443")) { throw new Error("CIVIC_URL contains disallowed authority components"); } return url; } ``` ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
civic-tool-runner.ts:249
Finding
Sensitive MCP Tool Arguments Are Logged in Plaintext<![CDATA[ ## Vulnerability Details **File Location**: `civic-tool-runner.ts`, lines 249-252 **Vulnerability Type**: Sensitive information exposure through logging **Risk Level**: Medium ### Vulnerable Code ```ts console.log(`\nCalling: ${toolName}`); if (Object.keys(toolArgs).length > 0) { console.log(`Args: ${JSON.stringify(toolArgs)}`); } ``` ### Technical Analysis The runner accepts arbitrary JSON arguments for any remotely exposed MCP tool and serializes the complete argument object to standard output before executing the call. There is no field-level redaction, sensitivity classification, output restriction, or secure debug-mode requirement. Tool arguments can contain credentials, authorization codes, email contents, recipient addresses, database statements, personal information, document contents, account identifiers, or other confidential values. Standard output is commonly retained in terminal capture, CI/CD logs, agent execution traces, process supervisors, centralized logging platforms, and support diagnostics. Although the command-line JSON value may already be visible to local process inspection or shell history depending on invocation, unconditional logging creates an additional persistent copy and can distribute it to systems and users that do not otherwise have access to the process arguments. ### Attack Path 1. A user or agent invokes `--call` with confidential data in the `--args` JSON object. 2. The runner parses the object into `toolArgs`. 3. Before making the MCP request, the runner serializes the entire object with `JSON.stringify`. 4. The plaintext value is written to standard output. 5. A terminal recorder, CI system, OpenClaw execution log, process supervisor, or centralized log collector retains the output. 6. A user with access to those logs retrieves the confidential arguments. An attacker must be able to induce a call containing sensitive arguments and subsequently access the generated logs, or already have access to a logg ...[truncated 638 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove argument logging from the default execution path. 2. If diagnostics are necessary, require an explicit debug option and clearly warn that enabling it may expose sensitive information. 3. Log only non-sensitive metadata by default, such as the tool name and the names or count of supplied fields. 4. Implement recursive redaction for likely secret fields, including `token`, `authorization`, `password`, `secret`, `apiKey`, `cookie`, `code`, and similar variants. 5. Prefer an explicit allowlist of safe fields over relying solely on a denylist, because arbitrary MCP schemas may use unexpected names for sensitive values. 6. Apply access controls, retention limits, and encryption to execution logs. 7. Review existing logs and remove or rotate any secrets that may already have been recorded. A safer default is: ```ts console.log(`\nCalling: ${toolName}`); if (Object.keys(toolArgs).length > 0) { console.log(`Argument fields: ${Object.keys(toolArgs).join(", ")}`); } ``` For high-sensitivity environments, log only the tool name and omit all argument information. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (32)

Credential Access

High
Category
Privilege Escalation
Content
### 1. Get your Civic credentials

1. Go to [nexus.civic.com](https://nexus.civic.com) and sign in
2. Get your **MCP URL** and **access token** from your profile settings

### 2. Configure in OpenClaw
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### 1. Get your Civic credentials

1. Go to [nexus.civic.com](https://nexus.civic.com) and sign in
2. Get your **MCP URL** and **access token** from your profile settings

### 2. Configure in OpenClaw
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Credential Access

High
Category
Privilege Escalation
Content
### 1. Get your Civic credentials

1. Go to [nexus.civic.com](https://nexus.civic.com) and sign in
2. Get your **MCP URL** and **access token** from your profile settings

### 2. Configure in OpenClaw
Confidence
70% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Lp3

Medium
Category
MCP Least Privilege
Confidence
90% confidence
Finding
The skill declares environment-variable requirements and provides executable command guidance, but it does not define an explicit tool scope such as permissions or allowed-tools. That omission weakens containment and reviewability, making it easier for an agent to invoke external capabilities or handle sensitive credentials without clear policy boundaries.

Missing User Warnings

Medium
Confidence
89% confidence
Finding
The setup instructions ask users to configure a third-party MCP endpoint and place a long-lived access token into agent configuration, but they do not clearly warn that data and credentials will be transmitted to an external service. In a skill that bridges to Gmail, databases, and storage systems, that missing disclosure increases the risk of unsafe consent and accidental overexposure of sensitive account data.

Missing User Warnings

Medium
Confidence
90% confidence
Finding
The agent instructions actively demonstrate listing and calling external tools, including Gmail queries, without requiring an explicit warning or confirmation that the action may read or modify data in external accounts. Because the skill targets many integrations, an agent could perform sensitive operations under user credentials with insufficient transparency.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
Using `npx tsx` without a pinned package version can cause the runtime to fetch or resolve whatever version is current at execution time. This creates a supply-chain risk: a malicious or compromised release of `tsx` or a dependency could execute arbitrary code in the agent environment while handling Civic credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
Using `npx tsx` without a pinned package version can cause the runtime to fetch or resolve whatever version is current at execution time. This creates a supply-chain risk: a malicious or compromised release of `tsx` or a dependency could execute arbitrary code in the agent environment while handling Civic credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
Using `npx tsx` without a pinned package version can cause the runtime to fetch or resolve whatever version is current at execution time. This creates a supply-chain risk: a malicious or compromised release of `tsx` or a dependency could execute arbitrary code in the agent environment while handling Civic credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
Using `npx tsx` without a pinned package version can cause the runtime to fetch or resolve whatever version is current at execution time. This creates a supply-chain risk: a malicious or compromised release of `tsx` or a dependency could execute arbitrary code in the agent environment while handling Civic credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
96% confidence
Finding
Using `npx tsx` without a pinned package version can cause the runtime to fetch or resolve whatever version is current at execution time. This creates a supply-chain risk: a malicious or compromised release of `tsx` or a dependency could execute arbitrary code in the agent environment while handling Civic credentials.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Rp1

Medium
Category
MCP Rug Pull
Confidence
70% confidence
Finding
npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Static analysis

No suspicious patterns detected.