fix: let untrusted plugins upload attachments for the composer again

This commit is contained in:
Linus Rath
2026-10-14 02:34:31 +02:00
parent f048db7b52
commit cef2438c33
3 changed files with 12 additions and 6 deletions
+8 -3
View File
@@ -306,11 +306,16 @@ describe('native keyword extension API', () => {
});
});
describe('privileged-only methods', () => {
it('refuses jmap.uploadBlob to an untrusted plugin even with email:blob-write', async () => {
describe('jmap.uploadBlob', () => {
it('is open to an untrusted plugin with email:blob-write, for composer attachment sources', async () => {
const p = plugin({ permissions: ['email:blob-write'], grantedPermissions: ['email:blob-write'] });
expect(await gateError(p, 'jmap.uploadBlob', [new Uint8Array(1), 'a.bin', 'application/octet-stream']))
.toMatch(/requires the privileged plugin tier/);
.not.toMatch(GATE_FAILURE);
});
it('still needs email:blob-write', async () => {
expect(await gateError(plugin(), 'jmap.uploadBlob', [new Uint8Array(1), 'a.bin', 'x/y']))
.toMatch(/lacks permission "email:blob-write"/);
});
});
+3 -3
View File
@@ -40,9 +40,9 @@ import { EncryptionAtRestConfig, PublicKeyInfo, PublicKeyInput, useAccountSecuri
*/
const PRIVILEGED_ONLY_METHODS = new Set<string>([
'jmap.fetchBlob',
// Puts arbitrary bytes on the mail server. Untrusted plugins attach files
// through the composer and draft APIs instead, which bound and label them.
'jmap.uploadBlob',
// NOTE: jmap.uploadBlob is deliberately NOT here. The composer's
// `composer-attachment-source` slot is built for untrusted plugins that
// upload a file (from cloud storage, say) and hand the blob id to onAttach.
'jmap.sendRaw',
'jmap.submitRaw',
'jmap.importRaw',
+1
View File
@@ -328,6 +328,7 @@ function buildPluginApi(manifest: PluginManifest) {
/** Fetch a blob's raw bytes by id. Resolves to a Uint8Array. */
fetchBlob: (blobId: string, opts?: { name?: string; type?: string, rangeHeader?: number }) =>
callApi('jmap.fetchBlob', [blobId, opts]) as Promise<Uint8Array>,
/** Upload bytes to the mail server (email:blob-write); pass the blob id to a composer's onAttach. */
uploadBlob: (content: Uint8Array, name: string, type: string) =>
callApi('jmap.uploadBlob', [content, name, type]) as Promise<{ blobId: string; size: number; type: string; }>,
/** Submit a fully-formed raw RFC822 message (already signed/encrypted). */