T09 · Insecure Skill Coding Practices
Warning
- Location
- scripts/auth.py:20
- Finding
- Sensitive credentials exposed through command-line arguments<![CDATA[ ## Vulnerability Details **File Locations**: - `SKILL.md:23` - `SKILL.md:31` - `SKILL.md:39` - `SKILL.md:47` - `SKILL.md:55` - `scripts/auth.py:20-24` - `scripts/get_self.py:18-22` - `scripts/get_balance.py:18-22` - `scripts/list_items.py:18-22` - `scripts/list_chats.py:18-22` **Vulnerability Type**: Sensitive information exposure through process arguments **Risk Level**: Medium ### Vulnerable Code `scripts/auth.py:20-24`: ```python if __name__ == "__main__": if len(sys.argv) < 3: print("Usage: auth.py <client_id> <client_secret>") sys.exit(1) token_data = get_token(sys.argv[1], sys.argv[2]) ``` `scripts/get_self.py:18-22`: ```python if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: get_self.py <token>") sys.exit(1) user = get_self(sys.argv[1]) ``` `scripts/get_balance.py:18-22`: ```python if __name__ == "__main__": if len(sys.argv) < 3: print("Usage: get_balance.py <token> <user_id>") sys.exit(1) balance = get_balance(sys.argv[1], sys.argv[2]) ``` `scripts/list_items.py:18-22`: ```python if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: list_items.py <token>") sys.exit(1) items = list_items(sys.argv[1]) ``` `scripts/list_chats.py:18-22`: ```python if __name__ == "__main__": if len(sys.argv) < 3: print("Usage: list_chats.py <token> <user_id>") sys.exit(1) chats = list_chats(sys.argv[1], sys.argv[2]) ``` The corresponding usage documented in `SKILL.md` instructs users to place secrets directly on the command line: ```bash python3 scripts/auth.py <client_id> <client_secret> python3 scripts/get_self.py <token> python3 scripts/get_balance.py <token> <user_id> python3 scripts/list_items.py <token> python3 scripts/list_chats.py <token> <user_id> ``` ### Technical Analysis The scripts retrieve the Avito client secret and bearer access tokens from `sys.argv`. Command-line arguments are not an app ...[truncated 2457 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Remove secrets from command-line arguments.** Read the client ID, client secret, and bearer token from protected environment variables or a dedicated credential store. 2. **Provide a non-echoing interactive fallback.** Use `getpass.getpass()` when a secret is not available from a secure source: ```python import getpass import os client_id = os.environ.get("AVITO_CLIENT_ID") client_secret = os.environ.get("AVITO_CLIENT_SECRET") if not client_id: client_id = input("Avito Client ID: ") if not client_secret: client_secret = getpass.getpass("Avito Client Secret: ") ``` Apply equivalent handling to bearer tokens, such as reading them from `AVITO_ACCESS_TOKEN`. 3. **Update `SKILL.md`.** Replace examples that contain positional secret arguments with environment-variable or secure-prompt examples. Do not suggest commands that place secrets directly in shell history. 4. **Use a protected credential store for automation.** In CI/CD or unattended environments, obtain secrets from the platform's secret manager and prevent secret values from appearing in job definitions, logs, or traces. 5. **Minimize token disclosure.** Avoid printing complete authentication responses by default. If token output is needed for interoperability, provide an explicit output option and warn users to redirect it only to a permission-restricted destination. 6. **Apply restrictive access controls.** Any file used to supply or store credentials should be readable only by the intended account, such as mode `0600` on Unix-like systems. 7. **Rotate exposed credentials.** Users who previously invoked these commands should remove affected entries from shell history and rotate the relevant client secrets or revoke bearer tokens where exposure is possible. ]]>
