Back to skill

Security audit

Find Cpa Firm

Security checks for vulnerabilities and agentic risk

Overview

The skill has a clear business-directory purpose, but its REST authentication instructions tell the agent to source a local .env.local file as shell code before calling the API.

Review this skill before installing. The ServiceGraph API use and paid unlock workflow are disclosed, but do not let an agent source .env.local as shell code. Prefer the MCP/OAuth path, or export only SERVICEGRAPH_API_KEY in the process environment and have the agent call the fixed ServiceGraph endpoint without reading or executing dotenv files.

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

T09 · Insecure Skill Coding Practices

Error
Location
SKILL.md:70
Finding

Unsafe Shell Execution Through Sourcing of .env.local

Content
View full analysis

Vulnerability Details

File Location: SKILL.md, lines 70–75
Vulnerability Type: Unsafe execution of environment configuration as shell code
Risk Level: High

Vulnerable Code

bash
1. **Try the call first** through a shell wrapper that sources `.env.local`:

   ```bash
   ( set -a; [ -f .env.local ] && . ./.env.local; set +a;
     curl -sS -H "Authorization: Bearer $SERVICEGRAPH_API_KEY" \
          'https://api.servicegraph.co/v1/datasets/pro_services/fields' )
text

### Technical Analysis

The shell dot command (`. ./.env.local`) does not treat `.env.local` as a passive environment-variable file. It evaluates the file as shell source code in the current shell. Consequently, command substitutions, shell functions, redirections, and arbitrary commands placed in that file execute when the documented authentication procedure is followed.

The use of `set -a` additionally exports every subsequently assigned shell variable to child processes. This exceeds the minimum privilege necessary because the API request requires only `SERVICEGRAPH_API_KEY`. Although the documented `curl` request legitimately sends that key to the declared ServiceGraph HTTPS endpoint, executing the entire environment file is unnecessary for that functionality.

### Attack Path

1. An attacker, compromised development tool, or untrusted project component creates or modifies `.env.local`.
2. The attacker inserts executable shell syntax, such as a command substitution or a standalone command, alongside apparently legitimate environment assignments.
3. A user invokes the Skill to search for or enrich CPA firms.
4. The Agent follows the authentication recipe and runs the supplied shell wrapper.
5. The dot command evaluates the malicious contents before `curl` makes the legitimate API request.
6. The injected commands execute with the operating-system permissions of the Agent process and can access any files, credentials, and network destinations available to that user.

...[truncated 617 chars]
Remediation
View remediation

Remediation Suggestions

  1. Do not source .env.local or any dotenv-style configuration file as shell code.
  2. Prefer the documented sandboxed MCP/OAuth flow so the bearer token remains isolated from the Agent context.
  3. For REST usage, require SERVICEGRAPH_API_KEY to be supplied through an already-exported process environment:
bash
test -n "${SERVICEGRAPH_API_KEY:-}" || {
  printf '%s\n' 'SERVICEGRAPH_API_KEY is not set' >&2
  exit 1
}

curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer ${SERVICEGRAPH_API_KEY}" \
  'https://api.servicegraph.co/v1/datasets/pro_services/fields'
  1. If loading a dotenv file is unavoidable, use a strict parser that accepts only the exact SERVICEGRAPH_API_KEY assignment and rejects command substitution, shell operators, additional variables, multiline values, and executable syntax.
  2. Remove set -a; pass or export only the single variable required for authentication.
  3. Ensure .env.local is excluded from version control, readable only by the owning user, and not writable by untrusted project processes.
  4. Continue transmitting the API token only to the fixed https://api.servicegraph.co origin over validated HTTPS, without redirects to untrusted hosts.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
Findings (2)

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 · SKILL.md (reported line 73)May include surrounding context.

  1. Try the call first through a shell wrapper that sources .env.local:

    bash
    ( set -a; [ -f .env.local ] && . ./.env.local; set +a;
      curl -sS -H "Authorization: Bearer $SERVICEGRAPH_API_KEY" \
           'https://api.servicegraph.co/v1/datasets/pro_services/fields' )
    

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · SKILL.md (reported line 75)May include surrounding context.

bash
   ( set -a; [ -f .env.local ] && . ./.env.local; set +a;
     curl -sS -H "Authorization: Bearer $SERVICEGRAPH_API_KEY" \
          'https://api.servicegraph.co/v1/datasets/pro_services/fields' )
  1. On 401 prompt the user: