T09 · Insecure Skill Coding Practices
- Location
dataagent_openapi_cli.mjs:96- Finding
Unredacted DataPilot API Credential Written to a Persistent Log
- Content
View full analysis
Vulnerability Details
File Location:
dataagent_openapi_cli.mjs, lines 96-105
Vulnerability Type: Plaintext credential disclosure through local logging
Risk Level: HighVulnerable Code:
js function getAuthHeaders(args) { writeLog({ type: "getAuthHeaders", args: sanitizeArgs(args), keyenv: process.env.DATAPILOT_API_KEY }); const auth = args.token || args.apiKey || process.env.DATAPILOT_API_KEY; if (!auth) { throw new Error("Missing auth. Provide --token/--apiKey or set DATAPILOT_API_KEY"); } return { Authorization: `Bearer ${auth}`, "X-Lang": "zh", }; }The log destination and write operation are defined as follows at lines 26 and 45-54:
js const LOG_FILE = join(__dirname, "dataagent_cli.log"); async function writeLog(entry) { const line = JSON.stringify({ timestamp: new Date().toISOString(), ...entry }) + "\n"; try { await appendFile(LOG_FILE, line, "utf-8"); } catch { // Log failure does not affect the main process } }Technical Analysis
getAuthHeaders()passes the complete value ofprocess.env.DATAPILOT_API_KEYtowriteLog()through thekeyenvproperty. The log writer serializes this value without redaction and appends it todataagent_cli.login the Skill directory.This bypasses the otherwise available
sanitizeSecret()andgetRelevantEnv()protections. It occurs whenever an authenticated command callsgetAuthHeaders(), even if the credential was supplied through a CLI argument instead of the environment, because the environment variable is logged whenever it exists.Persistent plaintext logging is not required for the declared DataPilot functionality and exceeds least-privilege data handling. The log also has no explicit restrictive file mode, retention policy, or cleanup mechanism.
Attack Path
- A user configures
DATAPILOT_API_KEYand executes any authenticated command, such as ` ...[truncated 1078 chars]
- A user configures
- Remediation
View remediation
Remediation Suggestions
-
Remove the credential from the logging call entirely:
js writeLog({ type: "getAuthHeaders", args: sanitizeArgs(args), keyConfigured: Boolean(process.env.DATAPILOT_API_KEY), }); -
Never log bearer tokens, API keys, datasource passwords, authorization headers, or complete environment values. Apply centralized recursive redaction as a defense in depth measure.
-
Create log files with restrictive permissions, such as mode
0o600, and store them in an appropriate user-specific state directory rather than the Skill source directory. -
Add log rotation and deletion policies to limit retention.
-
Delete existing
dataagent_cli.logfiles securely and rotate any API key that may already have been recorded. -
Add an automated test that supplies a sentinel credential, executes every command path, and verifies that the sentinel never appears in logs or command output.
-
