Back to skill

Security audit

lex

Security checks for vulnerabilities and agentic risk

Overview

The skill appears intended to help build Warden LangGraph agents, but some testing and production deployment examples could expose API keys or unauthenticated agent endpoints if copied directly.

Review this before installing if you plan to copy its deployment examples. Use HTTPS for any authenticated endpoint, do not pass real API keys as command-line arguments, add authentication before public /invoke or /stream routes, restrict CORS, avoid public Redis/Postgres defaults, replace example passwords, and pin dependencies/images for production use.

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

T09 · Insecure Skill Coding Practices

Error
Location
scripts/test-agent.py:16
Finding
API Credentials Can Be Exposed Through Command-Line Arguments and Plaintext HTTP<![CDATA[ ## Vulnerability Details **File Location**: `scripts/test-agent.py:16-22, 47-52, 77-83, 154-157, 184-189` **Vulnerability Type**: Sensitive credential exposure over an insecure transport **Risk Level**: High ### Vulnerable Code ```python class AgentTester: def __init__(self, url: str, api_key: str = None): self.url = url.rstrip('/') self.headers = { 'Content-Type': 'application/json' } if api_key: self.headers['Authorization'] = f'Bearer {api_key}' ``` ```python response = requests.post( f"{self.url}/invoke", json=payload, headers=self.headers, timeout=30 ) ``` ```python response = requests.post( f"{self.url}/stream", json=payload, headers=self.headers, stream=True, timeout=30 ) ``` ```python parser.add_argument( "--api-key", "-k", help="API key for authentication" ) ``` ```python if not args.url.startswith(('http://', 'https://')): print("Error: URL must start with http:// or https://") sys.exit(1) tester = AgentTester(args.url, args.api_key) ``` The unsafe command-line usage is also recommended in: - `README.md:77,207` - `references/quick-reference.md:18` ```bash python scripts/test-agent.py https://api.example.com --api-key [YOUR-API-KEY] ``` ### Technical Analysis The tester accepts an API key as a command-line argument and inserts it into an `Authorization: Bearer` header. Command-line secrets may be retained in shell history and can be visible through process-inspection facilities to other users or monitoring software on the same system. The URL validation permits both HTTPS and plaintext HTTP. When an HTTP URL is supplied, the bearer credential is transmitted without transport encryption. The destination is otherwise user-controlled and unrestricted, so a typo, malicious endpoint, or untrusted testing target can receive the credential. Sending a credential to a selected agent endpoint is necessary for authenticated te ...[truncated 1369 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove or deprecate the `--api-key` argument. 2. Read credentials from a protected environment variable, operating-system credential store, or interactive `getpass.getpass()` prompt. 3. Reject plaintext HTTP for all non-loopback destinations. 4. If HTTP is required for local development, permit it only for verified loopback hosts such as `127.0.0.1`, `::1`, and `localhost`, behind an explicit development flag. 5. Warn before sending credentials to a new or untrusted hostname. 6. Explicitly control redirects and ensure authorization headers are never forwarded to a different origin. 7. Update all README and quick-reference commands so secrets do not appear in shell arguments. 8. Recommend narrowly scoped, revocable testing keys rather than production-wide credentials. ]]>

T09 · Insecure Skill Coding Practices

Error
Location
references/deployment-guide.md:426
Finding
Production Deployment Example Exposes Unauthenticated Agent Execution Endpoints<![CDATA[ ## Vulnerability Details **File Location**: `references/deployment-guide.md:426-464, 483, 509-543` **Vulnerability Type**: Missing authentication and overly permissive network exposure **Risk Level**: High ### Vulnerable Code ```yaml apiVersion: v1 kind: Service metadata: name: warden-agent spec: selector: app: warden-agent ports: - port: 80 targetPort: 8000 type: LoadBalancer ``` ```typescript const app = express(); // Middleware app.use(helmet()); app.use(cors()); app.use(express.json()); ``` ```typescript // Main agent endpoint app.post('/invoke', async (req, res) => { try { const { input } = req.body; if (!input) { return res.status(400).json({ error: 'Input required' }); } const result = await agent.invoke({ input }); res.json(result); } catch (error) { console.error('Agent error:', error); res.status(500).json({ error: 'Internal error', message: error.message }); } }); // Streaming endpoint app.post('/stream', async (req, res) => { try { const { input } = req.body; res.setHeader('Content-Type', 'text/event-stream'); res.setHeader('Cache-Control', 'no-cache'); res.setHeader('Connection', 'keep-alive'); const stream = await agent.stream({ input }); for await (const chunk of stream) { res.write(`data: ${JSON.stringify(chunk)}\n\n`); } res.end(); } catch (error) { console.error('Streaming error:', error); res.write(`data: ${JSON.stringify({ error: error.message })}\n\n`); res.end(); } }); ``` ### Technical Analysis The guide presents this as a production server setup but does not apply authentication or authorization middleware to `/invoke` or `/stream`. Both routes directly execute the agent using attacker-supplied input. The Kubernetes example exposes the service through a `LoadBalancer`, which can make the endpoints reachable from external networks. In addition, `cors() ...[truncated 1594 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Add authentication middleware before `/invoke`, `/stream`, and any other non-health endpoint. 2. Use narrowly scoped API keys or signed tokens and compare secrets using constant-time operations. 3. Implement authorization so each credential can access only its intended agent and operations. 4. Replace unrestricted `cors()` with an explicit origin, method, and header allowlist. 5. Apply request-size limits, schema validation, per-identity rate limits, concurrency controls, and execution timeouts. 6. Default Kubernetes services to `ClusterIP` or an internal load balancer. 7. Place public deployments behind an authenticated API gateway or ingress with TLS. 8. Avoid returning raw internal exception messages to clients. 9. Document key rotation, revocation, audit logging, and abuse-monitoring procedures. 10. Add security tests verifying that unauthenticated requests receive `401 Unauthorized` or `403 Forbidden`. ]]>

T08 · Insecure Dependencies

Warning
Location
scripts/init-agent.py:29
Finding
Generated Projects Use Unpinned and Non-Reproducible Dependency Ranges<![CDATA[ ## Vulnerability Details **File Location**: `scripts/init-agent.py:29-38, 179-183` **Vulnerability Type**: Unsafe third-party dependency resolution **Risk Level**: Medium ### Vulnerable Code ```python "dependencies": { "@langchain/langgraph": "^0.0.19", "@langchain/openai": "^0.0.19", "dotenv": "^16.0.3", "express": "^4.18.2" }, "devDependencies": { "@types/node": "^20.0.0", "typescript": "^5.0.0", "vitest": "^1.0.0" } ``` ```python "requirements.txt": """langgraph>=0.0.19 langchain-openai>=0.0.19 python-dotenv>=1.0.0 fastapi>=0.100.0 uvicorn>=0.23.0""" ``` Users are then instructed to resolve and install these ranges: ```bash npm install ``` ```bash pip install -r requirements.txt ``` ### Technical Analysis The scaffold uses caret ranges for npm dependencies and unrestricted lower bounds for Python dependencies. It does not generate an npm lockfile, a Python constraints file, or package hashes. Consequently, two users running the same scaffold at different times may install materially different dependency versions. For Python in particular, `>=` permits any later release accepted by the resolver. Installation therefore introduces code that was not present in and was not reviewed as part of this Skill. This does not prove that any listed dependency is malicious. The issue is the lack of reproducible dependency selection and integrity verification, which enlarges the supply-chain attack surface and can also introduce incompatible updates. ### Attack Path 1. A user runs `scripts/init-agent.py` to generate a project. 2. The generated manifest contains broad dependency ranges and no lockfile or hashes. 3. At a later time, a new or compromised package release becomes eligible under those ranges. 4. The user runs `npm install` or `pip install -r requirements.txt`. 5. The package manager downloads the newly eligible package and its transitive dependencies. 6. Package installation hooks, build scripts, imported modules, or runtime cod ...[truncated 701 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Pin all direct dependencies to reviewed exact versions. 2. Generate and ship an npm lockfile, then instruct users and CI systems to use `npm ci`. 3. For Python, use a compiled lock or constraints file with exact versions. 4. Enable pip hash verification with `--require-hashes`. 5. Pin and review transitive dependencies where practical. 6. Disable unnecessary npm lifecycle scripts during untrusted installation stages. 7. Run dependency installation in an isolated, non-privileged build environment without production secrets. 8. Use automated vulnerability and provenance scanning for npm and Python packages. 9. Adopt a controlled dependency-update process that reviews release notes and regenerates lockfiles. 10. Document supported versions and test the scaffold against the exact locked dependency set. ]]>

T09 · Insecure Skill Coding Practices

Warning
Location
assets/example-configs.md:240
Finding
Infrastructure Examples Expose Redis and Use a Predictable Database Password<![CDATA[ ## Vulnerability Details **File Location**: `assets/example-configs.md:240-254, 278-285` **Vulnerability Type**: Unsafe infrastructure defaults and weak credentials **Risk Level**: Medium ### Vulnerable Code ```yaml services: agent: build: . ports: - "8000:8000" env_file: - .env environment: - REDIS_URL=redis://redis:6379 depends_on: - redis restart: unless-stopped redis: image: redis:alpine ports: - "6379:6379" volumes: - redis-data:/data restart: unless-stopped ``` ```yaml db: image: postgres:15-alpine environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: agent volumes: - postgres-data:/var/lib/postgresql/data restart: unless-stopped ``` ### Technical Analysis The Redis example publishes container port 6379 to the host using `"6379:6379"`. Unless host firewall rules prevent access, Docker may bind this service on external interfaces. The example does not configure Redis authentication, ACLs, or TLS. The PostgreSQL example uses the predictable credential pair `postgres:postgres`. Although the shown database service is not explicitly published to the host, the weak credential remains available to other containers on the Compose network and can become remotely exploitable if the configuration is later extended or deployed with broader network exposure. These defaults are likely intended for simple examples, but they are unsafe for deployment-oriented documentation because users commonly copy examples without replacing every placeholder. ### Attack Path #### Redis exposure 1. A user deploys the Redis Compose example on a network-reachable host. 2. Docker publishes port 6379 on the host. 3. Host firewall or cloud security-group rules permit access to the port. 4. Redis has no authentication or ACL requirement. 5. An attacker connects directly to Redis. 6. The attacker reads, modifies, or deletes cached agent data and ...[truncated 1048 chars]
Remediation
<![CDATA[ ## Remediation Suggestions 1. Remove Redis host-port publication when only the agent container requires access. 2. Place Redis and PostgreSQL on an internal Compose network and expose only the application service. 3. If Redis must be remotely reachable, configure ACL authentication, TLS, interface restrictions, and firewall allowlists. 4. Replace the hardcoded PostgreSQL password with a required secret variable such as `${POSTGRES_PASSWORD:?required}`. 5. Generate a strong, unique database password and store it in a secret manager or protected environment file. 6. Avoid using a database superuser for the application; create a least-privileged application role. 7. Pin container images to reviewed versions or immutable digests. 8. Add explicit warnings that example credentials are not suitable for production. 9. Include deployment checks that fail when known default credentials are detected. 10. Configure backup, audit logging, credential rotation, and network-policy guidance for production deployments. ]]>
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
Findings (41)

Tp4

High
Category
MCP Tool Poisoning
Confidence
98% confidence
Finding
The declared description focuses on building new Warden/LangGraph agents, preparing them for publishing, and deployment-related workflows. The actual code does not build agents, generate LangGraph logic, prepare publishing artifacts, integrate with Warden Studio, or handle deployments. Instead, it tests an existing agent service over HTTP. That is a materially different primary purpose, so this is a clear description-versus-behavior mismatch.

Credential Access

High
Category
Privilege Escalation
Content
"graphs": {
    "agent": "./src/graph.ts"  // or .py
  },
  "env": ".env"
}
```
Confidence
90% confidence
Finding
The skill instructs users to place API keys in a `.env` file and configures `langgraph.json` to load that file, but it provides no safeguards around secret handling, exclusion from version control, or least-privilege usage. In a code-generation or agent-runner setting, this can lead to accidental exposure of LangSmith, OpenAI, or other API credentials through repository commits, logs, packaging, or unintended file access.

Credential Access

High
Category
Privilege Escalation
Content
"graphs": {
    "agent": "./src/graph.ts"
  },
  "env": ".env"
}""",
            ".env.example": """# OpenAI Configuration
OPENAI_API_KEY=your_openai_key_here
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
"graphs": {
    "agent": "./src/graph.ts"
  },
  "env": ".env"
}""",
            ".env.example": """# OpenAI Configuration
OPENAI_API_KEY=your_openai_key_here
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
"graphs": {
    "agent": "./src/graph.ts"
  },
  "env": ".env"
}""",
            ".env.example": """# OpenAI Configuration
OPENAI_API_KEY=your_openai_key_here
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
"graphs": {
    "agent": "./src/graph.ts"
  },
  "env": ".env"
}""",
            ".env.example": """# OpenAI Configuration
OPENAI_API_KEY=your_openai_key_here
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
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
# WEATHER_API_KEY=""",
            ".gitignore": """node_modules/
dist/
.env
*.log
.DS_Store""",
            "src/graph.ts": """import { StateGraph, END } from "@langchain/langgraph";
Confidence
60% confidence
Finding
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Vague Triggers

Medium
Confidence
96% confidence
Finding
The trigger phrase "LangGraph agent" is overly generic for a skill that is supposed to activate for Warden-specific requests. In a skill-routing system, this can cause the agent to invoke this skill for unrelated LangGraph tasks, unnecessarily exposing downstream instructions, scripts, and deployment guidance outside the intended context and potentially leading to confused-deputy behavior.

Vague Triggers

Medium
Confidence
98% confidence
Finding
The statement that the skill triggers when users mention "Warden or LangGraph agents" creates an ambiguous activation boundary and broadens scope beyond the declared purpose of the skill. In agent ecosystems, such broad routing can misfire on unrelated requests, causing unintended use of specialized crypto/Web3 build instructions and weakening separation between skills.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill includes actionable shell, network, environment-variable, and file-write operations but declares no explicit tool scope or permissions boundary. In an agent-skill context, this increases the chance that a caller or downstream runtime will grant broader capabilities than intended, enabling command execution, outbound requests, and local file modification without clear restriction.

External Transmission

Medium
Category
Data Exfiltration
Content
Test your agent's API:

```bash
curl -X POST http://localhost:8000/invoke \
  -H "Content-Type: application/json" \
  -d '{"input": "test query"}'
```
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Rp1

Medium
Category
MCP Rug Pull
Confidence
75% confidence
Finding
Docker image references without a specific tag (:latest is implicit) or digest (@sha256:...) can be silently replaced by a malicious image.

External Transmission

Medium
Category
Data Exfiltration
Content
apis: {
    coingecko: {
      key: process.env.COINGECKO_API_KEY,
      baseUrl: 'https://api.coingecko.com/api/v3'
    },
    alchemy: {
      key: process.env.ALCHEMY_API_KEY!,
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
},
    weather: {
      key: process.env.WEATHER_API_KEY!,
      baseUrl: 'https://api.weatherapi.com/v1'
    }
  },
  server: {
Confidence
50% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

External Transmission

Medium
Category
Data Exfiltration
Content
All API calls require the `x-api-key` header with your LangSmith API key:

```bash
curl YOUR_AGENT_URL/runs/wait \
  --request POST \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: [YOUR-LANGSMITH-API-KEY]' \
Confidence
60% confidence
Finding
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Missing User Warnings

Medium
Confidence
91% confidence
Finding
The guide recommends request logging for all requests without discussing redaction, minimization, or excluding sensitive routes. In an agent deployment context, request paths and associated logging patterns often expand to include bodies, prompts, API inputs, or user-supplied data later, which can expose secrets, personal data, or confidential prompts in logs.

Intent-Code Divergence

Medium
Confidence
97% confidence
Finding
The manifest context for this skill says it should be used for creating new Warden agents and explicitly notes 'not community examples.' However, the embedded description in this guide says the skill is for building agents using Warden's community templates, which is the opposite of the stated scope. This is a direct documentation-level contradiction about intended behavior.

Static analysis

No suspicious patterns detected.