T09 · Insecure Skill Coding Practices
- Location
scripts/setup-wizard.py:121- Finding
Bearer Token Exposed Through Echoed Terminal Input
- Content
View full analysis
Vulnerability Details
File Location:
scripts/setup-wizard.py, line 121
Vulnerability Type: Plaintext sensitive credential input
Risk Level: LowVulnerable Code
python token = input(f"{CYAN} Enter your Private Integration token: {RESET}").strip()Technical Analysis
The setup wizard uses Python's standard
input()function to collect a GoHighLevel Private Integration bearer token. Terminal echo remains enabled whileinput()is active, so every character of the token is displayed as the user types it.This can expose the credential through shoulder surfing, screen sharing, terminal session recording, screenshots, or other mechanisms that capture visible terminal content. The code does not intentionally transmit the token to an unauthorized service: subsequent network requests are constrained to the declared GoHighLevel API host,
https://services.leadconnectorhq.com. Sending the bearer token to that host is necessary for the Skill's declared CRM functionality.Attack Path
- A user runs
scripts/setup-wizard.pywithoutHIGHLEVEL_TOKENalready configured. - The wizard prompts the user for a Private Integration token.
- The user enters the token through
input(), causing it to appear visibly in the terminal. - An observer, screen-sharing participant, terminal recorder, or captured screenshot obtains the token.
- The attacker submits the token as a bearer credential to the GoHighLevel API.
- The attacker can access or modify resources permitted by the token's configured scopes until the token is revoked or rotated.
Impact Assessment
Compromise grants the attacker the same API privileges as the affected Private Integration token. Depending on the scopes assigned by the user, this may include reading CRM contacts and conversations, sending messages, modifying opportunities, managing calendar data, or accessing invoices and payment-related records.
The impact is bounde ...[truncated 247 chars]
- A user runs
- Remediation
View remediation
Remediation Suggestions
Use
getpass.getpass()so the credential is collected with terminal echo disabled:python from getpass import getpass token = getpass( f"{CYAN} Enter your Private Integration token: {RESET}" ).strip()Additional hardening measures:
- Prefer preconfigured environment variables or a protected secret manager over interactive credential entry.
- Never place bearer tokens in command-line arguments, diagnostic output, exception messages, or persistent logs.
- Continue masking tokens when reporting configuration status.
- Recommend sub-account integrations and only the minimum scopes required for the user's intended operations.
- Restrict access to terminal recordings and CI/CD logs.
- Rotate the token immediately if it may have been exposed.
