Skip to content
Report library
Purpose / Other

Extension User Approval Skill Security Audit

What the author says it does (original text)

Approval-based user management.

Independent security check

Security risks found

Files checked
2
Risks found
1
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.No risks found
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.No risks found
Could it delete files or keep running?Looks for broad file deletion, disk overwrites, and programs set to start automatically.No risks found
Could it bypass safety checks?Looks for skipped website security checks, excessive file access, or actions that skip your approval.Risks found: 1
Medium risk

Approval does not automatically protect custom backend endpoints

Source references: 5
What we found

The mixin supplies approval-management endpoints, but `isCallerApproved()` is only for frontend UI gating. Every custom public backend function still needs its own server-side approval or authorization check.

Why this matters

If an application only hides frontend features and omits backend checks, an unapproved user may directly invoke public endpoints and perform supposedly protected actions.

The candidate correctly identifies an integration boundary: the mixin exposes approval-management endpoints but does not automatically enforce approval on application-specific backend endpoints. The migration guide explicitly says `isCallerApproved()` is only for frontend UI gating and requires canister-side guards to remain. If a developer only hides frontend features without checking approval or admin permission in each custom public function, an unapproved caller may still invoke backend functionality directly. Users should ask the author to confirm that every sensitive custom endpoint has a server-side guard and verify this with direct backend-call tests.

SKILL.md:113In the instructionsOpen original file
IMPORTANT: Apply the right authorization and/or approval check to each custom public function.
Show 4 other places
SKILL.md:119In the instructionsOpen original file
# User Approval Flow- Check approval status (`isCallerApproved`)- If not approved, show option to request approval (`requestApproval`)- Block access to main features for non-approved users- Admins have access to all features of the application- Display approval status clearly in the UI
migration/v0.x.y-to-v1.x.y.md:42In the instructionsOpen original file
Custom endpoints that guard on approval status continue to use the top-level `approvalState`:```motokopublic shared ({ caller }) func protectedFeature() : async () {    if (not (UserApproval.isApproved(approvalState, caller) or AccessControl.hasPermission(accessControlState, caller, #admin))) {        Runtime.trap("Unauthorized: Only approved users can perform this action");    };};```Keep these canister-side guards. The mixin-provided `isCallerApproved()` is a public query for frontend UI gating only; it does not enforce approval on custom backend endpoints.
migration/v0.x.y-to-v1.x.y.md:52In the instructionsOpen original file
Keep these canister-side guards. The mixin-provided `isCallerApproved()` is a public query for frontend UI gating only; it does not enforce approval on custom backend endpoints.
migration/v0.x.y-to-v1.x.y.md:73In the instructionsOpen original file
- [ ] Remove the four mixin-provided functions from `main.mo` and any custom mixins (keep top-level `UserApproval.initState(...)`)- [ ] Update any custom approval guards to use the top-level `approvalState`. Do not replace them with a frontend `isCallerApproved()` check- [ ] Run `mops install`, `mops build`, and `mops lint`
Could it mislead the AI or hide text?Checks the skill instructions for requests to ignore you, influence the report, or hide text in invisible characters.No risks found
Could it change links or payment recipients without asking?Looks for forced referral or payment changes combined with instructions to hide the change.No risks found

Inside this skill

5 instruction sections

The Skill exposes status, request, approval, and listing endpoints through the external `MixinUserApproval` module. The supplied material shows only its interface, not its implementation, so the claimed admin-only checks cannot be independently verified from this source.

View source
SKILL.md:25In the instructionsOpen original file
The prefabricated module `mo:caffeineai-user-approval/approval` provides low-level approval state management. Do not modify it.
SKILL.md:56In the instructionsOpen original file
`include MixinUserApproval(accessControlState, approvalState)` MUST be placed in `main.mo`, not in a custom mixin file. Declare `approvalState` at actor top level and pass it into the mixin. The mixin provides these public endpoints automatically:- `isCallerApproved()`- `requestApproval()`- `setApproval(user, status)`- `listApprovals()`
SKILL.md:142In the instructionsOpen original file
// Get all users and their approval status (admin only)listApprovals(): Promise<Array<UserApprovalInfo>>;// Approve or reject a user (admin only)setApproval(user: Principal, status: ApprovalStatus): Promise<void>;

During initialization, existing administrators are automatically approved while other users remain pending. Administrators therefore receive access to all approval-protected features.

View source
SKILL.md:111In the instructionsOpen original file
On `initState`, existing admins are automatically approved. All other users are pending.
SKILL.md:123In the instructionsOpen original file
- Block access to main features for non-approved users- Admins have access to all features of the application- Display approval status clearly in the UI

The migration instructs users to remove four hand-written approval endpoints and obtain them from the dependency mixin, while retaining approval checks on custom backend endpoints.

View source
migration/v0.x.y-to-v1.x.y.md:18In the instructionsOpen original file
### 2. Replace manual approval endpoints with `MixinUserApproval`Remove all hand-written approval actor endpoints. Keep `approvalState` at actor top level and pass it into the mixin in `main.mo` (not in a custom mixin file):
migration/v0.x.y-to-v1.x.y.md:69In the instructionsOpen original file
- [ ] Bump `caffeineai-user-approval` to `~1.0.0` in `mops.toml`- [ ] Ensure `caffeineai-authorization ~1.0.0` is installed and `include MixinAuthorization(accessControlState, null)` is present in `main.mo`- [ ] Add `let approvalState = UserApproval.initState(accessControlState)` and `include MixinUserApproval(accessControlState, approvalState)` in `main.mo`- [ ] Remove the four mixin-provided functions from `main.mo` and any custom mixins (keep top-level `UserApproval.initState(...)`)- [ ] Update any custom approval guards to use the top-level `approvalState`. Do not replace them with a frontend `isCallerApproved()` check- [ ] Run `mops install`, `mops build`, and `mops lint`- [ ] Regenerate frontend bindings if your workflow requires it
Start here · InstructionsSKILL.md
extension-user-approval
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.
Files and check records2 files

Coverage and gaps

Content covered in each file

These are the source ranges included in this check, not a guarantee that every issue has been resolved.

  • SKILL.mdFull text included
  • migration/v0.x.y-to-v1.x.y.mdFull text included

This report is for the version above. We read the available code and instructions without running the skill or checking extra packages it installs. This is not a promise of safety: a different version or setup may behave differently.

  • SKILL.mdInstructions
  • migration/v0.x.y-to-v1.x.y.mdSupporting file

Operations mentioned in code and instructions

Connect to websites
SKILL.md:13In the instructionsOpen original file
# User ApprovalUser approval extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).
Lines read
229
File checksum (to compare versions)
fe8bb0ad7392cbf568f9e72c76f1316511f832cdc5dbb625da2bffb10c027706