{"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/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/23_request.js#L269-L305","documentation":"validateAndNormalizeMethod upper-cases the method and rejects CONNECT, TRACE, and TRACK with TypeError \"Method is forbidden\". These methods are excluded from the fetch API for security/spec reasons (request smuggling, cross-site tracing); Deno throws at Request construction time. Custom token methods (e.g. PROPFIND) are allowed — only these three are forbidden.","triggerScenarios":"new Request(url, { method: \"TRACE\" }); { method: \"CONNECT\" }; { method: \"track\" } (case-insensitive).","commonSituations":"Generic HTTP clients being ported to fetch; test harnesses enumerating all standard methods; security scanners probing with TRACE; code driven by user-supplied method allow-lists that include forbidden methods.","solutions":["Remove CONNECT/TRACE/TRACK from the set of methods your code can issue","Use a raw TCP socket (Deno.connect) for CONNECT-style tunneling instead of fetch","Filter user-configurable methods against a deny-list before constructing the Request"],"exampleFix":"// before\nconst FORBIDDEN = new Set([\"connect\", \"trace\", \"track\"]);\nnew Request(\"https://example.com\", { method: \"TRACE\" }); // throws\n\n// after\nif (!FORBIDDEN.has(method.toLowerCase())) {\n  new Request(\"https://example.com\", { method });\n}","handlingStrategy":"validation","validationCode":"const FORBIDDEN_METHODS = new Set([\"connect\", \"trace\", \"track\"]);\nif (FORBIDDEN_METHODS.has(String(method).toLowerCase())) {\n  throw new Error(`Method ${method} is forbidden in fetch`);\n}\nconst req = new Request(url, { method });","typeGuard":"const FORBIDDEN = new Set([\"connect\", \"trace\", \"track\"]);\nfunction isAllowedFetchMethod(m: string): boolean {\n  return !FORBIDDEN.has(m.toLowerCase());\n}","tryCatchPattern":"try {\n  new Request(url, { method });\n} catch (err) {\n  if (err instanceof TypeError && err.message === \"Method is forbidden\") {\n    // reject the client request or substitute GET\n  } else throw err;\n}","preventionTips":["Filter CONNECT/TRACE/TRACK out of any user-supplied method allow-list","Remember the check is case-insensitive ('track' throws too)","Use raw sockets (Deno.connect) for tunneling, never fetch with CONNECT"],"tags":["fetch","request","http-method","forbidden"],"backgroundTag":"forbidden-http-method","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}