T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/contacts.py:92- Finding
Undocumented Bulk Access to Sensitive Fastmail Contact Data
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This Fastmail skill mostly does what it claims, but it also ships an undocumented contacts tool and allows sensitive email/contact actions with limited built-in safeguards.
Review carefully before installing. Use a least-privilege Fastmail token, avoid granting Contacts scope unless you intentionally want contact access, and require explicit human approval before send, move, trash, or bulk contact commands. Be aware that command output may place email or contact data into agent logs or transcripts.
scripts/contacts.py:92Undocumented Bulk Access to Sensitive Fastmail Contact Data
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
return
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
req = urllib.request.Request("https://api.fastmail.com/jmap/session", headers=headers)
session = json.loads(urllib.request.urlopen(req).read())
ACCOUNT = list(session["accounts"].keys())[0]
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
body = json.dumps({"using": USING, "methodCalls": method_calls}).encode()
req = urllib.request.Request("https://api.fastmail.com/jmap/api/", body, headers, method="POST")
resp = json.loads(urllib.request.urlopen(req).read())
for mr in resp.get("methodResponses", []):
if mr[0] == "error":
print(f"Error: {mr[1].get('type')} — {mr[1].get('description', '')}", file=sys.stderr)
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
return
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
req = urllib.request.Request("https://api.fastmail.com/jmap/session", headers=headers)
session = json.loads(urllib.request.urlopen(req).read())
ACCOUNT = list(session["accounts"].keys())[0]
Credentials or environment variables flow to a network sink. This is a high-confidence indicator of credential exfiltration.
headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}
body = json.dumps({"using": using or USING, "methodCalls": method_calls}).encode()
req = urllib.request.Request(API, body, headers, method="POST")
resp = json.loads(urllib.request.urlopen(req).read())
# Check for errors
for mr in resp.get("methodResponses", []):
if mr[0] == "error":
The declared description says the skill provides email superpowers via Fastmail JMAP, specifically read/search/send/move/trash mail. However, the supplied code only interacts with Fastmail contacts using JMAP Contacts methods (ContactCard/query and ContactCard/get). It requires a token with Contacts scope, fetches the JMAP session, and supports list/search/get for contacts. There is no code for reading email messages, searching mail, sending mail, moving mail between mailboxes, or trashing messages. This is a material description-behavior mismatch because the primary purpose and accessed resource are contacts, not email.
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
}
Or use 1Password injection: `op run --env-file=.env -- python3 scripts/fastmail.py unread`
## How It Works
Referenced artifact was not completely inspected
- `SKILL.md` — this file
The skill declares access to environment variables and networked email operations but does not define an explicit tool/permission scope. That makes the skill harder to sandbox and review, and increases the chance an agent can invoke sensitive capabilities beyond what a user expects. In an email skill, unclear scoping is especially risky because it combines secret handling (API tokens) with read/write access to private communications.
The skill advertises full email read/write capability, including destructive actions like move and trash, without a prominent privacy and safety warning. Users may not appreciate that granting the token enables access to all mailbox contents and allows irreversible or hard-to-audit actions on sensitive communications. For an agent skill, this can lead to overbroad delegation and accidental data exposure or mailbox tampering.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
python3 scripts/fastmail.py send "user@example.com" "Subject" "Body text"
### In heartbeat/cron:
This code makes authenticated network requests to Fastmail and sends user-supplied queries plus retrieves contact records, but the skill provides no explicit user-facing warning that contact data will be transmitted to an external service. The module docstring notes the required token, but it does not disclose the privacy impact of network access to personal contact information.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print("Get one at: https://app.fastmail.com/settings/security/tokens", file=sys.stderr)
sys.exit(1)
API = "https://api.fastmail.com/jmap/api/"
USING = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"]
USING_SEND = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:submission"]
ACCOUNT = None
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print("Get one at: https://app.fastmail.com/settings/security/tokens", file=sys.stderr)
sys.exit(1)
API = "https://api.fastmail.com/jmap/api/"
USING = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"]
USING_SEND = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:submission"]
ACCOUNT = None
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print("Get one at: https://app.fastmail.com/settings/security/tokens", file=sys.stderr)
sys.exit(1)
API = "https://api.fastmail.com/jmap/api/"
USING = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"]
USING_SEND = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:submission"]
ACCOUNT = None
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
print("Get one at: https://app.fastmail.com/settings/security/tokens", file=sys.stderr)
sys.exit(1)
API = "https://api.fastmail.com/jmap/api/"
USING = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"]
USING_SEND = ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:submission"]
ACCOUNT = None
Move and trash operations change mailbox state immediately without confirmation, undo guidance, or safety interlocks. In an autonomous-agent setting this can lead to accidental message loss, hiding important emails, or destructive actions triggered by prompt injection or misclassification of user intent.
The send command can transmit arbitrary email contents immediately with no confirmation prompt, dry-run mode, or policy check. In an agent context, this increases the risk of unintended outbound communication, data leakage, or social-engineering messages being sent if the tool is invoked from ambiguous or prompt-injected instructions.
No suspicious patterns detected.