Back to skill

Security audit

ia-python-services

Security checks for vulnerabilities and agentic risk

Overview

ClawScan marks this skill benign with high confidence: all seven Markdown components were fully scanned, and the reported concerns were judged low probability and expected or explainable in context.

The verdict is benign, and the scan completed with full coverage of the seven reported components. Before installing, consider whether skill-evaluation and diagnostic commands fit your needs, since the scanner could not establish their implementation or side effects. Benign does not mean risk-free.

Vulnerability Patterns
  • 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
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
Vulnerability Patterns
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
Findings (3)

Description-Behavior Mismatch

High
Category
MCP Tool Poisoning
Confidence
94% confidence
Finding

The supplied commands appear to evaluate and diagnose the named skill, a materially different purpose from assisting with Python application development. The script's implementation is not supplied, so no additional resource access or side effects can be established.

Content

No source excerpt is available for this finding.

Credential Access

High
Category
Privilege Escalation
Confidence
60% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · references/fastapi.md (reported line 21)May include surrounding context.

md
**Lifespan** for startup/shutdown: `@asynccontextmanager async def lifespan(app):`

**Configuration**: `pydantic_settings.BaseSettings` with `model_config = {"env_file": ".env"}`. Required fields = no default (fails fast at boot). `env_nested_delimiter = "__"` for grouped config. `secrets_dir` for Docker/K8s mounted secrets.

**Dependency injection**: `Depends(get_db)` for sessions, `Depends(get_current_user)` for auth. Override in tests: `app.dependency_overrides[get_db] = mock_db`. A `yield` dependency's cleanup runs **after the response is sent** by default (`scope="request"`); `Depends(get_db, scope="function")` closes it when the path operation returns, **before** the response goes out, so a DB session or lock is released without waiting on a slow client. A `"request"`-scoped dependency may only depend on other `"request"`-scoped ones; `"function"` may depend on either.

Unbounded Resource Access

Medium
Category
Excessive Agency
Confidence
80% confidence
Finding

Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.

Content

Scanner excerpt · references/concurrency-and-resilience.md (reported line 105)May include surrounding context.

md
failures.** Module-level `requests.get`/`requests.post` build a fresh `Session` and connection pool per call, so a dead or half-closed socket can never be served; a process-wide `Session` reuses keep-alive connections, and urllib3 does not liveness-probe one before reuse. When an LB or NAT has silently dropped an idle socket (an ALB's default idle timeout is 60s), the next reuse raises `ConnectionError` wrapping urllib3 `ProtocolError` / `http.client.RemoteDisconnected`, and under `HTTPAdapter(max_retries=0)`, chosen to "keep behavior unchanged", it reaches the caller unretried. That claim is true of *response* semantics (status, timeouts, body) and false of *connection-failure* semantics. It bites hardest during traffic lulls, when the connection has been idle past the LB timeout
- **`Retry(connect=1)` does not cover a stale keep-alive**; it is the wrong layer. urllib3 routes errors by class and a stale socket is a *read*/protocol error: `Retry._is_connection_error(ProtocolError('Con