T09 · Insecure Skill Coding Practices
- Location
opennotebook.py:319- Finding
API Key Exposure Through Command-Line Arguments
- Content
View full analysis
Vulnerability Details
File Locations:
opennotebook.py:319opennotebook.py:526-527test_integration.py:418-432
Vulnerability Type: Sensitive credential exposure through process arguments
Risk Level: MediumVulnerable Code
python parser.add_argument("--api-key", help="API 密钥")python if args.api_key: config.api_key = args.api_keypython base_url = self.client.notebooks.config.base_url api_key = self.client.notebooks.config.api_key commands = [ (["--base-url", base_url, "--api-key", api_key, "health"], "健康检查"), (["--base-url", base_url, "--api-key", api_key, "notebooks", "list"], "列出笔记本"), (["--base-url", base_url, "--api-key", api_key, "sources", "list"], "列出源"), (["--base-url", base_url, "--api-key", api_key, "notes", "list"], "列出笔记"), (["--base-url", base_url, "--api-key", api_key, "models", "list"], "列出模型"), (["--base-url", base_url, "--api-key", api_key, "transformations", "list"], "列出转换"), (["--base-url", base_url, "--api-key", api_key, "search", "query", "测试", "--limit", "3"], "搜索"), ] for cmd, desc in commands: result = subprocess.run( ["python3", str(cli_path)] + cmd, capture_output=True, text=True )Technical Analysis
The CLI accepts the bearer API key directly through the
--api-keyargument. Command-line arguments may be exposed through shell history, process inspection facilities, CI/CD execution logs, endpoint-monitoring products, crash diagnostics, or debugging output.The integration test compounds this issue by placing the same key in the argument vector of every spawned CLI process. Although
subprocess.runuses an argument list rather than a shell and is therefore not vulnerable to shell injection here, the secret remains visible as process metadata while each child process executes.Attack Path
- A user invokes the CLI or integration te ...[truncated 1028 chars]
- Remediation
View remediation
Remediation Suggestions
-
Remove or deprecate the
--api-keyoption for normal use. -
Read the key from
OPENNOTEBOOK_API_KEY, a protected credential file, standard input, or an operating-system secret store. -
If interactive entry is required, use
getpass.getpass()so the key is not echoed or retained in shell history. -
Change integration tests to pass the key through a restricted child-process environment instead of the argument vector:
python child_env = os.environ.copy() child_env["OPENNOTEBOOK_API_KEY"] = api_key result = subprocess.run( ["python3", str(cli_path), "--base-url", base_url, "health"], env=child_env, capture_output=True, text=True ) -
Ensure CI systems mask
OPENNOTEBOOK_API_KEYand do not print child environments. -
Rotate any API key that has already been supplied through command-line arguments in shared, monitored, or logged environments.
-
