T09 · Insecure Skill Coding Practices
- Location
index.js:85- Finding
Sensitive Data-Source Credentials Exposed in Query Results and In-Memory Cache
- Content
View full analysis
Vulnerability Details
File Location:
index.js, lines 85–88 and 95–124
Vulnerability Type: Sensitive information exposure through returned objects and caching
Risk Level: MediumVulnerable Code
javascript // From queryPolicies(), lines 85–88 const dataSource = this.config.dataSources[category]; const policies = await this.fetchFromDataSource(dataSource, category, options); this.policyCache.set(cacheKey, policies); return policies;javascript // From fetchFromDataSource(), lines 95–124 async fetchFromDataSource(dataSource, category, options) { // Simulated data const policies = [{ title: this.config.language === 'zh-CN' ? '${name}投资政策' : '${name} Investment Policy', description: this.config.language === 'zh-CN' ? '${name}最新投资政策和法规' : 'Latest investment policies and regulations in ${name}', effectiveDate: '2026-01-01', authority: this.config.language === 'zh-CN' ? '${name}政府' : '${name} Government', dataSource, keyPoints: this.config.language === 'zh-CN' ? [ '${name}市场准入政策', '外商投资优惠政策', '行业特定法规' ] : [ '${name} market access policies', 'Foreign investment incentives', 'Industry-specific regulations' ] }]; return { country: this.t('country'), category: this.t('categories', category), totalPolicies: policies.length, policies: policies, lastUpdated: new Date().toISOString(), dataSource, language: this.config.language }; }Technical Analysis
The project documentation instructs users to populate
dataSourceswith environment-derived API keys. The implementation reads the selected value fromthis.config.dataSources[category]and passes it intofetchFromDataSource().That function does not use the value solely for authentication or source access. Instead, it places the value into both:
- Every generated policy object as
policies[0].dataSource. - The top-level response as
dataSource.
The complete r ...[truncated 2145 chars]
- Every generated policy object as
- Remediation
View remediation
Remediation Suggestions
- Separate source endpoint configuration from authentication credentials. For example, use distinct
endpoint,sourceId, andapiKeyproperties. - Use credentials only at the point where an authenticated request is made, preferably in an authorization header. Never add credentials to policy records, return objects, error messages, or logs.
- Remove both
dataSourcefields from the returned data or replace them with a non-sensitive source identifier:
javascript return { country: this.t('country'), category: this.t('categories', category), totalPolicies: policies.length, policies, lastUpdated: new Date().toISOString(), sourceId: category, language: this.config.language };- Ensure cached objects contain only sanitized response data. If credentials are ever needed during retrieval, do not retain them in cache entries.
- Validate
categoryagainst an explicit allowlist before reading configuration values. - Add automated tests that configure a unique sentinel secret, invoke every public method, serialize the results and cache values, and assert that the sentinel never appears.
- Apply minimum privileges and short expiration periods to all API credentials so that accidental disclosure has limited impact.
- Update the documentation to distinguish data-source URLs from API keys and warn that credentials must not be used as response metadata.
- Separate source endpoint configuration from authentication credentials. For example, use distinct
