T09 · Insecure Skill Coding Practices
- Location
timedoctor.py:372- Finding
TimeDoctor Credentials and Long-Lived JWT Tokens Are Exposed Through Unsafe Interfaces
- Content
View full analysis
Vulnerability Details
File Location:
SKILL.md:27-35,SKILL.md:187-198,SKILL.md:278-295,timedoctor.py:372-373,timedoctor.py:396-402
Vulnerability Type: Credential exposure through command-line arguments, agent conversations, and standard output
Risk Level: MediumVulnerable Code and Instructions
SKILL.md:27-35instructs users to provide their password as a command-line argument and then export the returned long-lived token:bash python3 timedoctor.py login --email "your-email@company.com" --password "your-password"This returns a JWT token valid for 6 months. Copy the token and set it:
bash export TIMEDOCTOR_TOKEN="your-jwt-token-from-login-response"SKILL.md:187-198explicitly instructs the agent to solicit credentials from the user:text 1. **Check if User Has Token** - If `TIMEDOCTOR_TOKEN` is not set, help them login: ``` "To get started, I need your TimeDoctor credentials. I'll run: python3 timedoctor.py login --email YOUR_EMAIL --password YOUR_PASSWORD What's your TimeDoctor email and password?" ``` - After getting credentials, run login command - Extract token from response - Tell user to set: `export TIMEDOCTOR_TOKEN="extracted-token"` - Explain token is valid for 6 monthsSKILL.md:278-295repeats the workflow and directs the agent to return the token to the user:text Steps: 1. Check if TIMEDOCTOR_TOKEN is set 2. If not, ask for credentials: "To get started, I need your TimeDoctor login credentials. What's your TimeDoctor email and password?" 3. User provides: "email@company.com" and "password123" 4. Run: python3 timedoctor.py login --email "email@company.com" --password "password123" 5. Parse response and extract token 6. Tell user: "Great! I got your token. It's valid for 6 months (until September 2026). Please set it in your environment: export TIMEDOCTOR_TOKEN='1jxExVs9WGsWccrq2ysMKMZVZlTVyTZc15tl ...[truncated 3833 chars]- Remediation
View remediation
Remediation Suggestions
-
Remove password collection from agent conversations
- Do not instruct the agent to ask users for TimeDoctor passwords.
- Explicitly warn users not to paste passwords or tokens into chat.
- Prefer an official OAuth, browser-based authorization, device-code, or equivalent delegated authentication flow.
-
Remove the
--passwordcommand-line option- If password authentication is unavoidable, read the password directly from an interactive terminal with Python's
getpass.getpass(). - Ensure the password is neither echoed nor included in command arguments.
- Reject password input when no trusted interactive terminal is available.
- If password authentication is unavoidable, read the password directly from an interactive terminal with Python's
-
Do not print authentication responses or tokens
- Parse the authentication response internally.
- Never send the complete response to standard output.
- Return only a success message and non-sensitive metadata, such as the expiration date.
- Redact token-like values from exceptions, debug output, and agent tool results.
-
Use protected credential storage
- Store tokens in an operating-system credential manager or platform-provided secret store.
- Apply restrictive file permissions if a file-based fallback is necessary.
- Avoid documenting persistent token exports in shell profiles, because those files and commands may be copied into backups or exposed through support logs.
-
Reduce token exposure and lifetime
- Prefer short-lived access tokens with refresh-token rotation where supported.
- Document revocation procedures.
- Revoke and replace any token disclosed in a transcript, terminal recording, or command history.
-
Harden operational logging
- Disable tool-call and subprocess argument logging during authentication.
- Add structured redaction for passwords,
Authorizationheaders, JWTs, and login responses. - Verify that monitoring, crash reporting, and support bundles do not collect authentication material.
-
**Upda ...[truncated 276 chars]
-
