New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

pow-middleware

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pow-middleware

A middleware for Node.js HTTP request and proof of work handling

latest
Source
npmnpm
Version
0.1.2
Version published
Maintainers
1
Created
Source

POW Middleware

A middleware for Node.js HTTP request and proof of work handling

Installation

npm install pow-middleware

Usage

import express from 'express'
import powMiddleware from 'pow-middleware'

const app = express()
app.use(powMiddleware())

Custom options

app.use(
  powMiddleware({
    secret: 'my-secret-key',
    difficulty: 20,
    trustProxy: true,
    ttl: 5 * 60 * 1_000, // 5 minutes
    powHeaderName: 'x-custom-pow',
    powChallengeHeaderName: 'x-custom-pow-challenge',
  })
)

Solving challenges in browser

Here's a complete example showing how to handle PoW challenges with fetch:

// Step 1: Initial request (will fail with 403)
let response = await fetch(url)

if (response.status === 403) {
  const error = await response.json()
  console.log('Request blocked:', error) // { error: 'pow-required' }

  // Step 2: Extract challenge from response headers
  const challengeHeader = response.headers.get('x-pow-challenge')
  if (!challengeHeader) {
    throw new Error('No challenge provided')
  }

  const challenge = JSON.parse(challengeHeader)
  console.log('Challenge received:', challenge)

  // Step 3: Solve the challenge
  const { hash, solvedChallenge } = await solveChallenge(challenge)
  console.log('Challenge solved! Nonce:', solvedChallenge.nonce)

  // Step 4: Retry request with PoW headers
  response = await fetch(url, {
    headers: {
      'x-pow': hash,
      'x-pow-challenge': JSON.stringify(solvedChallenge),
    },
  })
}
// Helper function to solve the challenge
async function solveChallenge(challenge: any) {
  let nonce = 0
  let hash: string
  while (true) {
    challenge.nonce = nonce
    hash = await computePoWHash(challenge)
    if (checkLeadingZeroBits(hash, challenge.difficulty)) {
      return { hash, solvedChallenge: challenge }
    }
    nonce++
  }
  throw new Error('Failed to solve challenge')
}

// SHA-256 hash function for browser
async function sha256(data: string): Promise<string> {
  const encoder = new TextEncoder()
  const buffer = await crypto.subtle.digest('SHA-256', encoder.encode(data))
  return Array.from(new Uint8Array(buffer))
    .map((b) => b.toString(16).padStart(2, '0'))
    .join('')
}

// Compute PoW hash
async function computePoWHash(challenge: any): Promise<string> {
  const seed = `${challenge.id}:${challenge.ts}:${challenge.difficulty}:${challenge.req}:${challenge.signature}:${challenge.nonce}`
  return await sha256(seed)
}

// Check if hash has required leading zero bits
function checkLeadingZeroBits(hex: string, zeroBitsCount: number): boolean {
  // Convert hex string to bytes
  const bytes = new Uint8Array(hex.length / 2)
  for (let i = 0; i < bytes.length; i++) {
    bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16)
  }

  // Check if first zeroBitsCount bits are 0
  for (let bitIndex = 0; bitIndex < zeroBitsCount; bitIndex++) {
    const byteIndex = Math.floor(bitIndex / 8)
    if (byteIndex >= bytes.length) return false

    const bitPosition = bitIndex % 8
    const mask = 1 << (7 - bitPosition)

    if ((bytes[byteIndex] & mask) !== 0) {
      return false
    }
  }
  return true
}

Keywords

middleware

FAQs

Package last updated on 12 Feb 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts