cloudflare / workers-sdk

⛅️ Home to Wrangler, the CLI for Cloudflare Workers®
https://developers.cloudflare.com/workers/
Apache License 2.0
2.62k stars 688 forks source link

🐛 BUG: Error while importing node:buffer #6264

Closed essesoul closed 3 months ago

essesoul commented 3 months ago

Which Cloudflare product(s) does this pertain to?

Workers for Platforms

What version(s) of the tool(s) are you using?

.

What version of Node are you using?

No response

What operating system and version are you using?

windows11

Describe the Bug

When I try to create a worker according to https://developers.cloudflare.com/workers/examples/signing-requests/ ,I get "Uncaught Error: No such module " node:buffer". imported from "worker.js" (Code: 10021)".

I have added "compatibility_flags = [ "nodejs_als" ]" to wrangler.toml as per instructions.

worker.js

import { Buffer } from "node:buffer";

const encoder = new TextEncoder();

const EXPIRY = 600;

export default {
  /**
   *
   * @param {Request} request
   * @param {{SECRET_DATA: string}} env
   * @returns
   */
  async fetch(request, env) {

    const secretKeyData = encoder.encode(
      env.SECRET_DATA ?? "my secret symmetric key"
    );

    const key = await crypto.subtle.importKey(
      "raw",
      secretKeyData,
      { name: "HMAC", hash: "SHA-256" },
      false,
      ["sign", "verify"]
    );

    const url = new URL(request.url);

    if (url.pathname.startsWith("/generate/")) {
      url.pathname = url.pathname.replace("/generate/", "/");

      const timestamp = Math.floor(Date.now() / 1000);
      const dataToAuthenticate = `${url.pathname}${timestamp}`;

      const mac = await crypto.subtle.sign(
        "HMAC",
        key,
        encoder.encode(dataToAuthenticate)
      );

      // Refer to https://developers.cloudflare.com/workers/runtime-apis/nodejs/
      // for more details on using Node.js APIs in Workers
      const base64Mac = Buffer.from(mac).toString("base64");

      url.searchParams.set("verify", `${timestamp}-${base64Mac}`);

      return new Response(`${url.pathname}${url.search}`);
      // Verify all non /generate requests
    } else {
      // Make sure you have the minimum necessary query parameters.
      if (!url.searchParams.has("verify")) {
        return new Response("Missing query parameter", { status: 403 });
      }

      const [timestamp, hmac] = url.searchParams.get("verify").split("-");

      const assertedTimestamp = Number(timestamp);

      const dataToAuthenticate = `${url.pathname}${assertedTimestamp}`;

      const receivedMac = Buffer.from(hmac, "base64");
      const verified = await crypto.subtle.verify(
        "HMAC",
        key,
        receivedMac,
        encoder.encode(dataToAuthenticate)
      );

      if (!verified) {
        return new Response("Invalid MAC", { status: 403 });
      }

      // Signed requests expire after one minute. Note that this value should depend on your specific use case
      if (Date.now() / 1000 > assertedTimestamp + EXPIRY) {
        return new Response(
          `URL expired at ${new Date((assertedTimestamp + EXPIRY) * 1000)}`,
          { status: 403 }
        );
      }
    }

    return fetch(new URL(url.pathname, "https://example.com"), request);
  },
};

wrangler.toml

name = "url-sign"
main = "worker.js"
compatibility_date = "2024-07-15"
compatibility_flags = [ "nodejs_compat" ]

Please provide a link to a minimal reproduction

No response

Please provide any relevant error logs

No response

petebacondarwin commented 3 months ago

Did you use nodejs_compat or nodejs_als as the compatibility flag? The nodejs_als flag only gives access to the node:async_hooks import. For node:buffer you need nodejs_compat. (Also you could try out the new experimental Node.js compatibility option we are trialling by adding experimental:nodejs_compat_v2 flag.)

essesoul commented 3 months ago

The contents of the wrangler.toml file are as follows:

name = "url-sign"
main = "worker.js"
compatibility_date = "2024-07-15"
compatibility_flags = [ "nodejs_compat" ]

I tried experimental:nodejs_compat_v2 and still got the same error, is my formatting wrong?

petebacondarwin commented 3 months ago

Can you provide a link to a github repository that we can clone and test?

essesoul commented 3 months ago

I get an error after clicking deploy after editing online on cloudflare workers&pages

essesoul commented 3 months ago

My code was copied from the https://developers.cloudflare.com/workers/examples/signing-requests/ page

essesoul commented 3 months ago

I've tried using CLI deployment and it works fine already.

Perhaps there is a vulnerability in online deployment.

petebacondarwin commented 3 months ago

Oh did you create a wrangler.toml file in the Dashboard editor? If so, that won't work because we don't process that file online - it is only a Wrangler CLI thing. Instead, online, you need to go and update the compat flags in the settings part of the dashboard for the Worker.

essesoul commented 3 months ago

Yes, I edited wrangler.toml online and now I've solved it.