From 7ef038e9f7df13e8383943fdc97d3d2404360d87 Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Sun, 8 Dec 2024 20:52:34 -0500 Subject: [PATCH] Return correct HTTP status for disallowed HTTP methods Make sure that we return the correct HTTP status for disallowed HTTP methods: - For pages that do not exist, return 404. - For pages that do exist but do not support the requested method, return 405. A fact of life on the Internet is that public sites are constantly being probed for vulnerabilities or misconfigurations of common frameworks. These requests often attempt to POST or PUT to irrelevant endpoints. Before this patch, we were logging something like this for each such request: ``` 2024-12-08T13:52:31.557Z 48395885-e0a7-4cda-a750-3d5267bb20d1 ERROR Error: You made a POST request to "/wp-admin/admin-ajax.php" but did not provide an `action` for route "routes/$", so there is no way to handle the request. at sa (/var/task/index.cjs:49:10806) at u (/var/task/index.cjs:48:47306) at c (/var/task/index.cjs:48:46995) at Object.s [as query] (/var/task/index.cjs:48:46027) at Nvt (/var/task/index.cjs:64:17420) at /var/task/index.cjs:64:15716 at /var/task/index.cjs:137:7577 at Runtime.hOr [as handler] (/var/task/index.cjs:2326:74163) 2024-12-08T13:52:31.616Z 48395885-e0a7-4cda-a750-3d5267bb20d1 ERROR Error: Invariant failed at Ln (/var/task/index.cjs:318:39742) at lm (/var/task/index.cjs:340:1264) at O2 (/var/task/index.cjs:340:1930) at Blr (/var/task/index.cjs:340:2261) at y8e (/var/task/index.cjs:192:3805) at rZ (/var/task/index.cjs:192:4617) at gu (/var/task/index.cjs:192:7257) at rZ (/var/task/index.cjs:192:6651) at gu (/var/task/index.cjs:192:7257) at rZ (/var/task/index.cjs:192:6651) 2024-12-08T13:52:31.619Z 48395885-e0a7-4cda-a750-3d5267bb20d1 ERROR Error: Invariant failed at Ln (/var/task/index.cjs:318:39742) at lm (/var/task/index.cjs:340:1264) at O2 (/var/task/index.cjs:340:1930) at Blr (/var/task/index.cjs:340:2261) at y8e (/var/task/index.cjs:192:3805) at rZ (/var/task/index.cjs:192:4617) at gu (/var/task/index.cjs:192:7257) at rZ (/var/task/index.cjs:192:6651) at gu (/var/task/index.cjs:192:7257) at rZ (/var/task/index.cjs:192:6651) ``` Don't treat these as server errors and don't log them. Do return the correct HTTP status. --- app/components/CircularsEmailAddress.tsx | 2 +- app/components/NoticeFormat.tsx | 2 +- app/lib/utils.ts | 2 +- app/root.tsx | 38 ++++++++++-------------- app/routes/$.ts | 6 +++- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/app/components/CircularsEmailAddress.tsx b/app/components/CircularsEmailAddress.tsx index 1a7cd72f7..ee5e3aade 100644 --- a/app/components/CircularsEmailAddress.tsx +++ b/app/components/CircularsEmailAddress.tsx @@ -9,7 +9,7 @@ import { useHostname } from '~/root' export function useCircularsEmailAddress() { let hostname = useHostname() - if (!hostname.endsWith('gcn.nasa.gov')) hostname = 'test.gcn.nasa.gov' + if (!hostname?.endsWith('gcn.nasa.gov')) hostname = 'test.gcn.nasa.gov' return `circulars@${hostname}` } diff --git a/app/components/NoticeFormat.tsx b/app/components/NoticeFormat.tsx index acf1789f6..517adb26b 100644 --- a/app/components/NoticeFormat.tsx +++ b/app/components/NoticeFormat.tsx @@ -18,7 +18,7 @@ export function NoticeFormatInput({ onChange, }: { name: string - showJson: boolean + showJson?: boolean value?: NoticeFormat onChange?: (arg: NoticeFormat) => void }) { diff --git a/app/lib/utils.ts b/app/lib/utils.ts index bfd4c4b48..11e67ea6f 100644 --- a/app/lib/utils.ts +++ b/app/lib/utils.ts @@ -45,7 +45,7 @@ export function getFormDataString(formData: FormData, key: string) { } } -export function getEnvBannerHeaderAndDescription(hostname: string) { +export function getEnvBannerHeaderAndDescription(hostname?: string) { const production_hostname = 'gcn.nasa.gov' let heading, description if (hostname === `dev.${production_hostname}`) { diff --git a/app/root.tsx b/app/root.tsx index 2622d8f4c..2e5d2fd9b 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -138,39 +138,31 @@ export function shouldRevalidate() { } function useLoaderDataRoot() { - const result = useRouteLoaderData('root') - invariant(result) - return result + return useRouteLoaderData('root') } export function useUserIdp() { - const { idp } = useLoaderDataRoot() - return idp + return useLoaderDataRoot()?.idp } export function useEmail() { - const { email } = useLoaderDataRoot() - return email + return useLoaderDataRoot()?.email } export function useName() { - const { name } = useLoaderDataRoot() - return name + return useLoaderDataRoot()?.name } export function useModStatus() { - const { userIsMod } = useLoaderDataRoot() - return userIsMod + return useLoaderDataRoot()?.userIsMod } export function useSubmitterStatus() { - const { userIsVerifiedSubmitter } = useLoaderDataRoot() - return userIsVerifiedSubmitter + return useLoaderDataRoot()?.userIsVerifiedSubmitter } export function useRecaptchaSiteKey() { - const { recaptchaSiteKey } = useLoaderDataRoot() - return recaptchaSiteKey + return useLoaderDataRoot()?.recaptchaSiteKey } /** @@ -183,7 +175,7 @@ export function useRecaptchaSiteKey() { */ export function useFeature(feature: string) { const featureUppercase = feature.toUpperCase() - return useLoaderDataRoot().features.includes(featureUppercase) + return useLoaderDataRoot()?.features.includes(featureUppercase) } export function WithFeature({ @@ -195,8 +187,13 @@ export function WithFeature({ return <>{useFeature(Object.keys(features)[0]) && children} } +export function useOrigin() { + return useLoaderDataRoot()?.origin +} + export function useUrl() { - const { origin } = useLoaderDataRoot() + const origin = useOrigin() + invariant(origin) const { pathname, search, hash } = useLocation() const url = new URL(origin) url.pathname = pathname @@ -205,12 +202,9 @@ export function useUrl() { return url.toString() } -export function useOrigin() { - return useLoaderDataRoot().origin -} - export function useHostname() { - return new URL(useLoaderDataRoot().origin).hostname + const origin = useOrigin() + if (origin) return new URL(origin).hostname } export function useDomain() { diff --git a/app/routes/$.ts b/app/routes/$.ts index a998d5141..7f4f76e20 100644 --- a/app/routes/$.ts +++ b/app/routes/$.ts @@ -1,5 +1,5 @@ import type { SEOHandle } from '@nasa-gcn/remix-seo' -import type { LoaderFunction } from '@remix-run/node' +import type { ActionFunction, LoaderFunction } from '@remix-run/node' import type { BreadcrumbHandle } from '~/root/Title' @@ -12,4 +12,8 @@ export const loader: LoaderFunction = function () { throw new Response(null, { status: 404 }) } +export const action: ActionFunction = function () { + throw new Response(null, { status: 404 }) +} + export default function () {}