T05 · Unauthorized Access and Privilege Escalation
- Location
SKILL.md:119- Finding
Sensitive CRM Data and API Credentials Are Routed Through a Third-Party Proxy
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This skill is a read-only Pipedrive helper, but it routes sensitive CRM data and a bearer API key through a third-party proxy with limited security and scoping detail.
Install only if your organization approves api.maton.ai as a processor for Pipedrive CRM data. Use a narrowly scoped, revocable key, avoid broad list queries unless needed, do not print MATON_API_KEY, and rotate the key if it appears in logs or chat transcripts.
SKILL.md:119Sensitive CRM Data and API Credentials Are Routed Through a Third-Party Proxy
SKILL.md:324Troubleshooting Instructions Expose the Complete API Key in Terminal Output
The documentation states that an API proxy handles OAuth, but it does not prominently warn users that CRM queries and metadata are sent to an external third-party proxy endpoint. Because the queried data includes sales opportunities, contacts, organizations, and activities, this omission can cause users or agents to transmit sensitive CRM data without informed consent or proper governance review.
The keyword coverage list includes very broad and common terms such as 'Skill', 'Agent', 'API', 'Use', and 'LLM', which can spur unintended invocation far outside CRM workflows. In an agent ecosystem, this raises the risk of accidental access to external CRM data and unnecessary transmission of sensitive business information through the proxy service.
The activation guidance says the skill should be used broadly for AI model calling, orchestration, and LLM applications, which is much wider than the actual CRM query purpose. Overbroad routing criteria can cause the agent to invoke this skill in unrelated contexts, exposing CRM-connected capabilities and credentials when they were not needed.
The skill repeatedly markets the free edition as read-only, but later sections describe input modes that support create/modify/export/import operations. This inconsistency can mislead an agent or operator into attempting state-changing or data-export actions against CRM resources, weakening trust boundaries and increasing the chance of unintended data handling.
This example instructs the agent to send deal query data and a bearer credential to api.maton.ai, an external proxy service. Even though it is framed as normal operation, it results in off-environment transmission of CRM data and authentication material, which is sensitive in a sales/CRM context.
# 1. 列出所有open商机
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/deals?status=open')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
This contact-search example sends potentially sensitive personal/contact data queries to an external proxy endpoint. In a CRM setting, contact records often contain personal data, making third-party transmission a meaningful privacy and governance concern.
# 2. 搜索联系人
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/persons/search?term=john')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
This pipeline query example still transmits business metadata and the bearer token to an external service. While less sensitive than full contact records, it discloses internal sales process structure and relies on a third-party proxy not highlighted as a risk to the user.
# 3. 查看管道列表
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/pipelines')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
The base URL section explicitly confirms that all requests are forwarded through api.maton.ai and that the proxy injects OAuth tokens. This creates a trust dependency on a third-party intermediary for all CRM traffic, which is risky when handling commercial and contact data.
所有请求通过API代理服务转发到Pipedrive API,代理自动注入OAuth Token:
基础URL: https://api.maton.ai/pipedrive/{原生API路径}
认证头: Authorization: Bearer $MATON_API_KEY
This example transmits deal-listing requests and credentials to the external proxy service. Deal data can reveal pipeline status, revenue expectations, and customer relationships, so external routing materially increases exposure.
# 列出所有商机
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/deals')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Filtering open deals through the proxy still sends sensitive sales pipeline data off-platform. The operational context makes this more dangerous because even read-only sales data can be commercially sensitive and often subject to confidentiality controls.
# status: open, won, lost, deleted, all_not_deleted
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/deals?status=open&limit=50')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Fetching a specific deal by ID through the proxy can reveal detailed opportunity information to a third party, along with the bearer credential used to authorize access. This is a real exposure path even if the skill only intends read-only use.
# 查看指定商机详情
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/deals/123')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Searching deals by term sends user-entered business keywords and matching CRM records to an external proxy. Search terms themselves may contain confidential account names, project names, or strategic opportunities.
# 搜索商机
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/deals/search?term=enterprise')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Listing persons through a third-party proxy exposes contact information, which may include personal data regulated by privacy requirements. The fact that the skill is designed for CRM retrieval makes this more sensitive than generic external HTTP access.
# 列出联系人
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/persons?limit=50')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Retrieving a specific person record through the proxy can expose detailed personal and relationship data to a third party. This is a concrete confidentiality risk because CRM person records often contain direct identifiers and activity history.
# 查看联系人详情
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/persons/123')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Searching persons by name sends personal identifiers and resulting contact data to the proxy service. This increases the privacy risk surface and may conflict with organizational restrictions on sharing customer data with intermediaries.
# 搜索联系人
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/persons/search?term=john')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Organization listing requests reveal customer/account portfolio information to an external service. Even absent personal data, account names and business relationships are often commercially sensitive.
# 列出组织
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/organizations')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Fetching a specific organization record through the proxy exposes detailed account information externally. In CRM workflows, this can include strategic customer and revenue-related data that should not be silently relayed to third parties.
# 查看组织详情
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/organizations/456')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Activity listings can contain operational timelines, customer interactions, and employee work details, all of which are sent to the external proxy here. That makes the example a real confidentiality risk in the stated sales-management context.
# 列出活动
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/activities')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Filtering activities by type still sends potentially sensitive interaction metadata to the proxy. Such metadata can reveal business operations and customer engagement patterns even without full record content.
# 按类型过滤活动
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/activities?type=call')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Querying unfinished activities via the external proxy reveals current tasks and operational status. In a sales environment, this may expose live priorities, customer engagement state, and internal work patterns.
# 按完成状态过滤
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/activities?done=0')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Pipeline listings disclose internal sales process structure to the proxy service. While not as sensitive as personal records, this still reveals business methodology and depends on a third-party intermediary for access.
# 列出所有管道
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/pipelines')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Stage queries expose sales funnel configuration and associated access tokens to an external endpoint. The context makes this a genuine exposure, because internal process metadata can be valuable competitive intelligence.
# 列出阶段(按管道过滤)
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/stages?pipeline_id=1')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"
Paginated deal queries still transmit commercially sensitive CRM data and authentication credentials to the external proxy. The example normalizes third-party relay without adequate security warning, which increases the likelihood of unreviewed data disclosure.
# 使用start和limit参数分页
python -c "
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/pipedrive/api/v1/deals?start=0&limit=50&sort=add_time%20DESC')
req.add_header('Authorization', f'Bearer {os.environ[\"MATON_API_KEY\"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
"