{"record":{"id":"cbf30648fc30e049","repo":"RocketChat/Rocket.Chat","slug":"the-environmental-variable-envvarname-is-not","errorCode":null,"errorMessage":"The environmental variable \"${envVarName}\" is not readable.","messagePattern":"The environmental variable \"(.+?)\" is not readable\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/app/apps/server/bridges/environmental.ts","lineNumber":16,"sourceCode":"import type { IAppServerOrchestrator } from '@rocket.chat/apps';\nimport { EnvironmentalVariableBridge } from '@rocket.chat/apps/dist/server/bridges/EnvironmentalVariableBridge';\n\nexport class AppEnvironmentalVariableBridge extends EnvironmentalVariableBridge {\n\tallowed: Array<string>;\n\n\tconstructor(private readonly orch: IAppServerOrchestrator) {\n\t\tsuper();\n\t\tthis.allowed = ['NODE_ENV', 'ROOT_URL', 'INSTANCE_IP'];\n\t}\n\n\tprotected async getValueByName(envVarName: string, appId: string): Promise<string | undefined> {\n\t\tthis.orch.debugLog(`The App ${appId} is getting the environmental variable value ${envVarName}.`);\n\n\t\tif (!(await this.isReadable(envVarName, appId))) {\n\t\t\tthrow new Error(`The environmental variable \"${envVarName}\" is not readable.`);\n\t\t}\n\n\t\treturn process.env[envVarName];\n\t}\n\n\tprotected async isReadable(envVarName: string, appId: string): Promise<boolean> {\n\t\tthis.orch.debugLog(`The App ${appId} is checking if the environmental variable is readable ${envVarName}.`);\n\n\t\treturn this.allowed.includes(envVarName.toUpperCase()) || this.isAppsOwnVariable(envVarName, appId);\n\t}\n\n\tprotected isAppsOwnVariable(envVarName: string, appId: string): boolean {\n\t\t/**\n\t\t * Replace the letter `-` with `_` since environment variable name doesn't support it\n\t\t */\n\t\tconst appVariablePrefix = `RC_APPS_${appId.toUpperCase().replace(/-/g, '_')}`;\n\t\treturn envVarName.toUpperCase().startsWith(appVariablePrefix);\n\t}","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/app/apps/server/bridges/environmental.ts#L1-L34","documentation":"`AppEnvironmentalVariableBridge.getValueByName` (environmental.ts:12-20) returns an env var's value, but only after `isReadable` passes. A variable is readable if its uppercased name is in the hardcoded allowlist (`NODE_ENV`, `ROOT_URL`, `INSTANCE_IP`) OR it starts with `RC_APPS_<APPID>_` (appId uppercased, dashes to underscores) — see isAppsOwnVariable (environmental.ts:28-34). Otherwise the bridge throws; apps cannot read arbitrary process.env entries.","triggerScenarios":"App calls `environmentVariableReader.getValueByName('SECRET_TOKEN')` where the name is neither allowlisted nor prefixed with RC_APPS_<APPID>_.","commonSituations":"App trying to read a secret/config var without the required prefix; developer unaware of the allowlist; appId-derived prefix computed incorrectly (e.g. dashes not replaced).","solutions":["Prefix the variable with RC_APPS_<APPID>_ (e.g. RC_APPS_<APPID>_API_KEY).","Use only NODE_ENV, ROOT_URL, or INSTANCE_IP for non-prefixed reads.","Call isReadable first (it returns a boolean and does not throw) to check without failing."],"exampleFix":"// before\nconst v = await envReader.getValueByName('API_KEY')\n// after (set env RC_APPS_<APPID>_API_KEY, then)\nconst v = await envReader.getValueByName(`RC_APPS_${appId.toUpperCase().replace(/-/g, '_')}_API_KEY`)","handlingStrategy":"validation","validationCode":"async function safeGetEnv(envReader: any, name: string): Promise<string | undefined> {\n  if (!(await envReader.isReadable(name))) {\n    return undefined; // not allowed; do not call getValueByName\n  }\n  return envReader.getValueByName(name);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Namespace all app-specific env vars under RC_APPS_<APPID>_.","Whitelist expected names in your app config and validate against them.","Use isReadable (throw-free) as the probe before getValueByName."],"tags":["apps-engine","environment","security","validation"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}