
Research
Supply Chain Attack on Axios Pulls Malicious Dependency from npm
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.
node-webpush
Advanced tools
A dependency-free Web Push implementation for Node.js (TypeScript-first).
This library focuses on standards-compliant payload encryption + VAPID authentication, and produces request details
that can be sent with Node’s built-in fetch().
aes128gcm).aes128gcm (recommended): modern Web Push encoding (RFC 8291 + RFC 8188).aesgcm (legacy): kept for interoperability with older endpoints.crypto (no external libs).0x01 for non-last, 0x02 for last)baseNonce XOR SEQ per recordcrypto (JWK-based key objects).VAPID.GenerateKeys()).VAPID.Validate.*).generateRequest() produces { endpoint, init } for fetch(endpoint, init).TTL, Urgency, optional TopicContent-Encoding, Content-Type, Content-LengthAuthorization (VAPID or GCM/FCM key when applicable)Authorization: key=<apiKey> (VAPID not supported on legacy GCM).Authorization: key=<apiKey> if VAPID is disabled and a key is provided.npm install node-webpush
TypeScript is supported out of the box (the package emits .d.ts).
WebPush instanceimport {WebPush} from "node-webpush";
const webpush = new WebPush({
vapid: {
subject: "mailto:admin@example.com",
publicKey: process.env.VAPID_PUBLIC_KEY!,
privateKey: process.env.VAPID_PRIVATE_KEY!,
},
// Optional: used for legacy GCM/FCM key-based auth fallback
gcm: {apiKey: process.env.GCM_API_KEY ?? null},
});
const subscription = {
endpoint: "https://push-service.example/...",
keys: {
p256dh: "<base64url>",
auth: "<base64url>",
},
};
const res = await webpush.notify(subscription, "Hello from WebPush!", {
TTL: 60,
});
console.log("Status:", res.status);
import {VAPID} from "node-webpush";
const keys = VAPID.GenerateKeys();
console.log(keys.publicKey);
console.log(keys.privateKey);
You typically store these as environment variables:
VAPID_PUBLIC_KEYVAPID_PRIVATE_KEYnew WebPush(config)type WebPushConfig = {
vapid: {
publicKey: string;
privateKey: string;
subject: string | URL; // must be https: or mailto:
};
gcm?: { apiKey?: string | null };
};
Constructing WebPush validates:
https: or mailto:)webpush.generateRequest(subscription, payload?, options?)Returns the request parameters to call fetch() yourself.
const {endpoint, init} = webpush.generateRequest(subscription, "payload", {
TTL: 60,
});
const res = await fetch(endpoint, init);
This is useful if you want to:
webpush.notify(subscription, payload?, options?)Sends the request using fetch().
const res = await webpush.notify(subscription, "hello");
default it return the response even if not successful. It can also throw an error if the push service returns a non-2xx response. This can be enabled by:
import {WebPushError} from "./webpush";
try {
const res = await webpush.notify(subscription, "hello", {
throwOnInvalidResponse: true //Add this to the options
});
} catch (error: WebPushError){
console.error(error);
const responseObject = error.response; //<<-- The resulting response object can still be accessed
}
Throws
WebPushErrorwhen the push service returns a non-2xx response.This also contains the response but can be handled in the try-catch logic
type GenerateRequestOptions = {
headers?: Record<string, string>;
TTL?: number; // seconds
urgency?: "very-low" | "low" | "normal" | "high";
topic?: string; // base64url <= 32 chars
contentEncoding?: "aes128gcm" | "aesgcm";
// RFC8188 knobs (primarily for advanced use/testing)
rs?: number; // default 4096, must be >= 18
allowMultipleRecords?: boolean; // default false (Web Push wants single record)
finalRecordPadding?: number; // default 0
// Override authentication behavior:
vapidDetails?: WebPushConfig["vapid"] | null;
gcmAPIKey?: string | null;
};
aes128gcm is recommended for Web Push.allowMultipleRecords at false (default).topic must use URL-safe base64 characters and be <= 32 chars.This library follows typical push-service rules:
https://android.googleapis.com/gcm/send...)Authorization: key=<gcmAPIKey>vapidDetails is present: uses VAPIDAuthorization: key=<gcmAPIKey>If you want to disable VAPID for a call:
await webpush.notify(subscription, "hello", {
vapidDetails: null,
gcmAPIKey: process.env.GCM_API_KEY!,
});
import {WebPush} from "node-webpush";
const webpush = new WebPush({
vapid: {
subject: "https://example.com/contact",
publicKey: process.env.VAPID_PUBLIC_KEY!,
privateKey: process.env.VAPID_PRIVATE_KEY!,
},
});
const {endpoint, init} = webpush.generateRequest(subscription, "ping", {
TTL: 120,
urgency: "high",
});
console.log(init.headers); // inspect headers
const res = await fetch(endpoint, init);
console.log(res.status);
import {WebPush, WebPushError} from "node-webpush";
try {
await webpush.notify(subscription, "hello");
} catch (e) {
if (e instanceof WebPushError) {
console.error("Push service rejected request:", e.response.status);
console.error("Response body:", await e.response.text());
} else {
console.error("Unexpected error:", e);
}
}
fetch (Node 18+ recommended).target: ES2020 works.Apache 2.0 See LICENSE
FAQs
A dependency-free Web Push implementation for Node.js
The npm package node-webpush receives a total of 20 weekly downloads. As such, node-webpush popularity was classified as not popular.
We found that node-webpush demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

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.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.

Security News
TeamPCP is partnering with ransomware group Vect to turn open source supply chain attacks on tools like Trivy and LiteLLM into large-scale ransomware operations.