T09 · Insecure Skill Coding Practices
- Location
auth.md:58- Finding
Timing-Based Account Enumeration in Custom Authentication Backend
- Content
View full analysis
- Remediation
View remediation
Security audit
Security checks for vulnerabilities and agentic risk
This is a Django help skill with scoped local preference memory; I found no hidden execution, data export, or deceptive behavior.
Before installing, review the local memory behavior: this skill can use and update ~/Clawic/data/django/ and may consult ~/Clawic/profile.yaml for general preferences. Do not store secrets, credentials, sensitive production details, or untrusted quoted instructions in those files. Also treat the custom authentication backend and admin HTML notes as guidance to review carefully rather than code to copy verbatim.
auth.md:58Timing-Based Account Enumeration in Custom Authentication Backend
setup.md:11Persistent Cross-Session Preference Storage Creates a Memory-Poisoning Surface
Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.
- Two levels: `has_permission(request, view)` runs before the handler; `has_object_permission(request, view, obj)` runs only when `get_object()` is called — so a custom list endpoint that never calls it gets no object checks at all.
- `SAFE_METHODS` is the idiom for read-only-for-others permissions. Combine classes with `&`, `|`, `~`.
- Authentication answers "who"; permission answers "may they". A 401 means no credentials were recognized, a 403 means they were and it is not enough — returning the wrong one sends clients into a refresh loop.
- JWT is a dependency, not part of DRF. Its tradeoff is revocation: a stateless token stays valid until it expires, so keep access tokens short and put logout on the refresh token.
- CORS is not authentication and not part of DRF either; a browser preflight failing looks like an auth bug and is a middleware configuration.
## Pagination, Filtering, Versioning
The statement claims that HTML returned from a list_display callable is not escaped and therefore should use format_html. In Django admin, plain strings returned by display methods are escaped by default; format_html is used when you intentionally want to safely construct HTML markup. This incorrect guidance can cause developers to misunderstand the escaping model and, depending on how they act on it, either introduce unsafe uses of mark_safe/raw HTML or make incorrect security decisions about XSS handling in admin pages.
Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.
| `migrate --fake` | Writes a row in `django_migrations`, changes no schema | Correct only when the schema already matches; otherwise recorded history becomes a lie |
| `migrate --fake-initial` | Fakes only the initial migration if the tables exist | The safe variant for adopting an existing database |
| `migrate app 0006` | Migrates *backwards* to 0006 | Runs reverse operations; irreversible ones raise mid-way |
| `flush` | Deletes all data, keeps the schema, re-runs post-migrate | No confirmation with `--noinput` |
| `sqlflush` | Prints the truncation SQL | Harmless to print, catastrophic to pipe |
| `loaddata` | Loads a fixture, calling `save()` per object | Signals fire; existing rows with the same pk are overwritten |
| `dumpdata` | Serializes via `_default_manager` | A filtered default manager silently omits rows |
The setup instructions tell the agent to read user-local files such as ~/Clawic/data/django/config.yaml, ~/Clawic/data/django/memory.md, and ~/Clawic/profile.yaml automatically on first use, without any user-facing disclosure or consent step in the skill itself. This creates a privacy and boundary-risk issue because the skill is authorized to ingest potentially sensitive local context unrelated to the immediate task, and the instruction to 'Do not interview the user' reduces transparency rather than narrowing access.
The skill directs persistent writes to local config and memory files based on conversational content, again without an explicit warning that user data will be modified. Persistent state changes can silently record preferences, constraints, or project details, creating privacy, integrity, and surprise-modification risks, especially because the skill encourages automatic updating of stored values when the user mentions or corrects preferences.
Line L03 directs the user to create ~/Clawic/data/django/memory.md, which is a file-writing action affecting user data. The skill description does not include any warning or disclosure that it will create or modify a file on the local system.
This is a markdown file, so SQP-2 applies to omitted warnings about behaviors affecting user data or privacy. Line L097 mentions that unhandled exceptions emailed by AdminEmailHandler include request data, but frames it as implementation guidance rather than an explicit user-facing warning to avoid leaking sensitive request contents.
No suspicious patterns detected.