{"record":{"id":"e208c9e34ede7b38","repo":"instructure/canvas-lms","slug":"insufficient-permission-delete-internal-setting","errorCode":null,"errorMessage":"insufficient permission","messagePattern":"insufficient permission","errorType":"exception","errorClass":"GraphQL::ExecutionError","httpStatus":null,"severity":"warning","filePath":"app/graphql/mutations/delete_internal_setting.rb","lineNumber":29,"sourceCode":"#\n# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY\n# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR\n# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\n# details.\n#\n# You should have received a copy of the GNU Affero General Public License along\n# with this program. If not, see <http://www.gnu.org/licenses/>.\n#\nclass Mutations::DeleteInternalSetting < Mutations::BaseMutation\n  graphql_name \"DeleteInternalSetting\"\n\n  argument :internal_setting_id, ID, required: true, prepare: GraphQLHelpers.relay_or_legacy_id_prepare_func(\"InternalSetting\")\n\n  field :internal_setting_id, ID, null: false\n\n  def resolve(input:)\n    if !Account.site_admin.grants_right?(current_user, :manage_internal_settings) || (internal_setting = Setting.find(input[:internal_setting_id])).secret\n      raise GraphQL::ExecutionError, \"insufficient permission\"\n    end\n\n    context[:deleted_models] = { internal_setting: }\n    Setting.remove(internal_setting.name)\n\n    { internal_setting_id: CanvasSchema.id_from_object(internal_setting, Types::InternalSettingType, nil) }\n  rescue ActiveRecord::RecordNotFound\n    raise GraphQL::ExecutionError, \"not found\"\n  end\n\n  def self.internal_setting_id_log_entry(_topic, context)\n    context[:deleted_models][:internal_setting]\n  end\nend\n","sourceCodeStart":11,"sourceCodeEnd":44,"githubUrl":"https://github.com/instructure/canvas-lms/blob/1c9f0bb8013ed69c4f2efe11fd483025469b7e6c/app/graphql/mutations/delete_internal_setting.rb#L11-L44","documentation":"The deleteInternalSetting mutation raises \"insufficient permission\" when the caller is not a site admin with :manage_internal_settings rights, OR when the targeted Setting is marked secret. Both conditions are collapsed into a single error by design to avoid leaking information about secret settings.","triggerScenarios":"Calling deleteInternalSetting with a non-site-admin token, a site admin lacking manage_internal_settings, or passing the id of a secret setting (Setting.secret == true).","commonSituations":"Developers using regular account-admin tokens instead of site-admin credentials, or attempting to delete protected internal settings that Canvas intentionally hides from deletion.","solutions":["Authenticate as a site admin (Account.site_admin) with :manage_internal_settings permission","Check the setting is not secret via Setting before attempting deletion","Verify the user's role overrides at the site-admin account level","If the setting is secret, manage it through console/Setting API instead"],"exampleFix":"// before\nSetting.remove(input[:internal_setting_id])\n// after\nraise GraphQL::ExecutionError, \"insufficient permission\" unless Account.site_admin.grants_right?(current_user, :manage_internal_settings)\nsetting = Setting.find(input[:internal_setting_id])\nraise GraphQL::ExecutionError, \"insufficient permission\" if setting.secret","handlingStrategy":"try-catch","validationCode":"const isSiteAdmin = await query(myPermissions, { accountId: \"site_admin\" });\nif (!isSiteAdmin?.manageInternalSettings) return skip();","typeGuard":"function hasInternalSettingsAccess(perms) {\n  return perms?.manageInternalSettings === true;\n}","tryCatchPattern":"try {\n  await client.mutate(DELETE_INTERNAL_SETTING, { internalSettingId });\n} catch (e) {\n  if (e.message === \"insufficient permission\") {\n    // escalate token or skip secret settings\n  } else throw e;\n}","preventionTips":["Use site-admin credentials for internal setting operations","Skip settings flagged secret in the settings list UI","Document required site-admin rights for the integration","Verify role overrides before deploying automation"],"tags":["graphql","authorization","site-admin","internal-setting"],"backgroundTag":"insufficient-permissions","analyzedSha":"1c9f0bb8013ed69c4f2efe11fd483025469b7e6c","analyzedAt":"2026-09-15T20:33:18.891Z","contentChangedAt":"2026-09-15T20:33:18.891Z","schemaVersion":2},"datasetVersion":"2026-09-23T02:17:17.105Z"}