Back to skill

Security audit

KallyAI Executive Assistant (Claude Code)

Security checks for vulnerabilities and agentic risk

Overview

This skill matches its stated assistant purpose, but it gives a broadly triggered agent authority to perform real-world actions like calls, emails, bookings, outreach, phone-number changes, and billing-related changes without clear enough confirmation boundaries.

Review this carefully before installing. Use it only if you are comfortable granting KallyAI access to private communications and account actions, and avoid letting the broad ask command run without first confirming recipients, costs, affected accounts, and any irreversible actions such as releasing a phone number or changing connected channels/subscriptions.

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

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/kallyai.py:108
Finding

OAuth Tokens Exposed Through URL Query Parameters and Non-Atomic Credential File Permissions

Content
View full analysis

Vulnerability Details

File Location: scripts/kallyai.py:108-115 and scripts/kallyai.py:145-148
Vulnerability Type: OAuth credential exposure and insecure local secret-file creation
Risk Level: Medium

Vulnerable Code

python
def save_token(access_token: str, refresh_token: str = None, expires_in: int = 3600):
    """Save token securely (0600 permissions)."""
    TOKEN_FILE.write_text(json.dumps({
        "access_token": access_token,
        "refresh_token": refresh_token,
        "expires_at": time.time() + expires_in - 60,
    }))
    TOKEN_FILE.chmod(0o600)
python
if "access_token" in params:
    auth_result["access_token"] = params["access_token"][0]
    auth_result["refresh_token"] = params.get("refresh_token", [None])[0]
    auth_result["state"] = params.get("state", [None])[0]

The corresponding OAuth flow is documented in references/api-reference.md:47-57:

text
GET /v1/auth/cli?redirect_uri=http://localhost:PORT&state=OPTIONAL_STATE

After authentication, redirects to:

http://localhost:PORT?access_token=TOKEN&refresh_token=TOKEN&expires_in=3600&state=STATE

Technical Analysis

The OAuth callback transports both the access token and refresh token in the URL query string. Query parameters can be retained in browser history and may be visible to browser extensions, local browser telemetry, diagnostic tooling, or other software that records navigated URLs. A refresh token is particularly sensitive because it can potentially be exchanged for new access tokens after the original access token expires.

The credential file is also written before restrictive permissions are applied. Path.write_text() creates or truncates the file using permissions derived from the process umask, and chmod(0o600) is only called after the sensitive contents have been written. This produces a race window during which another local account may be able to ...[truncated 2075 chars]

Remediation
View remediation

Remediation Suggestions

  1. Replace query-parameter token delivery with OAuth 2.0 Authorization Code Flow with PKCE.
    • Return only a short-lived, single-use authorization code to the localhost callback.
    • Exchange the code and PKCE verifier for tokens through a TLS-protected back-channel request.
    • Do not place access tokens or refresh tokens in URLs.
  2. Make the OAuth state parameter mandatory at both the client and server.
  3. Return browser responses with restrictive headers, including Cache-Control: no-store, Pragma: no-cache, and an appropriate Referrer-Policy.
  4. Create credential files with restrictive permissions before writing secrets. Use os.open() with mode 0o600, then wrap the descriptor for writing.
  5. Prefer an atomic update strategy:
    • Create a temporary file in the same directory with mode 0o600.
    • Write and flush the credential data.
    • Optionally call fsync().
    • Atomically replace the destination with os.replace().
  6. Before reading an existing credential file, verify that it is owned by the current user, is a regular file rather than a symbolic link, and has no group or world permissions.
  7. Where available, store refresh tokens in the operating system's credential manager instead of a plaintext JSON file.
  8. Revoke existing tokens after migrating the authentication flow.

T08 · Insecure Dependencies

Note
Location
scripts/kallyai.py:31
Finding

Unpinned Third-Party Dependency Installation Guidance

Content
View full analysis

Vulnerability Details

File Location: scripts/kallyai.py:31-35
Vulnerability Type: Unconstrained third-party dependency installation
Risk Level: Low

Vulnerable Code

python
try:
    import httpx
except ImportError:
    print(json.dumps({"error": {"code": "missing_dependency", "message": "httpx is required. Install with: pip install httpx"}}))
    sys.exit(1)

Technical Analysis

When httpx is unavailable, the CLI instructs users to install it using an unconstrained pip install httpx command. The project does not provide a reviewed lockfile, an exact version constraint, or package hashes in the audited directory.

Consequently, the version installed at execution time is determined by the package index and dependency resolver rather than by the version reviewed with this project. A future compromised, malicious, or behaviorally incompatible release of httpx or one of its transitive dependencies could therefore be installed.

The package name itself is correctly spelled, and the reviewed project does not configure an untrusted package index or automatically execute the installation command. This lowers the severity, but it does not eliminate the supply-chain risk.

Attack Path

  1. A user runs the CLI in an environment where httpx is not installed.
  2. The CLI displays the recommendation to run pip install httpx.
  3. The user executes that command against the configured Python package index.
  4. The resolver installs the latest available package and transitive dependencies without validating them against project-controlled hashes.
  5. If a resolved package version or transitive dependency has been compromised, malicious code can execute during installation, import, or normal HTTP-client operation.
  6. That code runs with the privileges of the user who performed the installation or invoked the CLI.

Exploitation depends on compromise of the package source, dependency chain, or pack ...[truncated 684 chars]

Remediation
View remediation

Remediation Suggestions

  1. Add a dependency manifest that constrains httpx and all relevant transitive dependencies to reviewed versions.
  2. Generate a lockfile or hash-locked requirements file and require integrity verification during installation.
  3. Replace the generic instruction with a project-specific installation command, such as installation from the audited lockfile.
  4. Use an isolated virtual environment rather than recommending global or privileged package installation.
  5. Configure trusted package indexes explicitly in deployment documentation and avoid dependency resolution from untrusted extra indexes.
  6. Establish automated dependency scanning and a controlled update process so pinned versions receive timely security updates after review.
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Tool MisuseTool Parameter Abuse, Chaining Abuse, Unsafe Defaults
Findings (26)

Vague Triggers

High
Category
Not specified by scanner
Confidence
98% confidence
Finding

The manifest description includes extremely broad trigger phrases like email, search, book, find, schedule, messages, research, assistant, and calendar, which overlap heavily with ordinary user requests. This makes accidental or overly broad invocation likely, and because the skill can perform charged, privacy-sensitive, and account-affecting actions, unintended activation can lead directly to external actions without sufficient user intent.

Content

No source excerpt is available for this finding.

Missing User Warnings

High
Category
Not specified by scanner
Confidence
97% confidence
Finding

The skill advertises capabilities to send emails, handle calls, manage messages, provision phone numbers, order services, and perform billing-related tasks, but it does not prominently warn about privacy exposure, financial cost, external communications, or irreversible side effects before those actions occur. In this context, users may unknowingly authorize actions that affect third parties, spend credits or money, or expose sensitive personal data.

Content

No source excerpt is available for this finding.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 539)May include surrounding context.

md
### Delete Inbound Calls

**`DELETE /v1/inbound/calls`**

Bulk delete inbound call records.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 661)May include surrounding context.

md
### Delete Routing Rule

**`DELETE /v1/inbound/rules/{rule_id}`**

---

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 717)May include surrounding context.

md
### Delete Contact

**`DELETE /v1/inbound/contacts/{contact_id}`**

---

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 856)May include surrounding context.

md
### Remove Call Forwarding

**`DELETE /v1/phone-numbers/{phone_number_id}/forwarding`**

---

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

This endpoint permanently releases a phone number and the documentation notes it 'cannot be undone,' yet no explicit warning about confirmation or anti-automation safeguards is shown. In an agentic skill that manages telephony resources, destructive irreversible actions are more dangerous because a misinterpreted prompt or prompt injection could disrupt inbound/outbound communications and cause loss of a business-critical number.

Content

Scanner excerpt · references/api-reference.md (reported line 887)May include surrounding context.

md
### Release Phone Number

**`DELETE /v1/phone-numbers/{phone_number_id}`**

Releases the phone number (cannot be undone).

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 929)May include surrounding context.

md
#### Delete Event

**`DELETE /v1/actions/calendar/events/{event_id}`**

---

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 989)May include surrounding context.

md
#### Cancel Booking

**`DELETE /v1/actions/bookings/{booking_id}`**

---

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 1324)May include surrounding context.

md
### Disconnect Account

**`DELETE /v1/email/accounts/{account_id}`**

---

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 1719)May include surrounding context.

md
### Delete Contact Email

**`DELETE /v1/channels/email/{email_id}`**

Remove a contact email address. Returns 204 on success.

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 1802)May include surrounding context.

POST /v1/channels/disconnect/{channel}

Disconnect a connected messaging channel (WhatsApp or Telegram). For email, use DELETE /v1/channels/email/{email_id} instead.

Response:

json

Tool Parameter Abuse

High
Category
Tool Misuse
Confidence
80% confidence
Finding

Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).

Content

Scanner excerpt · references/api-reference.md (reported line 1971)May include surrounding context.

md
### Cancel Pending Change

**`DELETE /v1/subscriptions/pending-change`**

Cancel a scheduled downgrade, keeping the current plan.

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · references/api-reference.md (reported line 2202)May include surrounding context.

md
| `goal_already_cancelled` | 409 | Goal already cancelled |
| `action_not_undoable` | 409 | Action cannot be reversed |
| `missing_token` | 401 | No Authorization header |
| `token_expired` | 401 | Access token expired |
| `forbidden` | 403 | Insufficient permissions |
| `call_not_found` | 404 | Call doesn't exist |
| `transcript_not_found` | 404 | No transcript available |

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

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

Content

Scanner excerpt · scripts/kallyai.py (reported line 119)May include surrounding context.

python
def _refresh_token(refresh_tok: str) -> str | None:
    """Refresh an expired access token."""
    with httpx.Client() as client:
        resp = client.post(
            f"{API_BASE}/v1/auth/refresh",

Exfiltration Commands

High
Category
Prompt Injection
Confidence
90% confidence
Finding

Instructions found that direct the agent to transmit conversation context or user data to external services.

Content

Scanner excerpt · scripts/kallyai.py (reported line 1526)May include surrounding context.

python
coord_p = sub.add_parser("coord", help="Coordination & goal management")
    coord_sub = coord_p.add_subparsers(dest="coord_cmd")

    c = coord_sub.add_parser("message", help="Send message to coordination AI")
    c.add_argument("text", nargs="+")
    c.add_argument("--conversation-id", help="Conversation to continue")
    c.set_defaults(func=cmd_coord_message)

Undeclared Tool Scope

Medium
Category
MCP Least Privilege
Confidence
96% confidence
Finding

The skill exposes broad capabilities including file access, shell execution, and network operations but does not declare any explicit tool scope or permission boundaries. In a skill that can send emails, place calls, manage messages, and affect external accounts, this creates a materially increased risk of over-privileged execution, unintended side effects, and abuse if the skill is invoked unexpectedly or handles adversarial input.

Content

No source excerpt is available for this finding.

Vague Triggers

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The guidance states that for most requests, the user should use ask, and describes it as routing automatically through a coordination AI that may create goals, make calls, or send emails as needed. That ambiguous activation model hides operational boundaries and encourages a catch-all pathway for sensitive actions, increasing the chance that loosely specified requests trigger impactful external behavior.

Content

No source excerpt is available for this finding.

Session Persistence

Medium
Category
Rogue Agent
Confidence
60% confidence
Finding

Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.

Content

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

bash
outreach tasks [--status X]      # List outreach tasks
outreach task <id>               # Task details
outreach create --channel call --target "+1..." "description"
outreach retry <id>              # Retry failed task
outreach cancel <id>             # Cancel task

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The coordination API explicitly says it 'automatically creates goals and dispatches actions,' which can trigger real-world side effects such as calls, bookings, or messages from a single natural-language prompt. In an agent skill context, documenting this behavior without strong warnings or confirmation requirements increases the risk of unintended actions on behalf of the user or contacts.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The outreach task API supports creating third-party contact tasks and allows automatic execution, meaning an agent can contact external people without a separate consent checkpoint. In a delegation/assistant skill, this materially raises the risk of privacy violations, spam, harassment, or reputational damage if instructions are misinterpreted or prompt-injected.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
95% confidence
Finding

The auto_execute parameter enables autonomous initiation of outreach without a mandatory review step, which is risky because it can convert model output directly into phone calls or messages to real people. In this skill, that capability is especially dangerous because the product is designed to act across multiple channels and make contact decisions on the user's behalf.

Content

Scanner excerpt · references/api-reference.md (reported line 1900)May include surrounding context.

"recipient_name": "Dr. Smith", "urgency": "high", "coordination_message_id": "optional-msg-id", "auto_execute": true }

text

Intent-Code Divergence

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The docstring says email sending is 'queued for approval,' but the implementation directly calls a send endpoint. If users or higher-level agents rely on the approval guarantee, this mismatch can cause unintended outbound email actions, creating a consent and integrity risk for a high-impact communication channel.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
96% confidence
Finding

The backward-compatibility argument parser sets the default language to "es", causing calls invoked via legacy flags to use Spanish unless the user explicitly overrides it. This is a natural-language locale policy issue because the tool imposes a specific language by default rather than offering a neutral default or requiring user choice.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

The main calls make command defines --language with default="es", so outbound calls will be conducted in Spanish unless the user notices and changes the setting. This forces a specific language choice in a general-purpose skill and can violate language/locale policy expectations.

Content

No source excerpt is available for this finding.

Static analysis

No suspicious patterns detected.