T09 · Insecure Skill Coding Practices
- Location
index.js:103- Finding
DingTalk Access Tokens Are Exposed in URL Query Strings
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This DingTalk approval skill appears purpose-built rather than malicious, but it can change real business approval records and requests broader sensitive access than is well-scoped.
Install only if you are comfortable giving this plugin DingTalk application credentials that can read approval details and execute approval/refusal actions. Use a least-privilege DingTalk app, avoid granting contact-directory access unless separately needed, protect and rotate the AppSecret, and require the agent or operator to show task details and get explicit confirmation before any approve or reject action.
index.js:103DingTalk Access Tokens Are Exposed in URL Query Strings
references/configuration.md:22Configuration Guide Requests Unnecessary Contact-Directory Permission
The README advertises approve/reject functionality but does not warn that these actions can alter official organizational workflow records and may be difficult or impossible to reverse. In an approval-processing skill, lack of explicit caution increases the risk of accidental destructive actions by users or agents acting on ambiguous instructions.
The README tells users to place an AppSecret directly in configuration but provides no warning that it is a sensitive credential or guidance on secure storage. This can lead to secrets being committed to source control, shared in screenshots, or stored in plaintext on multi-user systems, enabling unauthorized access to DingTalk APIs.
This markdown file presents all user-facing content in a single forced language, and it does not offer an alternative language option or document that the skill is intentionally limited to a Chinese-speaking or region-specific audience. Under the policy, forcing a specific language without user opt-in is a natural-language policy violation.
The skill documents network-backed capabilities and privileged enterprise actions, but it does not declare any explicit tool scope or allowed-tools boundary. In an agentic environment, missing scope constraints can enable broader-than-intended tool access or invocation paths, which is especially risky because the skill can perform real approval decisions against DingTalk OA workflows.
The trigger conditions are broad enough that ordinary mentions of DingTalk, OA approvals, notifications, or batch processing could activate the skill without strong user intent verification. Because the skill supports destructive state-changing actions like approve/reject, overbroad invocation increases the chance of unintended workflow actions or data exposure from enterprise approval records.
The skill describes how to execute approval and rejection actions but does not require a clear warning or explicit confirmation step before performing irreversible or business-sensitive operations. In an enterprise OA context, mistaken approvals/rejections can alter audit trails, affect HR/finance/legal processes, and cause operational or compliance harm.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// 获取应用访问令牌
async function getDingtalkToken() {
const res = await fetch("https://api.dingtalk.com/v1.0/oauth2/accessToken", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ appKey: config.appKey, appSecret: config.appSecret })
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// 获取应用访问令牌
async function getDingtalkToken() {
const res = await fetch("https://api.dingtalk.com/v1.0/oauth2/accessToken", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ appKey: config.appKey, appSecret: config.appSecret })
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// 获取应用访问令牌
async function getDingtalkToken() {
const res = await fetch("https://api.dingtalk.com/v1.0/oauth2/accessToken", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ appKey: config.appKey, appSecret: config.appSecret })
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// 获取应用访问令牌
async function getDingtalkToken() {
const res = await fetch("https://api.dingtalk.com/v1.0/oauth2/accessToken", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ appKey: config.appKey, appSecret: config.appSecret })
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// 获取应用访问令牌
async function getDingtalkToken() {
const res = await fetch("https://api.dingtalk.com/v1.0/oauth2/accessToken", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ appKey: config.appKey, appSecret: config.appSecret })
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
// 获取应用访问令牌
async function getDingtalkToken() {
const res = await fetch("https://api.dingtalk.com/v1.0/oauth2/accessToken", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ appKey: config.appKey, appSecret: config.appSecret })
The skill exposes an approval-execution action that can irreversibly approve or reject business workflows without any built-in confirmation, re-authentication, or anti-mistake safeguard. In an agent setting, a misunderstood prompt, prompt injection, or accidental tool invocation could cause unauthorized business actions with real operational impact.
Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
}
// 执行审批
const executeRes = await fetch("https://api.dingtalk.com/v1.0/workflow/processInstances/execute", {
method: "POST",
headers: {
"Content-Type": "application/json",
The manifest describes this skill as a 钉钉 OA 审批处理插件 focused on pending approvals, approval details, and approve/reject actions. The additional tool get_vacation_balance accesses DingTalk attendance/vacation APIs to query leave quotas, which is a separate HR attendance capability not reflected in the manifest description or listed usage contexts.
The document includes appSecret in the token request example without emphasizing that it is a highly sensitive credential that must never be exposed client-side, logged, or embedded in prompts or docs used by untrusted parties. If mishandled, an attacker could obtain access tokens and invoke DingTalk APIs with the application's privileges.
The approval-execution API documentation describes agree/refuse actions but does not warn that these operations change business workflow state and may be irreversible or difficult to roll back. In an agent skill context, missing operator warnings increases the chance of unintended approvals/rejections being triggered automatically or with insufficient user confirmation.
The documentation includes realistic-looking secret values in JSON examples and shell export commands, which can normalize unsafe handling of credentials and lead users to paste real secrets into plaintext config files or shell history. In a plugin that requires high-privilege DingTalk app credentials for approval actions, this increases the chance of credential leakage and subsequent unauthorized access to approval data or actions.
Natural-language instructions, examples, and operational notes are presented exclusively in Chinese. Under the policy, forcing a specific language without user opt-in can be a locale/language policy issue unless the constraint is explicitly documented and justified.
The skill’s natural-language instructions, examples, and user interaction patterns are entirely presented in Chinese, with no indication that the user may choose another language. This can constitute a language/locale policy issue when the skill implicitly assumes a fixed language without opt-in or documented justification.
The code formats user-visible times with toLocaleString('zh-CN'), which hard-codes a specific locale in output. This imposes a language/locale choice on users without opt-in or explanation, matching the policy category for locale constraints.
This manifest uses Chinese-only natural-language descriptions for the plugin and its configuration fields, which can constitute a language/locale policy violation when no opt-in or alternative language is provided. There is no indication that the plugin is intentionally limited to a Chinese-only audience or region-specific compliance context.
No suspicious patterns detected.