{"data":{"skill":{"slug":"um-why-douyin-search-keyword","name":"douyin-search-keyword","icon":"📦","repo":"https://github.com/um-why/douyin-search-openclaw/tree/master/","status":"approved","author":"um-why","authorVersion":null,"skillstoreRevision":null},"audit":{"id":"cf7d98b8-ac28-4e8f-b3ef-d23c9da48b84","skill_id":"a81ed620-d9e9-4d96-be04-e0e50d46ba5f","version":3,"content_hash":"8238faadaa902d1b5ac1dfa2018a0abe","risk_level":"safe","is_blocked":false,"safe_to_publish":true,"analysis_status":"ok","agent_auto_install_policy":"allowed","manual_install_policy":"allowed","summary":"Static shell-execution alerts are false positives caused by JavaScript template literals and documentation command examples. The confirmed risk is high because this community skill runs a Node.js script, reads GUAIKEI_API_TOKEN, sends the token and search terms to www.guaikei.com, and writes search output to local files.","remediation":[],"risk_factor_evidence":[{"factor":"scripts","evidence":[{"file":"SKILL.md","line_end":13,"line_start":13},{"file":"package.json","line_end":8,"line_start":6},{"file":"scripts/search.js","line_end":7,"line_start":1}]},{"factor":"network","evidence":[{"file":"lib/douyin.js","line_end":163,"line_start":143},{"file":"lib/douyin.js","line_end":261,"line_start":241},{"file":"lib/douyin.js","line_end":275,"line_start":275}]},{"factor":"filesystem","evidence":[{"file":"scripts/search.js","line_end":40,"line_start":36},{"file":"scripts/search.js","line_end":112,"line_start":101},{"file":"scripts/search.js","line_end":205,"line_start":203}]},{"factor":"env_access","evidence":[{"file":"scripts/search.js","line_end":114,"line_start":114},{"file":"SKILL.md","line_end":16,"line_start":14}]}],"critical_findings":[],"high_findings":[{"title":"Environment Token Sent to Third-Party API","locations":[{"file":"scripts/search.js","line_end":114,"line_start":114},{"file":"lib/douyin.js","line_end":163,"line_start":143},{"file":"lib/douyin.js","line_end":261,"line_start":241}],"confidence":0.9,"description":"The command reads GUAIKEI_API_TOKEN and passes it into requests to www.guaikei.com. This is intended API use, but it exposes user search terms and credentials to an external service controlled outside the marketplace.","confidence_reasoning":"The token is read from process.env and passed to createWithRetry and searchWithRetry. Both request builders use the external hostname www.guaikei.com."},{"title":"API Token Included in Request URL Query Parameters","locations":[{"file":"lib/douyin.js","line_end":156,"line_start":145},{"file":"lib/douyin.js","line_end":255,"line_start":243}],"confidence":0.88,"description":"The API token is placed in query parameters for both task creation and result lookup. Query parameters are commonly captured by proxies, server logs, and debugging tools.","confidence_reasoning":"The request path is built with querystring.stringify(params), and params includes token in both API calls. This is a clear credential exposure pattern even if the service is legitimate."}],"medium_findings":[{"title":"Hardcoded Default API Token","locations":[{"file":"lib/key.js","line_end":20,"line_start":16},{"file":"scripts/search.js","line_end":114,"line_start":114}],"confidence":0.84,"description":"If GUAIKEI_API_TOKEN is missing or invalid, the skill silently falls back to a hardcoded token. This can route user searches through a shared credential without explicit consent.","confidence_reasoning":"The fallback token is returned directly when the environment value is absent, empty, non-string, or not 32 characters. The code labels this as a default experience token."},{"title":"Search Results Persisted to Local File","locations":[{"file":"scripts/search.js","line_end":192,"line_start":177},{"file":"scripts/search.js","line_end":205,"line_start":203}],"confidence":0.78,"description":"The script writes the complete final output to scripts/last-search.json. The results may include public content links, author metadata, timestamps, and the user search keyword.","confidence_reasoning":"The writeFileSync call stores finalOutput after it is populated with keyword, result metadata, and content URLs. The data appears public, but local persistence is not optional."}],"low_findings":[{"title":"Static External Command Alerts Are False Positives","locations":[{"file":"lib/douyin.js","line_end":97,"line_start":73},{"file":"scripts/search.js","line_end":33,"line_start":13},{"file":"SKILL.md","line_end":302,"line_start":287}],"confidence":0.96,"description":"The reported backtick locations are JavaScript template literals or Markdown command examples, not shell execution APIs. No evidence of child_process, eval, or shell backtick execution was found in the inspected files.","confidence_reasoning":"The cited code uses console output strings and documentation blocks. These constructs do not execute commands in Node.js or Markdown."},{"title":"Static Path Traversal Alerts Are Mostly False Positives","locations":[{"file":"scripts/search.js","line_end":5,"line_start":3},{"file":"lib/douyin.js","line_end":40,"line_start":38},{"file":"scripts/search.js","line_end":112,"line_start":99}],"confidence":0.82,"description":"The ../lib imports are normal relative module imports, and the image join operation is output formatting. Keyword-derived lock files are constrained by sanitization, but still create local files from user input.","confidence_reasoning":"The imports do not traverse user-controlled paths. The remaining lock-file path uses sanitized keywords, so traversal is unlikely, but filesystem side effects remain real."}],"dangerous_patterns":[{"title":"External HTTPS Requests with Credential Parameters","locations":[{"file":"lib/douyin.js","line_end":163,"line_start":145},{"file":"lib/douyin.js","line_end":261,"line_start":243}],"confidence":0.9,"description":"The skill builds HTTPS requests to www.guaikei.com and includes the API token in query parameters.","confidence_reasoning":"The code uses https.request and querystring.stringify on params that contain token. This is directly visible in both request functions."},{"title":"Environment Variable Access for API Credential","locations":[{"file":"scripts/search.js","line_end":114,"line_start":114}],"confidence":0.92,"description":"The command reads GUAIKEI_API_TOKEN from process.env and uses it for remote API calls.","confidence_reasoning":"The environment variable is read in a single direct expression and passed to the key helper. There is no ambiguity about the credential source."},{"title":"Local File Creation and Result Persistence","locations":[{"file":"scripts/search.js","line_end":112,"line_start":101},{"file":"scripts/search.js","line_end":205,"line_start":203}],"confidence":0.8,"description":"The script creates lock files and writes the most recent search output under the scripts directory.","confidence_reasoning":"The filesystem writes are direct fs.writeFileSync calls. The behavior is useful for idempotency and persistence, but it should be disclosed to users."}],"files_scanned":7,"total_lines":1043,"audit_model":"codex","audited_at":"2026-06-30T21:43:15.149+00:00","created_at":"2026-07-07T02:38:14.136376+00:00","static_findings":[],"finding_verdicts":[],"semantic_findings":[],"subject_marketplace_commit_sha":null,"subject_content_hash":null,"subject_tree_hash":null,"subject_plugin_path":null,"audit_payload_hash":null,"confirmed_risk_level":null,"scanner_version":null,"policy_version":null,"subject":{"marketplaceCommitSha":null,"contentHash":null,"treeHash":null,"pluginPath":null,"auditPayloadHash":null},"scannerVersion":null,"policyVersion":null},"auditTranslation":null,"localization":{"requestedLocale":"en","contentLocale":"en","availableLocales":["en"],"fallbackToEnglish":false},"attestation":{"availability":"not_attestable","url":null,"status":null,"reason":"confirmed_risk_level does not match the canonical trust resolver"},"trust":{"publicState":"public","auditState":"complete","auditCurrentness":null,"confirmedRiskLevel":"safe","confirmedFindingCount":0,"capabilityReviewCount":4,"needsReviewCount":0,"falsePositiveCount":2,"agentAutoInstallPolicy":"allowed","manualInstallPolicy":"allowed","artifactSignatureState":"available","attestationState":"not_attestable","verificationState":"not_verified"},"isLatest":false}}