{"record":{"id":"774eed370c978cbb","repo":"RocketChat/Rocket.Chat","slug":"error-shield-disabled","errorCode":"error-shield-disabled","errorMessage":"This shield type is disabled","messagePattern":"This shield type is disabled","errorType":"exception","errorClass":"Meteor.Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/misc.ts","lineNumber":237,"sourceCode":"\tasync function action() {\n\t\tconst { type, icon } = this.queryParams;\n\t\tlet { channel, name } = this.queryParams;\n\t\tif (!settings.get('API_Enable_Shields')) {\n\t\t\tthrow new Meteor.Error('error-endpoint-disabled', 'This endpoint is disabled', {\n\t\t\t\troute: '/api/v1/shield.svg',\n\t\t\t});\n\t\t}\n\n\t\tconst types = settings.get<string>('API_Shield_Types');\n\t\tif (\n\t\t\ttype &&\n\t\t\ttypes !== '*' &&\n\t\t\t!types\n\t\t\t\t.split(',')\n\t\t\t\t.map((t: string) => t.trim())\n\t\t\t\t.includes(type)\n\t\t) {\n\t\t\tthrow new Meteor.Error('error-shield-disabled', 'This shield type is disabled', {\n\t\t\t\troute: '/api/v1/shield.svg',\n\t\t\t});\n\t\t}\n\t\tconst hideIcon = icon === 'false';\n\t\tif (hideIcon && !name?.trim()) {\n\t\t\treturn API.v1.failure('Name cannot be empty when icon is hidden');\n\t\t}\n\n\t\tlet text;\n\t\tlet backgroundColor = '#4c1';\n\t\tswitch (type) {\n\t\t\tcase 'online':\n\t\t\t\tif (Date.now() - onlineCacheDate > cacheInvalid) {\n\t\t\t\t\tonlineCache = await Users.countUsersNotOffline();\n\t\t\t\t\tonlineCacheDate = Date.now();\n\t\t\t\t}\n\n\t\t\t\ttext = `${onlineCache} ${i18n.t('Online')}`;","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/2a7de457074cbb4d4373fbd9a4e5bea292c9c764/apps/meteor/server/api/v1/misc.ts#L219-L255","documentation":"shield.svg validates the optional type query parameter against the comma-separated API_Shield_Types setting (misc.ts:228-240). Unless that setting is '*' (the default), a type not present in the list throws error-shield-disabled. This only fires after an admin narrowed the whitelist - with the default '*' every type passes.","triggerScenarios":"GET /api/v1/shield.svg?type=<t> where API_Shield_Types is e.g. 'online,userCount' and <t> is any other value (avatar, channel, etc.), including case mismatches, since the comparison is exact after trimming.","commonSituations":"Admin restricts shields to a few types after a data-exposure review and existing badges of other types start failing; typos or wrong casing in the type parameter; documentation examples using types the workspace never whitelisted.","solutions":["Add the needed type to API_Shield_Types (comma-separated) in Administration -> General -> REST API","Check exact spelling and case of the type parameter against the configured list","Only set '*' if exposing every badge type is acceptable for your security posture"],"exampleFix":"# before\n GET /api/v1/shield.svg?type=avatar&name=alice  # API_Shield_Types = 'online,userCount'\n # => error-shield-disabled\n\n # after: admin adds the type (or uses '*')\n POST /api/v1/settings/API_Shield_Types  {\"value\": \"online,userCount,avatar\"}\n GET /api/v1/shield.svg?type=avatar&name=alice","handlingStrategy":"validation","validationCode":"const allowedTypes = await fetchTypesFromConfig(); // e.g. read API_Shield_Types once via an admin settings call, or cache the known-good list\nconst type = 'online';\nif (allowedTypes !== '*' && !allowedTypes.split(',').map((t) => t.trim()).includes(type)) {\n  throw new Error(`Shield type '${type}' not allowed; configured: ${allowedTypes}`);\n}\nawait fetch(`${server}/api/v1/shield.svg?type=${type}`);","typeGuard":"const isAllowedShieldType = (type: string, configured: string): boolean =>\n  configured === '*' || configured.split(',').map((t) => t.trim()).includes(type);","tryCatchPattern":"try {\n  await fetch(`${server}/api/v1/shield.svg?type=${type}`);\n} catch (err) {\n  if (err?.error === 'error-shield-disabled') {\n    dropBadge(type); // type not whitelisted on this workspace - stop requesting it\n  }\n}","preventionTips":["Match badge type lists between your embed code and the workspace's API_Shield_Types setting","Treat a whitelisted-type failure as permanent until the admin list changes - do not re-request on every page view"],"tags":["rest-api","shields","settings","validation"],"backgroundTag":"feature-disabled-by-setting","analyzedSha":"2a7de457074cbb4d4373fbd9a4e5bea292c9c764","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}