T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/dexscan.js:20- Finding
Overly Broad Parent-Directory Credential Discovery
- Content
View full analysis
Vulnerability Details
File Location:
scripts/dexscan.js, lines 20–44
Vulnerability Type: Least-privilege violation through unrestricted ancestor.envdiscovery
Risk Level: MediumVulnerable Code
javascript function readEnvFile() { const envConfig = {}; let currentDir = __dirname; // Search upward for a .env file until reaching the filesystem root while (true) { const envPath = path.join(currentDir, '.env'); if (fs.existsSync(envPath)) { const content = fs.readFileSync(envPath, 'utf-8'); content.split('\n').forEach(line => { const match = line.match(/^\s*DS_ACCESS_KEY\s*=\s*"?([^"]*)"?/); if (match) envConfig.DS_ACCESS_KEY = match[1].trim(); const match2 = line.match(/^\s*DS_SECRET_KEY\s*=\s*"?([^"]*)"?/); if (match2) envConfig.DS_SECRET_KEY = match2[1].trim(); }); break; } const parentDir = path.dirname(currentDir); // Stop after reaching the filesystem root if (parentDir === currentDir) { break; } currentDir = parentDir; } return envConfig; }Technical Analysis
The
readEnvFile()function begins at the script directory and traverses every ancestor directory until it reaches the filesystem root. It reads the first.envfile encountered and extractsDS_ACCESS_KEYandDS_SECRET_KEY.This behavior is broader than the declared requirement.
SKILL.mdstates that the.envfile resides in the Skill working directory, so reading.envfiles from arbitrary parent projects or shared runtime directories is unnecessary. A fixed Skill-local path would provide all filesystem access required by the declared functionality.If the Skill-local
.envfile is absent, credentials with matching names from an unrelated ancestor configuration can be sile ...[truncated 2175 chars]- Remediation
View remediation
Remediation Suggestions
-
Restrict credential-file access to the documented Skill-local
.envfile:javascript function readEnvFile() { const envConfig = {}; const envPath = path.resolve(__dirname, '..', '.env'); if (!fs.existsSync(envPath)) { return envConfig; } const content = fs.readFileSync(envPath, 'utf8'); content.split('\n').forEach(line => { const accessMatch = line.match(/^\s*DS_ACCESS_KEY\s*=\s*"?([^"]*)"?\s*$/); const secretMatch = line.match(/^\s*DS_SECRET_KEY\s*=\s*"?([^"]*)"?\s*$/); if (accessMatch) { envConfig.DS_ACCESS_KEY = accessMatch[1].trim(); } if (secretMatch) { envConfig.DS_SECRET_KEY = secretMatch[1].trim(); } }); return envConfig; } -
Do not traverse above the Skill root under any circumstances.
-
Prefer credentials supplied through a dedicated secret manager or explicitly injected process environment variables.
-
If configurable file locations are required, accept an explicit trusted path and validate it against an approved configuration directory.
-
Reject ambiguous configurations rather than silently selecting the first ancestor
.envfile. -
Keep the secret key local to HMAC generation, never log authentication headers, and ensure diagnostic errors do not include credential values.
-
Add tests verifying that
.envfiles outside the Skill root are never read.
-
