Workers GitHub Hook integration Error: TypeError: timingSafeEqual is not a function

Hi, new to Workers and trying to expand my JS knowledge and learn more about the framework and general web development.

I’m going through the “GitHub SMS notifications using Twilio” tutorial and rather than use Twilio I’m testing it with Pushover.

The function runs fine in wrangler dev mode, albeit I’m skipping the checkSignature function :sweat_smile:.

The hook is triggered successfully, however the response is weird: Error: TypeError: timingSafeEqual is not a function

Since I’m not familiar with with node:crypto package, thought it would be worth checking with the community.

thanks for the help!

code looks like this:

import { createHmac, timingSafeEqual } from 'node:crypto';
import { Buffer } from 'node:buffer';

function checkSignature(text, headers, githubSecretToken) {
	const hmac = createHmac('sha256', githubSecretToken);
	const expectedSignature = hmac.digest('hex');
	const actualSignature = headers.get('X-Hub-Signature-256');

	const trusted = Buffer.from(`sha256=${expectedSignature}`, 'utf8');
	const untrusted = Buffer.from(actualSignature, 'utf8');

	return trusted.byteLength == untrusted.byteLength
		&& timingSafeEqual(trusted, untrusted);

async function sendMsg(accountID, authToken, msg) {
	const endpoint = '';
	const enconded = new URLSearchParams({
		'token': authToken,
		'user': accountID,
		'message': msg

	const request = {
		body: enconded,
		method: 'POST',
		headers: {
			'Content-Type': 'application/x-www-form-urlencoded',

	const response = await fetch(endpoint, request);
	const result = await response.json();

	return Response.json(result);

export default {
	async fetch(request, env, ctx) {
		if (request.method !== 'POST') {
			return new Response('Please send a POST request!');
		try {
			const rawBody = await request.text();

			if (!checkSignature(rawBody, request.headers, env.GITHUB_SECRET_TOKEN)) {
				return new Response("Wrong password, try again", { status: 403 });

			const action = request.headers.get('X-GitHub-Event');
			const json = JSON.parse(rawBody);
			const repoName = json.repository.full_name;
			const senderName = json.sender.login;

			return await sendMsg(
				`${senderName} completed ${action} on repo ${repoName}`
		} catch (e) {
			return new Response(`Error:  ${e}`);



So it turns out the way to get the function to work is to use the to use crypto.subtle.timingSafeEqual :person_shrugging:

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.