T09 · Insecure Skill Coding Practices
Warning
- Location
- src/audit.js:341
- Finding
- Secret leakage audit skips nested and nonstandard configuration locations<![CDATA[ ## Vulnerability Details **File Location**: `src/audit.js:341-422` **Vulnerability Type**: Incomplete recursive secret detection **Risk Level**: Medium ### Vulnerable Code ```javascript const configStr = JSON.stringify(config); const foundSecrets = new Set(); // Check top-level env scanObj('env', config.env || {}, secretPatterns, push, foundSecrets); // Check skill entries env const skills = (config.skills && config.skills.entries) || {}; for (const [skillName, skill] of Object.entries(skills)) { scanObj(`skills.entries.${skillName}.env`, skill.env || {}, secretPatterns, push, foundSecrets); } // Check channel configs for tokens const channels = config.channels || {}; for (const [chName, ch] of Object.entries(channels)) { if (ch.botToken) { for (const sp of secretPatterns) { if (sp.pattern.test(ch.botToken)) { const key = `channels.${chName}.botToken`; if (!foundSecrets.has(key)) { foundSecrets.add(key); push({ category: 'secret_leakage', severity: 'critical', issue: `Channel "${chName}" has a ${sp.type} in botToken — this is expected for channel config but MUST NOT be shared.`, recommendation: 'Ensure this config file is never shared, committed to git, or sent to external services without sanitization.', }); } } } } } // Check gateway auth token exposure const gwToken = (config.gateway && config.gateway.auth && config.gateway.auth.token) || ''; if (gwToken) { push({ category: 'secret_leakage', severity: 'medium', issue: 'Gateway auth token is stored in plaintext in the config file.', recommendation: 'Consider using environment variable references or a secrets manager for the gateway token.', }); } // Check remote token const remote = (config.gateway && config.gateway.remote) || {}; if (remote.token && remote.token ...[truncated 3414 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Replace shallow, location-specific scanning with recursive traversal of every object, array, key, and string value in the configuration. 2. Preserve the full property path for every detected value so findings remain actionable without printing the secret itself. 3. Either scan `configStr` or remove the unused variable; recursive structured traversal is preferable because it can report accurate paths. 4. Detect suspicious key names in addition to value formats, including `authorization`, `cookie`, `session`, `clientSecret`, `accessToken`, `refreshToken`, `webhook`, and equivalent variants. 5. Treat malformed or unexpected configuration structures safely rather than silently skipping them. 6. Add regression tests for secrets in nested objects, arrays, plugin-specific fields, custom channel properties, authorization headers, and neutral field names. 7. Document that pattern-based detection is heuristic and must not be treated as proof that a configuration contains no secrets. ]]>
