Next.js Server Actions ಒಂದು use-server ಫೈಲ್‌ನಲ್ಲಿರುವ ಪ್ರತಿಯೊಂದು ಎಕ್ಸ್‌ಪೋರ್ಟ್ ಮಾಡಲಾದ ಫಂಕ್ಷನ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸಾರ್ವಜನಿಕ HTTP ಎಂಡ್‌ಪಾಯಿಂಟ್ ಆಗಿ ಪ್ರದರ್ಶಿಸುತ್ತದೆ, ಮತ್ತು ಕ್ಲೈಂಟ್ ಆ ಫಂಕ್ಷನ್ ಅನ್ನು ಕರೆಯಲು ಬಳಸುವ ವಿಶಿಷ್ಟ ಐಡಂಟಿಫೈಯರ್ ಅನ್ನು ಅದಕ್ಕೆ ನಿಯೋಜಿಸುತ್ತದೆ. ಬಟನ್, ಲಿಂಕ್ ಅಥವಾ ಯಾವುದೇ ಇತರ UI ಎಲಿಮೆಂಟ್ ಇರಲಿ ಅಥವಾ ಇಲ್ಲದಿರಲಿ, ಆ ಎಂಡ್‌ಪಾಯಿಂಟ್ ಅಸ್ತಿತ್ವದಲ್ಲಿರುತ್ತದೆ, ಅಂದರೆ ಐಡಂಟಿಫೈಯರ್ ಅನ್ನು ಕಂಡುಕೊಳ್ಳುವ ಯಾರೇ ಆದರೂ ನೇರವಾಗಿ ಆ ಫಂಕ್ಷನ್ ಅನ್ನು ಕರೆಯಬಹುದು.

ಫ್ರೇಮ್‌ವರ್ಕ್‌ನ ವಿನ್ಯಾಸವು Server Actions ಅನ್ನು ಸಾಮಾನ್ಯ ಹೆಲ್ಪರ್ ಫಂಕ್ಷನ್‌ಗಳಂತೆ ಪರಿಗಣಿಸುತ್ತದೆ, ಆದರೆ ರನ್‌ಟೈಮ್‌ನಲ್ಲಿ ಅವು ತಲುಪಬಹುದಾದ URLಗಳಾಗುತ್ತವೆ. UI ಮಾತ್ರ ಏಕೈಕ ಗೇಟ್‌ಕೀಪರ್ ಎಂದು ಭಾವಿಸುವ ಡೆವಲಪರ್‌ಗಳಿಗೆ, ಇದು ಕೇವಲ ಒಂದು ನಿರ್ದಿಷ್ಟ ರಿಕ್ವೆಸ್ಟ್ ಮೂಲಕವೇ ಬಳಸಬಹುದಾದ ಒಂದು ಅದೃಶ್ಯ ಅಟ್ಯಾಕ್ ಸರ್ಫೇಸ್ ಅನ್ನು ಸೃಷ್ಟಿಸುತ್ತದೆ.

Server Actions ಏಕೆ ಸುರಕ್ಷಿತ ಎಂದು ತೋರಿತು

ಪ್ರತ್ಯೇಕ API ರೂಟ್‌ಗಳ ಬೋയ്‌ಲರ್‌ಪ್ಲೇಟ್ ಅನ್ನು ತಪ್ಪಿಸಲು, ಡೆವಲಪರ್‌ಗಳು ತಮ್ಮ ಕಾಂಪೊನೆಂಟ್‌ಗಳ ಪಕ್ಕದಲ್ಲೇ ಸರ್ವರ್-ಸೈಡ್ ಕೋಡ್ ಬರೆಯಲು ಅನುವು ಮಾಡಿಕೊಡಲು Server Actions ಅನ್ನು ಪರಿಚಯಿಸಲಾಯಿತು. ಒಂದು ಸಾಮಾನ್ಯ ಬಳಕೆ ಹೀಗಿರುತ್ತದೆ:

<form action={deleteInvoice}>
  <button type="submit">Delete</button>
</form>

ಫಾರ್ಮ್ ಮೂಲಕ ಮಾತ್ರ deleteInvoice ಅನ್ನು ಟ್ರಿಗ್ಗರ್ ಮಾಡಲು ಸಾಧ್ಯವಿರುವುದರಿಂದ, ಅನೇಕ ಡೆವಲಪರ್‌ಗಳು ಅನಧಿಕೃತ ಬಳಕೆದಾರರಿಗಾಗಿ ಬಟನ್ ಅನ್ನು ಮರೆಮಾಚುತ್ತಾರೆ, TypeScript ಸಿಗ್ನೇಚರ್‌ಗಳು ತಪ್ಪಾದ ಡೇಟಾವನ್ನು ತಡೆಯುತ್ತವೆ ಎಂದು ಭಾವಿಸುತ್ತಾರೆ ಮತ್ತು ಫಂಕ್ಷನ್ ಸರ್ವರ್-ಓನ್ಲಿ ಮಾಡ್ಯೂಲ್‌ನಲ್ಲಿ ಇರುತ್ತದೆ ಎಂಬ ಅಂಶದ ಮೇಲೆ ಅವಲಂಬಿತರಾಗುತ್ತಾರೆ. ಈ ಯಾವುದೇ ಕಲ್ಪನೆಗಳು ನೈಜ ರಕ್ಷಣೆಯನ್ನು ನೀಡುವುದಿಲ್ಲ.

ಗುಪ್ತವಾಗಿ ಬಯಲಾಗುವ ಅಂಶಗಳು

ಒಂದು ಫೈಲ್‌ನಲ್ಲಿ “use server” ಇದ್ದಾಗ, Next.js ಪ್ರತಿಯೊಂದು ಎಕ್ಸ್‌ಪೋರ್ಟ್ ಮಾಡಲಾದ ಫಂಕ್ಷನ್ ಅನ್ನು ಈ ಕೆಳಗಿನಂತೆ ಎಂಡ್‌ಪಾಯಿಂಟ್ ಆಗಿ ಕಾಂಪೈಲ್ ಮಾಡುತ್ತದೆ:

POST /_next/data/<build-id>/<page>.json?__rsc=<action-id>

<action-id> ಎಂಬುದು ಕ್ಲೈಂಟ್ ಬಂಡಲ್‌ನಲ್ಲಿ ಅಳವಡಿಸಲಾದ ಸ್ಥಿರ ಹ್ಯಾಶ್ (stable hash) ಆಗಿದೆ. ದಾಳಿಕೋರರು (attacker) ಇದನ್ನು ಈ ಕೆಳಗಿನ ವಿಧಾನಗಳ ಮೂಲಕ ಪಡೆಯಬಹುದು:

  • ಪೇಜ್‌ನ ನೆಟ್‌ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಪರೀಕ್ಷಿಸುವ ಮೂಲಕ.
  • ಬಂಡಲ್ ಮಾಡಲಾದ JavaScript ಅನ್ನು ಓದುವ ಮೂಲಕ (ID ಎಂಬುದು ಒಂದು ಪ್ಲೇನ್ ಸ್ಟ್ರಿಂಗ್ ಆಗಿರುತ್ತದೆ).
  • ಪ್ರಾಜೆಕ್ಟ್ ಮುನ್ಸೂಚನೆ ನೀಡಬಹುದಾದ ಮಾದರಿಗಳನ್ನು ಅನುಸರಿಸುತ್ತಿದ್ದರೆ, ಹೆಸರಿಸುವ ಪದ್ಧತಿಗಳ (naming conventions) ಆಧಾರದ ಮೇಲೆ ಊಹಿಸುವ ಮೂಲಕ.

ಒಮ್ಮೆ ID ತಿಳಿದ一旦, ಯಾವುದೇ ಟೂಲ್‌ನಿಂದ—cURL, Postman ಅಥವಾ ದುರುದ್ದೇಶಪೂರಿತ ಸ್ಕ್ರಿಪ್ಟ್‌ನಿಂದ—ರಿಕ್ವೆಸ್ಟ್ ಕಳುಹಿಸಬಹುದು, ಇದು ಯಾವುದೇ UI-ಮಟ್ಟದ ಪರಿಶೀಲನೆಗಳನ್ನು ಬೈಪಾಸ್ ಮಾಡುತ್ತದೆ.

ಮೂರು ನಿರ್ದಿಷ್ಟ ಅಪಾಯಗಳು

ಅಪಾಯ ಇದು ಏಕೆ ಮುಖ್ಯ
UI ಪರಿಶೀಲನೆಗಳು ಅಸಮರ್ಥವಾಗಿವೆ ಬಟನ್ ಅಥವಾ ಲಿಂಕ್ ಅನ್ನು ಮರೆಮಾಚುವುದು ಅಡಿಯಲ್ಲಿರುವ ಎಂಡ್‌ಪಾಯಿಂಟ್ ಅನ್ನು ಅಳಿಸುವುದಿಲ್ಲ. ಸರ್ವರ್‌ನಲ್ಲಿ ಇನ್ನೂ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಗುಪ್ತ ಅಡ್ಮಿನ್ ಪೇಜ್‌ನಂತೆ ಎಂಡ್‌ಪಾಯಿಂಟ್ ತಲುಪಲು ಸಾಧ್ಯವಿರುತ್ತದೆ.
TypeScript ರನ್‌ಟೈಮ್ ಸುರಕ್ಷತೆಯನ್ನು ನೀಡುವುದಿಲ್ಲ ಕೋಡ್ ರನ್ ಆಗುವಾಗ ಟೈಪ್‌ಗಳನ್ನು ತೆಗೆದುಹಾಕಲಾಗುತ್ತದೆ. deleteInvoice(id: number) ಎಂದು ಘೋಷಿಸಲಾದ ಫಂಕ್ಷನ್ ದೊಡ್ಡ ಸ್ಟ್ರಿಂಗ್, ಅರೇ ಅಥವಾ ದುರುದ್ದೇಶಪೂರಿತ JSON ಅನ್ನು ಸ್ವೀಕರಿಸಬಹುದು, ಇದು ಲಾಜಿಕ್ ದೋಷಗಳು ಅಥವಾ ಇಂಜೆಕ್ಷನ್ ದಾಳಿಗಳಿಗೆ ಕಾರಣವಾಗಬಹುದು.
ಡಿಫಾಲ್ಟ್ ಅಥೆಂಟಿಕೇಶನ್ ಅಥವಾ ಅಥರೈಸೇಶನ್ ಇಲ್ಲ Server Actions ಸ್ಥಳೀಯ ಹೆಲ್ಪರ್‌ಗಳಂತೆ ಕಾಣುವುದರಿಂದ, ಡೆವಲಪರ್‌ಗಳು ಸಾಂಪ್ರದಾಯಿಕ API ರೂಟ್‌ಗಳಲ್ಲಿ ಇರುವ ಸೆಷನ್ ಚೆಕ್‌ಗಳು, CSRF ರಕ್ಷಣೆ ಅಥವಾ ರೋ-ಲೆವೆಲ್ ಪರ್ಮಿಷನ್ ಚೆಕ್‌ಗಳನ್ನು ಸೇರಿಸಲು ಮರೆಯುತ್ತಾರೆ.

Server Action ಅನ್ನು ಹೇಗೆ ಸುರಕ್ಷಿತಗೊಳಿಸುವುದು

  1. ಕರೆ ಮಾಡುವವರನ್ನು ಅಥೆಂಟಿಕೇಟ್ ಮಾಡಿ – ಯಾವುದೇ ಬಿಸಿನೆಸ್ ಲಾಜಿಕ್ ರನ್ ಆಗುವ ಮೊದಲು ಮಾನ್ಯವಾದ ಸೆಷನ್ ಅಥವಾ ಟೋಕನ್ ಇದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸಿ.
  2. ಪೇಲೋಡ್ ಅನ್ನು ವ್ಯಾಲಿಡೇಟ್ ಮಾಡಿ – ರನ್‌ಟೈಮ್‌ನಲ್ಲಿ ಡೇಟಾ ಟೈಪ್‌ಗಳು ಮತ್ತು ಮೌಲ್ಯದ ಮಿತಿಗಳನ್ನು ಜಾರಿಗೊಳಿಸಲು ಸ್ಕೀಮಾ ಲೈಬ್ರರಿಯನ್ನು (ಉದಾಹರಣೆಗೆ, Zod, Yup) ಬಳಸಿ.
  3. ಆಪರೇಷನ್ ಅನ್ನು ಅಥರೈಸ್ ಮಾಡಿ – “ಬಳಕೆದಾರರು ಲಾಗ್ ಇನ್ ಆಗಿದ್ದಾರೆಯೇ?” ಎಂಬುದನ್ನು ಮೀರಿ, ಅವರು ಮಾರ್ಪಡಿಸಲು ಅಥವಾ ಅಳಿಸಲು ಪ್ರಯತ್ನಿಸುತ್ತಿರುವ ನಿರ್ದಿಷ್ಟ ರೆಕಾರ್ಡ್ ಅವರಿಗೆ ಸೇರಿದ್ದೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ.

ಒಂದು ಕನಿಷ್ಠ ಉದಾಹರಣೆ:

'use server';
import { getSession } from '@/auth';
import { z } from 'zod';
import { db } from '@/db';

const DeleteInvoiceSchema = z.object({
  id: z.number().int().positive(),
});

export async function deleteInvoice(formData: FormData) {
  const session = await getSession();
  if (!session) throw new Error('Unauthenticated');

  const parsed = DeleteInvoiceSchema.safeParse({
    id: Number(formData.get('id')),
  });
  if (!parsed.success) throw new Error('Invalid input');

  const invoice = await db.invoice.findUnique({ where: { id: parsed.data.id } });
  if (!invoice || invoice.ownerId !== session.userId) {
    throw new Error('Unauthorized');
  }

  await db.invoice.delete({ where: { id: invoice.id } });
}

ಈ ಕೋಡ್ ಅಥೆಂಟಿಕೇಶನ್ ಅನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಪರಿಶೀಲಿಸುತ್ತದೆ, ಬರುವ id ಅನ್ನು ವ್ಯಾಲಿಡೇಟ್ ಮಾಡುತ್ತದೆ ಮತ್ತು ಡಿಲೀಟ್ ಮಾಡುವ ಮೊದಲು ಲಾಗ್ ಇನ್ ಆಗಿರುವ ಬಳಕೆದಾರರು ನಿಜವಾಗಿಯೂ ಇನ್‌ವಾಯ್ಸ್‌ನ ಮಾಲೀಕರಾಗಿದ್ದಾರೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳುತ್ತದೆ.

ಇತರ ಸೂಕ್ಷ್ಮ Next.js ತಪ್ಪುಗಳು

ಸಮಸ್ಯೆ ಲಕ್ಷಣ ಪರಿಹಾರ
NEXT_PUBLIC_ ಎನ್ವಿರಾನ್ಮೆಂಟ್ ವೇರಿಯೇಬಲ್‌ಗಳು NEXT_PUBLIC_ ಎಂದು ಪ್ರಾರಂಭವಾಗುವ ಯಾವುದೂ ಕೂಡ ಕ್ಲೈಂಟ್‌ನಲ್ಲಿ ಬಂಡಲ್ ಆಗುತ್ತದೆ, ಇದು ರಹಸ್ಯಗಳನ್ನು (secrets) ಬಯಲಿಗೆತರಬಹುದು. ರಹಸ್ಯಗಳನ್ನು ಸಾಮಾನ್ಯ ಎನ್ವಿರಾನ್ಮೆಂಟ್ ವೇರಿಯೇಬಲ್‌ಗಳಲ್ಲಿ ಇರಿಸಿ, ಅವುಗಳಿಗೆ ಎಂದಿಗೂ NEXT_PUBLIC_ ಪ್ರಿಫಿಕ್ಸ್ ಬಳಸಬೇಡಿ.
ಓಪನ್ ರಿಡೈರೆಕ್ಟ್‌ಗಳು redirect ಕ್ವೆರಿ ಪ್ಯಾರಾಮೀಟರ್ ಅನ್ನು ಸ್ವೀಕರಿಸಿ ಅದನ್ನು ಸುಮ್ಮನೆ ಸೇರಿಸುವುದು ಬಳಕೆದಾರರನ್ನು //evil.com ಗೆ ಕಳುಹಿಸಬಹುದು. ವೈಟ್‌ಲಿಸ್ಟ್ ಮೂಲಕ ಗುರಿಯನ್ನು ವ್ಯಾಲಿಡೇಟ್ ಮಾಡಿ ಅಥವಾ ಸೇಮ್-ಓರಿಜಿನ್ ಚೆಕ್‌ಗಳನ್ನು ಜಾರಿಗೊಳಿಸಿ.
ಸರ್ವರ್-ಸೈಡ್ ರಿಕ್ವೆಸ್ಟ್ ಫೋರ್ಜರಿ (SSRF) ಬಳಕೆದಾರರು ನೀಡಿದ URL ಅನ್ನು ಫೆಚ್ ಮಾಡುವುದು ದಾಳಿಕೋರರಿಗೆ ಆಂತರಿಕ ಸೇವೆಗಳು ಅಥವಾ ಕ್ಲೌಡ್ ಮೆಟಾಡೇಟಾ ಎಂಡ್‌ಪಾಯಿಂಟ್‌ಗಳನ್ನು ತಲುಪಲು ಅವಕಾಶ ಮಾಡಿಕೊಡಬಹುದು. ಹೋಸ್ಟ್‌ನೇಮ್‌ಗಳಿಗೆ ಅಲೋ-ಲಿಸ್ಟ್ ಬಳಸಿ, ಖಾಸಗಿ IP ಶ್ರೇಣಿಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ ಮತ್ತು ಟೈಮ್‌ಔಟ್‌ಗಳನ್ನು ಹೊಂದಿಸಿ.
dangerouslySetInnerHTML ಬಳಕೆದಾರರು ನೀಡಿದ HTML ಅನ್ನು ಸ್ಯಾನಿಟೈಸೇಶನ್ ಇಲ್ಲದೆ ರೆಂಡರ್ ಮಾಡುವುದು XSS ಗೆ ದಾರಿ ಮಾಡಿಕೊಡುತ್ತದೆ. DOMPurify ನಂತಹ ಲೈಬ್ರರಿಯನ್ನು ಬಳಸಿ ಅಥವಾ ನೇರ HTML
  • ಫ್ರೇಮ್‌ವರ್ಕ್ ಅಪ್‌ಡೇಟ್‌ಗಳು – Next.js ಬಿಡುಗಡೆಗಳ ಮೇಲೆ ನಿಗಾ ಇರಿಸಿ; ತಂಡವು built-in authentication hooks ಅನ್ನು ಪರಿಚಯಿಸಬಹುದು ಅಥವಾ ಜನರೇಟ್ ಮಾಡಲಾದ endpoints ಅನ್ನು sandbox ಮಾಡಬಹುದು.
  • ಸಮುದಾಯದ ಟೂಲಿಂಗ್ – ಇಲ್ಲಿ ವಿವರಿಸಲಾದ ಸುರಕ್ಷತಾ ಕ್ರಮಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತಗೊಳಿಸಲು ಹೊಸ ESLint ಪ್ಲಗಿನ್‌ಗಳು ಮತ್ತು Next.js-ನಿರ್ದಿಷ್ಟ Semgrep ನಿಯಮಗಳು ಹೊರಬರುತ್ತಿವೆ.
  • ನೈಜ-ಪ್ರಪಂಚದ ಘಟನೆಗಳು – ಹೆಚ್ಚಿನ ಪ್ರಾಜೆಕ್ಟ್‌ಗಳು Server Actions ಅನ್ನು ಅಳವಡಿಸಿಕೊಳ್ಳುತ್ತಿದ್ದಂತೆ, ಪ್ರಾಯೋಗಿಕವಾಗಿ ಅಪಾಯವನ್ನು ವಿವರಿಸುವ ಬಹಿರಂಗಪಡಿಸಿದ exploits ಬಗ್ಗೆ ಗಮನವಿರಲಿ. ಉಲ್ಲಂಘನೆ (breach) ಸಂಭವಿಸುವ ಮೊದಲು ಆಂತರಿಕ ಭದ್ರತಾ ವಿಮರ್ಶೆಗಳನ್ನು ನಡೆಸಲು ಆರಂಭಿಕ ಪತ್ತೆಬರಹವು ಸಹಕಾರಿಯಾಗುತ್ತದೆ.

ಸಾರಾಂಶ: Next.js Server Action ಎಂಬುದು ಖಾಸಗಿ helper ಅಲ್ಲ; ನೀವು ಅದನ್ನು export ಮಾಡಿದ ಕ್ಷಣವೇ ಅದು ಸಾರ್ವಜನಿಕ HTTP endpoint ಆಗುತ್ತದೆ. ಇದನ್ನು ಯಾವುದೇ ಇತರ API route ನಂತೆ ಪರಿಗಣಿಸಿ—authenticate ಮಾಡಿ, validate ಮಾಡಿ ಮತ್ತು authorize ಮಾಡಿ—ಇಲ್ಲದಿದ್ದರೆ, UI ಪಕ್ಕದಲ್ಲೇ server code ಬರೆಯುವ ಅನುಕೂಲವು ಶೀಘ್ರದಲ್ಲೇ security liability ಆಗಬಹುದು.