T09 · Insecure Skill Coding Practices
- Location
scripts/dida365_lib/cli.py:668- Finding
OAuth Callback Accepts a Missing State Parameter
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
The skill mostly fits Dida365 task management, but it needs review because endpoint override options can send OAuth secrets, bearer tokens, and task data to non-Dida365 URLs.
Review this skill before installing. Use only the default Dida365 endpoints unless you are deliberately testing with trusted infrastructure, and check that DIDA365_AUTH_BASE_URL, DIDA365_API_BASE_URL, config.json, and command flags have not been set to unexpected hosts. Treat client secrets, authorization codes, and token.json as sensitive. Confirm task or project deletion requests carefully, and clear cached tokens when you no longer need the skill.
scripts/dida365_lib/cli.py:668OAuth Callback Accepts a Missing State Parameter
scripts/dida365_lib/cli.py:70Unrestricted Base URL Overrides Can Expose OAuth Credentials, Bearer Tokens, and Task Data
Referenced artifact was not completely inspected
te format, confirmed reminder patterns, and confirmed recurrence patterns from `references/api-reference.md`. Do not invent undocumented values.
Referenced artifact was not completely inspected
te format, confirmed reminder patterns, and confirmed recurrence patterns from `references/api-reference.md`. Do not invent undocumented values.
Referenced artifact was not completely inspected
te format, confirmed reminder patterns, and confirmed recurrence patterns from `references/api-reference.md`. Do not invent undocumented values.
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
- `GET /open/v1/project/{projectId}/data`
- `POST /open/v1/project`
- `POST /open/v1/project/{projectId}`
- `DELETE /open/v1/project/{projectId}`
### Task
Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
- `POST /open/v1/task`
- `POST /open/v1/task/{taskId}`
- `POST /open/v1/project/{projectId}/task/{taskId}/complete`
- `DELETE /open/v1/project/{projectId}/task/{taskId}`
- `POST /open/v1/task/move`
- `POST /open/v1/task/completed`
- `POST /open/v1/task/filter`
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
diagnostics.append("Missing OAuth client settings. Run auth setup first or pass --client-id and --client-secret.")
if settings.token_file.exists() and not settings.token_data.get("access_token"):
diagnostics.append("Token file exists but does not contain a usable access token.")
elif not settings.access_token:
diagnostics.append("No access token available. Run auth login-local or auth exchange-code.")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
diagnostics.append("Missing OAuth client settings. Run auth setup first or pass --client-id and --client-secret.")
if settings.token_file.exists() and not settings.token_data.get("access_token"):
diagnostics.append("Token file exists but does not contain a usable access token.")
elif not settings.access_token:
diagnostics.append("No access token available. Run auth login-local or auth exchange-code.")
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
token = self.settings.access_token
if not token:
raise UserFacingError(
"Access token is required. Run auth exchange-code or auth login-local first.",
)
return self.transport.request(
method,
The README is entirely written as Chinese-only user-facing guidance and describes natural-language interaction with the agent, but it does not mention any option to use another language or explain a region-specific limitation. That can indicate a language/locale policy issue when a skill effectively constrains users to a specific language without opt-in.
The skill requires environment secrets, local file access, shell execution, and network access, but the manifest does not declare an explicit tool/permission scope. That weakens least-privilege controls and can cause an agent runtime or reviewer to underestimate the skill’s real capabilities, increasing the chance of unintended credential access, local state modification, or outbound requests.
Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
That means the following are explicit non-goals here:
- standalone tag catalog / CRUD operations outside task create or update writes
- project folder / group operations
- full-account sync from private endpoints
- private batch task/project operations
The documentation instructs the agent to persist OAuth configuration and token state locally and to perform write operations against projects and tasks, but it does not clearly warn about credential storage location, persistence duration, or the fact that commands can modify remote user data. This can lead to users unknowingly leaving long-lived tokens on disk or triggering destructive changes without informed consent.
The file lists OAuth authorization and token endpoints as covered surface, which implies credential and token handling, but it does not include any warning about sensitive authentication data. For markdown files, omission of warnings about privacy-sensitive behavior is in scope when the skill description covers authentication flows or access to protected account data.
This markdown file documents DELETE /open/v1/project/{projectId} and DELETE /open/v1/project/{projectId}/task/{taskId} as part of the skill surface, but it does not warn users that these operations can remove user data. Although later notes mention observed soft-delete behavior for some task deletions, there is no upfront caution that deletion behavior may vary and may affect data integrity or recovery.
This markdown file includes authentication examples that use sensitive values such as client secrets and authorization codes, but it does not warn users to keep these values confidential or avoid exposing them in shell history and logs. Because SQP-2 applies to markdown files when descriptions omit warnings about privacy- or security-relevant behavior, the missing disclosure is a valid concern.
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
exit_code=1,
) from exc
server.timeout = 0.5
def serve() -> None:
while not event.is_set():
Skill allows unbounded resource consumption (API calls, storage, compute). Without rate limits or quotas, a compromised or misbehaving agent can cause denial-of-service or cost overruns.
deadline = time.time() + timeout
try:
while time.time() < deadline:
if event.wait(timeout=0.2):
return CallbackResult(
code=result["code"],
state=result.get("state"),
This code exposes project delete and immediately calls client.delete_project(project_id) with no confirmation prompt, warning message, or explanatory comment about the irreversible effect. For a code file, destructive operations should have some form of user disclosure unless the warning is clearly provided elsewhere, which is not evidenced in this file.
The task delete handler resolves the task and project identifiers and then directly invokes client.delete_task(...) without printing a warning, requesting confirmation, or documenting the destructive behavior in nearby comments/docstrings. This is a safety-relevant deletion path in a code file and lacks visible disclosure in the code shown.
This markdown file advertises operations such as deleting tasks and broad task/project modification, but it does not include an explicit warning that these actions may permanently alter user data. Under the markdown-specific warning criterion, skills affecting user data should disclose potentially destructive behavior.
SQP-3 covers natural-language language or locale policy violations across all file types. The description contains a Chinese primary description followed by an English instruction ('Use when...'), which may impose inconsistent language expectations without explicit user opt-in or a documented bilingual policy.
Skill's behavior or capabilities extend beyond its stated purpose. Scope creep allows an agent to perform actions unrelated to its documented functionality, increasing the attack surface.
### Usage Notes
- `repeatFlag` is not limited to plain RFC-style `RRULE` values. Dida365 also returns and accepts `ERULE`, `LUNAR`, and `TT_SKIP`-extended rules.
- Some values encode the current task date, such as `BYMONTHDAY=16` or `BYMONTH=3;BYMONTHDAY=16`. When creating a new rule, adjust those date parts to match the task's intended schedule.
- The CLI preserves `--repeat-flag ""`, so an empty string can be used to clear a stored recurrence value.
- Real undated-task testing showed `repeatFlag` can be silently cleared instead of preserved. For reliable recurrence writes, use `repeatFlag` only on tasks that already have `startDate` and `dueDate`.
The natural-language documentation states that reminder trigger values were confirmed through 'Chinese-locale app checks,' and later uses Chinese-locale behavior to justify excluded patterns. This introduces a locale-specific constraint in the skill documentation without explicitly offering user choice or clearly framing the limitation as region-specific behavior users should opt into or account for.
This code loads sensitive values such as DIDA365_CLIENT_SECRET and DIDA365_ACCESS_TOKEN from environment variables, which is a safety-relevant credential access operation under the rule. In this file there is no confirmation prompt, user-facing log/print, or explanatory comment/docstring specifically warning that credentials will be sourced from the environment.
Dynamic getattr() with a non-literal attribute name can access arbitrary object attributes, potentially bypassing access controls.
payload = dict(settings.config_data)
fields_to_save = tuple(fields) if fields is not None else CONFIG_FIELDS
for field in fields_to_save:
value = getattr(settings, field)
if value not in (None, ""):
payload[field] = value
if updates:
No suspicious patterns detected.