{"record":{"id":"4710b40de5578a4f","repo":"denoland/deno","slug":"method-is-forbidden","errorCode":null,"errorMessage":"Method is forbidden","messagePattern":"Method is forbidden","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/23_request.js","lineNumber":287,"sourceCode":" * @returns {string}\n */\nfunction validateAndNormalizeMethod(m) {\n  if (RegExpPrototypeExec(HTTP_TOKEN_CODE_POINT_RE, m) === null) {\n    throw new TypeError(\"Method is not valid\");\n  }\n  const upperCase = StringPrototypeToUpperCase(m);\n  switch (upperCase) {\n    case \"DELETE\":\n    case \"GET\":\n    case \"HEAD\":\n    case \"OPTIONS\":\n    case \"POST\":\n    case \"PUT\":\n      return upperCase;\n    case \"CONNECT\":\n    case \"TRACE\":\n    case \"TRACK\":\n      throw new TypeError(\"Method is forbidden\");\n  }\n  return m;\n}\n\nclass Request {\n  /** @type {InnerRequest} */\n  [_request];\n  /** @type {Headers} */\n  [_headersCache];\n  [_getHeaders];\n  [_headersGuard];\n  [_signalCache];\n  [_url];\n  [_method];\n\n  /** @type {Headers} */\n  get [_headers]() {\n    if (this[_headersCache] === undefined) {","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/23_request.js#L269-L305","documentation":"After normalization to uppercase, the methods CONNECT, TRACE, and TRACK hit the forbidden branch of validateAndNormalizeMethod and throw TypeError 'Method is forbidden', as required by the Fetch spec — these verbs cannot be issued from web-platform fetch. TRACK is rejected alongside TRACE for historical IE-era reasons.","triggerScenarios":"fetch(url, { method: 'TRACE' }), new Request(url, { method: 'CONNECT' }), or any casing thereof ('trace', 'Connect'); also proxying a raw method string taken from an inbound request that happened to be TRACE/TRACK.","commonSituations":"Forwarding arbitrary incoming methods in a proxy/gateway, health-check scripts that try TRACE, or feature flags that map to forbidden verbs.","solutions":["Use a different HTTP method; if you need TRACE/CONNECT semantics, use a lower-level TCP/TLS client instead of fetch","When forwarding inbound methods, filter out CONNECT/TRACE/TRACK (reply 405) before constructing the outgoing Request","Map the operation onto a safe custom token method like 'X-Trace' if server and client are both yours"],"exampleFix":"// before\nconst method = inbound.method; // could be 'TRACE'\nawait fetch(target, { method });\n\n// after\nconst FORBIDDEN = new Set(['CONNECT', 'TRACE', 'TRACK']);\nconst method = inbound.method.toUpperCase();\nif (FORBIDDEN.has(method)) return new Response(null, { status: 405 });\nawait fetch(target, { method });","handlingStrategy":"type-guard","validationCode":"const FORBIDDEN = new Set(['CONNECT', 'TRACE', 'TRACK']);\nfunction safeMethod(m) {\n  const upper = String(m).toUpperCase();\n  if (FORBIDDEN.has(upper)) throw new Error(`forbidden method: ${upper}`);\n  return upper;\n}","typeGuard":"/** @param {string} m */\nfunction isAllowedFetchMethod(m) {\n  const u = m.toUpperCase();\n  return /^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/.test(m) && !['CONNECT', 'TRACE', 'TRACK'].includes(u);\n}","tryCatchPattern":null,"preventionTips":["Filter CONNECT/TRACE/TRACK out of forwarded methods (405)","Do not expose arbitrary client-supplied verbs to fetch","Use raw TCP/TLS sockets, not fetch, if TRACE/CONNECT behavior is truly required"],"tags":["fetch","request","http-method","spec-compliance"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}