Skip to content
Report library
Purpose / Documents

Extension Object Storage Skill Security Audit

What the author says it does (original text)

General file/object storage, such as for images, videos, files, documents and other bulk data. Perfect fit for image galleries, video galleries, and other file or object management. Supports large files beyond IC limit, with browser-cached HTTP URL access.

Independent security check

Security risks found

Files checked
1
Risks found
2
Could it run dangerous commands?Looks for programs run straight after downloading, remote control of your computer, and hidden commands.Risks found: 1
Low risk

Adopting the Skill places third-party frontend and backend packages in the application's execution path

Source references: 5
What we found

The instructions make installation of two named packages and invocation of their mixin/API mandatory. The frontend package receives complete upload contents, and the backend package supplies platform-reserved methods, so these are not compile-time type declarations alone. Their source is absent from the supplied material, so this audit cannot verify their actual network destinations or other side effects.

Why this matters

The packages and their transitive dependencies gain the capabilities of their respective build or runtime environments. File data and application behavior could be affected if package provenance, publisher, or resolved versions differ from expectations.

What this evidence establishes

The instructions do require installing and executing named npm and mops packages: the frontend API receives complete file bytes, and the backend mixin supplies storage infrastructure, so both enter the upload path. That is consistent with the Skill’s stated object-storage purpose; third-party dependencies alone do not establish malicious behavior. However, their source is absent, so the network destination, permission scope, and additional side effects cannot be verified. Users can ask for pinned versions, source-review results, and the actual gateway domain, and restrict dependency and network permissions.

This assessment concerns the code and conditions shown, not proof that harm has occurred.
SKILL.md:22In the instructionsOpen original file
1. **mops dependency** — add `caffeineai-object-storage` to `mops.toml` under `[dependencies]`.2. **Mixin invocation** — `include MixinObjectStorage()` in `main.mo` (imported from `"mo:caffeineai-object-storage/Mixin"`).3. **Storage.ExternalBlob types** — every data field that represents a file MUST use `Storage.ExternalBlob`, never `Text`.4. **Frontend npm package** — `@caffeineai/object-storage` installed and `ExternalBlob.fromBytes(bytes, file.type, file.name)` used at the call site.
Show 4 other places
SKILL.md:27In the instructionsOpen original file
CRITICAL: The frontend package (`@caffeineai/object-storage`) does NOT work without the backend mops package (`caffeineai-object-storage`). Installing only the npm package and not the mops package causes silent upload failures (403 from the storage gateway). You MUST install both together.
SKILL.md:74In the instructionsOpen original file
NEVER create your own implementation of `_immutableObjectStorageCreateCertificate` or any other `_immutableObjectStorage*` method. These are platform-reserved method names provided exclusively by the `MixinObjectStorage` mixin from the mops package. Hand-written implementations produce wrong return types and cause `403 Forbidden: Invalid payload` at upload time.
SKILL.md:49In the instructionsOpen original file
The only type you use from `mo:caffeineai-object-storage/Storage` is `ExternalBlob` (which is `Blob`). All other functions in `Storage.mo` are internal infrastructure used by `MixinObjectStorage` -- do not call them directly.
SKILL.md:132In the instructionsOpen original file
```typescriptconst handleUpload = async (file: File) => {  const bytes = new Uint8Array(await file.arrayBuffer());  const blob = ExternalBlob.fromBytes(bytes, file.type, file.name).withUploadProgress((pct) => {    setProgress(pct);  });  await actor.uploadFile(file.name, blob);};
Could it expose your files or keys?Looks for uploads of files containing passwords or keys, and keys written directly in the code.Risks found: 1
Medium risk

File contents and original filenames leave the application backend for an external storage gateway

Source references: 4
What we found

The Skill explicitly uses off-chain storage and directs the frontend to pass the file's full bytes, browser-supplied MIME type, and original filename to the storage library. The filename is placed in the gateway's Content-Disposition metadata and also retained by the application backend. The provided material does not identify the gateway operator or state retention, access-control, or deletion rules.

Why this matters

Sensitive document contents and filenames containing names, customer numbers, or project details may reside outside the application's database. Reviewing only on-chain or backend records could therefore understate the data-residency, disclosure, and compliance scope.

When this Skill is adopted and a file is uploaded, the frontend reads the complete file and gives its bytes, MIME type, and original filename to the external-storage component. The text explicitly says content is stored off-chain while the backend stores only a reference. The gateway also returns the filename in Content-Disposition. Thus, file content and names cross the application backend’s data boundary. The supplied material does not describe the gateway operator, retention, access controls, or deletion process; users should confirm these before uploading sensitive files.

SKILL.md:16In the instructionsOpen original file
This skill adds off-chain file/object storage with on-chain references. The `MixinObjectStorage` mixin provides infrastructure for file operations; you track uploaded files in your own data structures using `Storage.ExternalBlob`.
Show 3 other places
SKILL.md:129In the instructionsOpen original file
Pass the browser `File` type and name into `fromBytes` so the gateway blob tree stores `Content-Type` and `Content-Disposition` (original filename). Also pass `file.name` to the backend so app records keep the filename for lists and UI.
SKILL.md:132In the instructionsOpen original file
```typescriptconst handleUpload = async (file: File) => {  const bytes = new Uint8Array(await file.arrayBuffer());  const blob = ExternalBlob.fromBytes(bytes, file.type, file.name).withUploadProgress((pct) => {    setProgress(pct);  });  await actor.uploadFile(file.name, blob);};```
SKILL.md:31In the instructionsOpen original file
File content is stored off-chain. The backend manages references to external files using the `Storage.ExternalBlob` type from `mo:caffeineai-object-storage/Storage`. The frontend handles the actual upload/download; the backend only stores the reference.
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.No risks found
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

4 instruction sections

The Skill requires both a backend mops package and a frontend npm package. The backend mixin supplies platform-reserved storage methods, while the frontend library performs the actual uploads and downloads.

View source
SKILL.md:22In the instructionsOpen original file
1. **mops dependency** — add `caffeineai-object-storage` to `mops.toml` under `[dependencies]`.2. **Mixin invocation** — `include MixinObjectStorage()` in `main.mo` (imported from `"mo:caffeineai-object-storage/Mixin"`).3. **Storage.ExternalBlob types** — every data field that represents a file MUST use `Storage.ExternalBlob`, never `Text`.4. **Frontend npm package** — `@caffeineai/object-storage` installed and `ExternalBlob.fromBytes(bytes, file.type, file.name)` used at the call site.
SKILL.md:31In the instructionsOpen original file
File content is stored off-chain. The backend manages references to external files using the `Storage.ExternalBlob` type from `mo:caffeineai-object-storage/Storage`. The frontend handles the actual upload/download; the backend only stores the reference.

The upload flow reads all bytes from the browser File and passes the content, MIME type, and original filename to the external-storage library; the application backend separately retains the filename.

View source
SKILL.md:129In the instructionsOpen original file
Pass the browser `File` type and name into `fromBytes` so the gateway blob tree stores `Content-Type` and `Content-Disposition` (original filename). Also pass `file.name` to the backend so app records keep the filename for lists and UI.
SKILL.md:132In the instructionsOpen original file
```typescriptconst handleUpload = async (file: File) => {  const bytes = new Uint8Array(await file.arrayBuffer());  const blob = ExternalBlob.fromBytes(bytes, file.type, file.name).withUploadProgress((pct) => {    setProgress(pct);  });  await actor.uploadFile(file.name, blob);};```

For display, the Skill uses an opaque proxy URL generated by the storage library. For downloads, it retrieves the full bytes from storage and triggers a browser save.

View source
SKILL.md:146In the instructionsOpen original file
Use `getDirectURL()` for inline display (images, videos). This returns an opaque proxy URL -- it has no file extension, so never inspect the URL to determine file type.```typescript<img src={record.blob.getDirectURL()} alt={record.filename} />```
SKILL.md:179In the instructionsOpen original file
```typescriptconst handleDownload = async (record: FileRecord) => {  const bytes = await record.blob.getBytes();  const blob = new Blob([bytes]);  const url = URL.createObjectURL(blob);  const a = document.createElement("a");  a.href = url;  a.download = record.filename;  document.body.appendChild(a);  a.click();  document.body.removeChild(a);  URL.revokeObjectURL(url);};```
Start here · InstructionsSKILL.md
extension-object-storage
Lines connect the instruction file to its sections, not an observed execution order. Select a section to read the source.
Files and check records1 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

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

Operations mentioned in code and instructions

Connect to websites
SKILL.md:12In the instructionsOpen original file
# Object StorageObject storage extension for [Caffeine AI](https://caffeine.ai?utm_source=caffeine-skill&utm_medium=referral).
Install extra software packages
SKILL.md:220In the instructionsOpen original file
| `403 Forbidden: Invalid payload` on `PUT /v1/blob-tree/` | Backend canister missing `_immutableObjectStorageCreateCertificate` or returning wrong type | Install `caffeineai-object-storage` in mops.toml, add `include MixinObjectStorage()`  | `403 Forbidden: Invalid payload` (all files) | `@caffeineai/object-storage` npm installed but `caffeineai-object-storage` mops NOT installed | Add the mops dependency and rebuild backend || Method exists but still 403 | Hand-written stub returns wrong type (e.g. `Blob` or `()` instead of `record { method; blob_hash }`) | Remove the custom implementation, use the platform mixin instead |
Lines read
223
File checksum (to compare versions)
3ce7112beafb81678ec6391e151119d650f34c243ec744a0667e08633597f7c7