Back to skill

Security audit

Ziptax Sales Tax

Security checks for vulnerabilities and agentic risk

Overview

The skill is a coherent ZipTax lookup helper, but its bundled script has unsafe address handling that can run injected local commands and it places the API key in a URL for metrics.

Review before installing. Avoid or patch scripts/lookup.sh before using it with user-controlled addresses, prefer direct API calls with header-based authentication, do not put the API key in query strings, and make sure users understand that precise addresses or coordinates will be sent to ZipTax.

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
scripts/lookup.sh:58
Finding
Arbitrary Python Code Execution Through an Unsafely Interpolated Address## Vulnerability Details **File Location**: `scripts/lookup.sh:58-61` **Vulnerability Type**: Command injection through dynamically generated Python source code **Risk Level**: High ```bash if [[ -n "$ADDRESS" ]]; then ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$ADDRESS'))") curl -s "${BASE_URL}/request/${VERSION}?address=${ENCODED}" \ -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool ``` ### Technical Analysis The value of `ADDRESS` is controlled by the `--address` command-line argument and is interpolated directly into the source code passed to `python3 -c`. Shell quoting prevents ordinary shell word splitting, but it does not make the resulting Python program safe. An address containing a single quote and valid Python syntax can terminate the intended string literal and append arbitrary Python statements. The Python interpreter then executes those statements with the same operating-system identity, environment variables, filesystem permissions, and network access as the script. This behavior is not necessary for URL encoding. User data should be passed to Python through an argument or standard input, never embedded into executable source code. ### Attack Path 1. An attacker influences the address supplied to the Skill or persuades a user or agent to perform a lookup using a crafted address. 2. The attacker supplies Python syntax that closes the quoted address and adds a statement, for example: ```text ')); __import__("os").system("id"); # ``` 3. The shell expands the crafted value inside the `python3 -c` argument. 4. Python parses the injected text as executable source code. 5. The injected operating-system command runs before the ZipTax request is made. The payload could replace `id` with commands that read accessible files, inspect environment variables, make outbound requests, or modify resources writable by the current account. ### Impact Assessment ...[truncated 568 chars]
Remediation
## Remediation Suggestions Pass the address as a data argument rather than inserting it into Python source: ```bash ENCODED=$( python3 -c 'import sys, urllib.parse; print(urllib.parse.quote(sys.argv[1]))' \ "$ADDRESS" ) ``` Alternatively, use a URL-aware HTTP client that accepts query parameters separately. Apply strict argument-count checks before reading `$2`, validate lookup inputs according to their expected formats, and add regression tests containing quotes, semicolons, newlines, command substitutions, and Python syntax. The tests should verify that such input is encoded as data and never executed.

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/lookup.sh:53
Finding
ZipTax API Key Exposed in the Metrics Request URL## Vulnerability Details **File Location**: `scripts/lookup.sh:53-56` **Vulnerability Type**: Sensitive credential transmitted in a URL query parameter **Risk Level**: Medium ```bash if $METRICS; then curl -s "${BASE_URL}/account/metrics?key=${ZIPTAX_API_KEY}" | python3 -m json.tool exit 0 fi ``` Related documentation also endorses query-parameter authentication: - `SKILL.md:48`: `Auth: Header X-API-KEY or query param key` - `references/api-reference.md:5-8`: API keys may be supplied through a query parameter. ### Technical Analysis The metrics operation embeds `ZIPTAX_API_KEY` directly into the request URL even though the project already supports the safer `X-API-KEY` request header. HTTPS protects the URL while it is in transit, but it does not prevent exposure at either endpoint or within local process metadata. URLs are commonly retained by server access logs, reverse proxies, observability systems, debugging tools, HTTP-client diagnostics, and command histories. While `curl` is running, its URL argument may also be observable through process-inspection facilities by users or monitoring software with sufficient local access. Query-string authentication is unnecessary for the declared functionality because the same API accepts header authentication. ### Attack Path 1. A user exports a valid `ZIPTAX_API_KEY` and runs `lookup.sh --metrics`. 2. The script constructs a URL containing the complete secret. 3. The URL is supplied to `curl` as a process argument and sent to the ZipTax endpoint. 4. A local process observer, API access-log reader, reverse-proxy operator, diagnostic collector, or monitoring-system user obtains the recorded URL. 5. The observer extracts the `key` parameter and reuses the API credential for unauthorized requests until it is revoked or rotated. ### Impact Assessment Exposure permits unauthorized use of the affected ZipTax account within the permissions associated with the API k ...[truncated 357 chars]
Remediation
## Remediation Suggestions Send the API key exclusively through the existing authentication header: ```bash if $METRICS; then curl -s "${BASE_URL}/account/metrics" \ -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool exit 0 fi ``` Remove query-parameter authentication recommendations from `SKILL.md` and `references/api-reference.md`, and update examples to use `X-API-KEY`. Ensure that application and proxy logging policies redact authentication headers. Rotate any API key that may already have been captured in URL or process-monitoring logs.
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
  • MCP Least PrivilegeUnderdeclared Capability, Wildcard Permission, Missing Permission Declaration
  • MCP Tool PoisoningHidden Instructions, Unicode Deception, Parameter Description Injection
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (14)

External Script Fetching

High
Category
Supply Chain
Content
fi

if $METRICS; then
  curl -s "${BASE_URL}/account/metrics?key=${ZIPTAX_API_KEY}" | python3 -m json.tool
  exit 0
fi
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
if [[ -n "$ADDRESS" ]]; then
  ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$ADDRESS'))")
  curl -s "${BASE_URL}/request/${VERSION}?address=${ENCODED}" \
    -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool
elif [[ -n "$LAT" && -n "$LNG" ]]; then
  curl -s "${BASE_URL}/request/${VERSION}?lat=${LAT}&lng=${LNG}" \
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
curl -s "${BASE_URL}/request/${VERSION}?address=${ENCODED}" \
    -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool
elif [[ -n "$LAT" && -n "$LNG" ]]; then
  curl -s "${BASE_URL}/request/${VERSION}?lat=${LAT}&lng=${LNG}" \
    -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool
elif [[ -n "$POSTALCODE" ]]; then
  curl -s "${BASE_URL}/request/${VERSION}?postalcode=${POSTALCODE}" \
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

External Script Fetching

High
Category
Supply Chain
Content
curl -s "${BASE_URL}/request/${VERSION}?lat=${LAT}&lng=${LNG}" \
    -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool
elif [[ -n "$POSTALCODE" ]]; then
  curl -s "${BASE_URL}/request/${VERSION}?postalcode=${POSTALCODE}" \
    -H "X-API-KEY: ${ZIPTAX_API_KEY}" | python3 -m json.tool
else
  echo "Error: Provide --address, --lat/--lng, or --postalcode" >&2
Confidence
90% confidence
Finding
Remote code is downloaded and executed. This bypasses code review and could introduce malicious code.

Lp3

Medium
Category
MCP Least Privilege
Confidence
92% confidence
Finding
The skill documents shell and network-based behavior but does not declare any explicit tool scope or permissions boundary. This can lead to overbroad execution in an agent environment, making external requests and shell invocation possible without clear least-privilege constraints or reviewer visibility.

External Transmission

Medium
Category
Data Exfiltration
Content
### Address Lookup (most accurate)
```bash
curl -s "https://api.zip-tax.com/request/v60?address=200+Spectrum+Center+Drive+Irvine+CA+92618" \
  -H "X-API-KEY: $ZIPTAX_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
### Address Lookup (most accurate)
```bash
curl -s "https://api.zip-tax.com/request/v60?address=200+Spectrum+Center+Drive+Irvine+CA+92618" \
  -H "X-API-KEY: $ZIPTAX_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
### Address Lookup (most accurate)
```bash
curl -s "https://api.zip-tax.com/request/v60?address=200+Spectrum+Center+Drive+Irvine+CA+92618" \
  -H "X-API-KEY: $ZIPTAX_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
### Address Lookup (most accurate)
```bash
curl -s "https://api.zip-tax.com/request/v60?address=200+Spectrum+Center+Drive+Irvine+CA+92618" \
  -H "X-API-KEY: $ZIPTAX_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
### cURL
```bash
curl -X GET "https://api.zip-tax.com/request/v60?address=200+Spectrum+Center+Drive+Irvine+CA+92618" \
  -H "X-API-KEY: YOUR_API_KEY"
```
Confidence
85% confidence
Finding
The cURL sample shows external transmission of a full street address to a third-party endpoint. External transmission is expected for this skill's purpose, but in an agent context it is still security-relevant because it may send user-provided sensitive location information off-platform, and the example also documents support for query-parameter API keys elsewhere, which increases risk of accidental secret exposure if copied naively.

External Transmission

Medium
Category
Data Exfiltration
Content
```python
import requests
resp = requests.get(
    "https://api.zip-tax.com/request/v60",
    params={"address": "200 Spectrum Center Drive Irvine CA 92618"},
    headers={"X-API-KEY": "YOUR_API_KEY"}
)
Confidence
86% confidence
Finding
The Python sample performs an outbound request containing a full address to an external API. This is functionally necessary for the skill, but it still represents a real data egress path for sensitive user location data in an agent environment, especially if callers automatically forward user-entered addresses without notice or policy checks.

External Transmission

Medium
Category
Data Exfiltration
Content
### JavaScript
```javascript
const resp = await fetch(
  "https://api.zip-tax.com/request/v60?address=200+Spectrum+Center+Drive+Irvine+CA+92618",
  { headers: { "X-API-KEY": "YOUR_API_KEY" } }
);
const data = await resp.json();
Confidence
86% confidence
Finding
The JavaScript sample sends a full address to a third-party service, creating an external data transmission channel. Within this skill's context that behavior is expected, but it remains a meaningful privacy/security concern because an integrator may unknowingly pass sensitive user location data to the vendor without disclosure, and copied examples may normalize unsafe practices.

Missing User Warnings

Low
Confidence
83% confidence
Finding
The documentation encourages sending full street addresses and precise coordinates to a third-party API without any privacy, retention, or consent guidance. In the context of an agent skill, this can cause transmission of sensitive location data derived from user input to an external service, increasing privacy and compliance risk if users are not warned or data minimization is not applied.

Description-Behavior Mismatch

Low
Confidence
89% confidence
Finding
The manifest describes the skill as looking up U.S. sales tax rates across U.S. jurisdictions, but the referenced documentation explicitly states that Canadian GST/HST/PST rates are available and EU VAT is in development. That broadens the represented capability beyond the skill's declared U.S.-focused scope.

Static analysis

No suspicious patterns detected.