Back to skill

Security audit

bigin-crm-skill

Security checks for vulnerabilities and agentic risk

Overview

This appears to be a real Bigin CRM integration, but it needs Review because it stores offline CRM tokens, requests broader OAuth access than the code uses, and can change live CRM data in bulk without strong safeguards.

Review before installing for production use. Use a Bigin sandbox first, keep OAuth client secrets and token files out of shared repos and backups, remove unnecessary settings scope if possible, and fix the OAuth callback to use state validation and loopback binding. Treat bulk update, auto-advance, delete, and close-won/close-lost commands as live business-data changes that should be previewed and approved.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • 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/auth.py:55
Finding

OAuth Callback Is Exposed to Login CSRF and Network-Based Code Injection

Content
View full analysis
str: """ Generate authorization URL for Bigin Returns: Authorization URL string """ return ( f"https://accounts.zoho.{self.dc}/oauth/v2/auth?" f"scope={self.scope}&" f"client_id={self.client_id}&" f"response_type=code&" f"access_type=offline&" f"redirect_uri={self.redirect_uri}" ) def start_auth_flow(self) -> Dict[str, Any]: """ Start local server and authenticate via browser Returns: Token dictionary with access_token and refresh_token """ auth_code = None class CallbackHandler(http.server.BaseHTTPRequestHandler): def do_GET(handler_self): nonlocal auth_code query = urllib.parse.urlparse(handler_self.path).query params = urllib.parse.parse_qs(query) if 'code' in params: auth_code = params['code'][0] handler_self.send_response(200) handler_self.send_header('Content-type', 'text/html') handler_self.end_headers() handler_self.wfile.write(b"""

Authentication Successful!

You can close this window and return to the terminal.

""") else: handler_self.send_response(400) handler_self.end_headers() handler_self.wfile.write(b"Authentication failed. No code received.") def log_message(self, format, *args): # Suppress default logging pass # Open browser for authent ...[truncated 2979 chars]
Remediation
View remediation

T05 · Unauthorized Access and Privilege Escalation

Warning
Location
scripts/auth.py:41
Finding

OAuth Scope Includes Unnecessary Full Bigin Settings Access

Content
View full analysis
Remediation
View remediation
Vulnerability Patterns
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Rogue AgentSelf-Modification, Session Persistence
  • Trigger AbuseOverly Broad Trigger, Shadow Command Trigger, Keyword Baiting Trigger
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
Findings (40)

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/auth.py (reported line 241)May include surrounding context.

python
if int(time.time()) - saved_at >= expires_in - 300:
            # Token expired or about to expire, refresh it
            print("Access token expired. Refreshing...")
            refresh_token = tokens.get("refresh_token")
            if not refresh_token:
                raise ValueError("No refresh token available. Please re-authenticate.")

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/auth.py (reported line 160)May include surrounding context.

python
Initialize Bigin CRM client
        
        Args:
            auth_token: OAuth2 access token
            dc: Data center - com, eu, in, au, jp, uk, ca, etc.
        """
        self.base_url = f"https://www.zohoapis.{dc}/bigin/v2"

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/auth.py (reported line 218)May include surrounding context.

python
Initialize Bigin CRM client
        
        Args:
            auth_token: OAuth2 access token
            dc: Data center - com, eu, in, au, jp, uk, ca, etc.
        """
        self.base_url = f"https://www.zohoapis.{dc}/bigin/v2"

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/auth.py (reported line 221)May include surrounding context.

python
Initialize Bigin CRM client
        
        Args:
            auth_token: OAuth2 access token
            dc: Data center - com, eu, in, au, jp, uk, ca, etc.
        """
        self.base_url = f"https://www.zohoapis.{dc}/bigin/v2"

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/auth.py (reported line 285)May include surrounding context.

python
Initialize Bigin CRM client
        
        Args:
            auth_token: OAuth2 access token
            dc: Data center - com, eu, in, au, jp, uk, ca, etc.
        """
        self.base_url = f"https://www.zohoapis.{dc}/bigin/v2"

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/bigin_crm.py (reported line 36)May include surrounding context.

python
Initialize Bigin CRM client
        
        Args:
            auth_token: OAuth2 access token
            dc: Data center - com, eu, in, au, jp, uk, ca, etc.
        """
        self.base_url = f"https://www.zohoapis.{dc}/bigin/v2"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The README instructs users to place OAuth client credentials, including a client secret, into a local JSON config file without guidance on secret handling, exclusion from source control, or secure storage. This increases the risk of credential leakage through git commits, backups, shared workstations, or artifact packaging, which could enable unauthorized API access if the credentials are exposed.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

The usage examples include create, update, win/lose, advance, and bulk-update commands that modify live CRM records, but the markdown does not warn users that these actions change production data or recommend using a sandbox first during operation. Under the markdown-file criteria, descriptions should disclose behaviors that can affect user data or system integrity.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The file advertises CSV contact import and automation commands that can create tasks, reassign owners, or auto-advance pipelines, but it omits cautionary language about bulk updates and automated actions affecting many records at once. This is a markdown-level missing warning because the described behavior could materially affect user data and workflow integrity.

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 52)May include surrounding context.

2. Pipeline Management (Core Feature)

bash
# Create a pipeline entry (like a deal/opportunity)
bigin pipeline create --contact-id 12345 --company-id 67890 \
  --stage "Initial Contact" --amount 50000 \
  --closing-date "2026-03-15" --owner "sales@yourcompany.com"

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
90% confidence
Finding

The skill promotes bulk-update and auto-advance automation that can change many pipeline records at once, including moving deals to 'Closed Won', without warning about reversibility, review, or safeguards. In a sales CRM context, such actions can corrupt business data, trigger downstream workflows, distort forecasting, and be difficult to unwind at scale.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
93% confidence
Finding

The skill documents an automated workflow that creates or updates CRM contacts, companies, pipelines, tasks, and even sends replies based on incoming email, but it does not mention confirmation prompts, approval gates, or disclosure that external CRM state will be modified. This can lead to unintended data creation, incorrect record linkage, privacy issues, and unauthorized outbound actions if email content is misparsed or attacker-controlled.

Content

No source excerpt is available for this finding.

Natural-Language Policy Violations

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The config sets default_dc to com, which corresponds to the United States, while also defining multiple regional data centers. This creates a natural-language locale policy concern because the skill defaults users to a specific region without indicating user selection, opt-in, or a documented justification for that locale choice.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
94% confidence
Finding

This code persists access and refresh tokens to a file under the user's home directory, which is a safety-relevant credential storage operation. Although permissions are restricted and comments describe the implementation, there is no user-facing disclosure at the point of action explaining that sensitive tokens will be saved locally.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 59)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 236)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 343)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 479)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 585)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 636)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 680)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines"
        payload = {"data": [data]}
        response = requests.post(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
98% confidence
Finding

When DEBUG is enabled, the client logs full request headers and response bodies to stderr, which includes the OAuth Authorization header and potentially sensitive CRM data. In an agent or shared execution environment, stderr may be captured by logs, exposing credentials and customer records to operators, other tools, or downstream log systems.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 139)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines/{pipeline_id}"
        payload = {"data": [data]}
        response = requests.put(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 291)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines/{pipeline_id}"
        payload = {"data": [data]}
        response = requests.put(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()

External Transmission

Medium
Category
Data Exfiltration
Confidence
80% 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 · scripts/bigin_crm.py (reported line 398)May include surrounding context.

python
"""
        url = f"{self.base_url}/Pipelines/{pipeline_id}"
        payload = {"data": [data]}
        response = requests.put(url, headers=self.headers, json=payload)
        response.raise_for_status()
        return response.json()