Coder Social home page Coder Social logo

wkovacs64 / hibp Goto Github PK

View Code? Open in Web Editor NEW
112.0 5.0 6.0 16.81 MB

An unofficial TypeScript SDK for the 'Have I been pwned?' service.

Home Page: https://wkovacs64.github.io/hibp

License: MIT License

JavaScript 5.55% HTML 1.75% TypeScript 92.69%
hibp haveibeenpwned pwned security hack dump breach pastes passwords javascript

hibp's Introduction

logo

hibp

An unofficial TypeScript SDK for Troy Hunt's Have I been pwned? service.

npm Version Build Status Code Coverage All Contributors

Installation

In Node.js:

npm install hibp

In Deno:

// Replace x.y.z with the desired hibp version
import * as hibp from 'npm:[email protected]';

See the browser section below for information on how to use it in the browser.

Features (๐Ÿ”‘ = requires an API key)

  • Get a single breach event
  • Get all breaches for an account ๐Ÿ”‘
  • Get all breach events in the system
  • Get all data classes
  • Get all pastes for an account ๐Ÿ”‘
  • Securely check a password to see if it has been exposed in a data breach
  • Check a SHA-1 or NTLM prefix to see if it has been exposed in a data breach
  • Search for an account in both breaches and pastes at the same time ๐Ÿ”‘
  • Get your subscription status ๐Ÿ”‘
  • All queries return a Promise
  • Available server-side (Node.js) and client-side (browser)
  • Written in TypeScript, so all modules come fully typed

Usage

ECMAScript module syntax:
// import individual modules as needed
import { dataClasses, search } from 'hibp';
// or, import all modules into a local namespace
import * as hibp from 'hibp';
CommonJS module syntax:
// require individual modules as needed
const { dataClasses, search } = require('hibp');
// or, require all modules into a local namespace
const hibp = require('hibp');

The following modules are available:

Please see the API reference for more detailed usage information and examples.

Quick-Start Example

import { search } from 'hibp';

async function main() {
  try {
    const data = await search('someAccountOrEmail', { apiKey: 'my-api-key' });
    if (data.breaches || data.pastes) {
      // Bummer...
      console.log(data);
    } else {
      // Phew! We're clear.
      console.log('Good news โ€” no pwnage found!');
    }
  } catch (err) {
    // Something went wrong.
    console.log(err.message);
  }
}

main();

Rate Limiting

The haveibeenpwned.com API rate limits requests to prevent abuse. In the event you get rate limited, the module will throw a custom RateLimitError which will include a retryAfterSeconds property so you know when you can try the call again (as a number, unless the remote API did not provide one, in which case it will be undefined - but that should never happen).

Using in the browser

You have several options for using this library in a browser environment:

  1. Bundled

    The most efficient and recommended method is to bundle it with client-side code using a module bundler like webpack or, more likely, whatever your framework of choice uses under the hood.

  2. UMD

    There is also a Universal Module Definition (UMD) build provided for usage in the browser. When using this build, an hibp object will be added to the browser's window object.

    The recommended way to include the UMD build (when using a <script> tag) is to use the unpkg CDN, specifying the exact version you want. If you don't specify a version, the latest tag will be used, which could be dangerous if/when there are breaking changes made to the API. See unpkg for details and advanced version specification, but generally you will want to do the following (replacing x.y.z with the version you want):

    <script src="https://unpkg.com/[email protected]"></script>
  3. ESM for Browsers

    Modern browsers now support importing ECMAScript modules via <script type="module"> tags. Like the UMD option above, this build is also available the unpkg CDN (and the same versioning rules apply), but you must specify the full path (including the file extension). For example:

    <script type="module">
      // Replace x.y.z with the desired hibp version      โ†“ โ†“ โ†“
      import { dataClasses } from 'https://unpkg.com/[email protected]/dist/browser/hibp.module.js';
    
      const logDataClasses = async () => {
        console.table(await dataClasses());
      };
    
      logDataClasses();
    </script>

    For more information on ESM in the browser, check out Using JS modules in the browser.

Try It Out

Test hibp in your browser with RunKit.

Projects Using hibp

Send me a PR or an email and I'll add yours to the list!

License

This module is distributed under the MIT License.

Contributors โœจ

Thanks goes to these wonderful people (emoji key):

Justin Hall
Justin Hall

๐Ÿ’ป ๐Ÿ“– ๐Ÿš‡ ๐Ÿšง ๐Ÿ‘€ โš ๏ธ
Troy Hunt
Troy Hunt

๐Ÿ”ฃ
Jelle Kralt
Jelle Kralt

๐Ÿ’ป
Anton W
Anton W

๐Ÿ›
Daniel Adams
Daniel Adams

๐Ÿ’ป
Markus Dolic
Markus Dolic

๐Ÿ›
Jonathan Sharpe
Jonathan Sharpe

๐Ÿ’ป
Ryan
Ryan

๐Ÿ›
Stuart McGregor
Stuart McGregor

๐Ÿ›

This project follows the all-contributors specification. Contributions of any kind welcome!

hibp's People

Contributors

allcontributors[bot] avatar danieladams456 avatar dependabot[bot] avatar github-actions[bot] avatar jellekralt avatar renovate-bot avatar renovate[bot] avatar textbook avatar wkovacs64 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

hibp's Issues

TypeError: Cannot read properties of undefined (reading 'startsWith')

Since v14.1.0 we have started seeing an error occurring at

process.versions.node.startsWith('18.')
.

Debugging through I can see that process is actually defined when this code executes. I think perhaps this could be a Next.js thing but I am not totally sure. We call hibp from the browser I should add.

I wonder if using typeof window === 'undefined' rather than typeof process !== 'undefined' might be an approach which would have the same effect but not impact on Next.js users.

Thanks.

Is there timeout on fetch?

I couldn't find anything in sources so I assume there's no timeout on doing fetch on HIBP API?
It would be nice to have an option to define it in config, as well as some default timeout.

Error - "You may need an appropriate loader to handle this file type"

Not sure if this in an appropriate place to report this issue, but, I am coming back to a Vue2 + Vuetify project, which I haven't touched in about six months.

On running npm run serve, I am met with this message;

ERROR  Failed to compile with 1 error

error  in ./node_modules/hibp/dist/esm/api/haveibeenpwned/fetchFromApi.mjs

Module parse failed: Unexpected token (18:19)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
|    * should never happen.
|    */
>   retryAfterSeconds;
| 
|   constructor(retryAfter, message, options) {
...

The only method that I am importing from your library is

import { pwnedPassword } from 'hibp';

and if I remove this import, I no longer receive the error

Again, I am not sure exactly where, or why, this error is occurring, but as I say I have changed nothing in my project for the past 6 months

EDIT: This occurs when using hibp v11.1.0, using v11.0.0 I do not get any errors and all works fine

Request blocked or forbidden

haveibeenpwned.com recently (mid-January, 2019) adjusted their API abuse prevention policies and now many API consumers are being blocked. The primary target appears to be the User-Agent string in the API request, but there is more to the story as multiple users with the same UA can receive different results for the same request (e.g. one blocked, one succeeds). IP address and/or region may also be playing a part. It also seems the rules are most strict surrounding the breachedaccount endpoint.

The requirements in the haveibeenpwned API documentation state that a User-Agent must be included in all API requests to avoid being blocked. hibp does this this outside of the browser (i.e. Node.js), but it is not currently possible for hibp to set its own User-Agent when running in the browser because haveibeenpwned.com does not include it in the Access-Control-Allow-Headers header field of a preflight response. (Try it out on test-cors.org and you will see it fail. See MDN's CORS page for more details.) Furthermore, some browsers (e.g. Chrome) will even block requests client-side that attempt to modify the UA as they consider it unsafe, so the problem would still exist for some users even if the CORS rules were adjusted to allow it.

Currently, it seems like most/all browser UA strings are being blocked outright. The test link in the API documentation fails on every browser I've tested from various devices, locations, and networks. I don't know if this is intentional and browser support needs to be dropped from hibp or if the abuse prevention rules are too strict and need adjusted. Edit (2019-01-25): Confirmed with Troy that this is intentional.


In versions of hibp prior to 7.4.0, the error would appear as such:

Error: Forbidden - no user agent has been specified in the request.

This is because the haveibeenpwned.com API documentation states a 403 Forbidden response would occur in the case of a missing User-Agent header field in the request. However, this is not the only case where they respond with 403 Forbidden now, so that error message is no longer accurate.

hibp version 7.4.0 includes a more specific error message, indicating if you are being blocked by haveibeenpwned.com when a Cloudflare Ray ID is present in the response header:

Error: Request blocked, contact haveibeenpwned.com if this continues (Ray ID: xxxxxxxx-xyz)

If no Cloudflare Ray ID is present, you will get a more generalized error:

Error: Forbidden - access denied.

Related issues:

#38
wKovacs64/pwned#27
wKovacs64/pwned#30

Not finding realy simple passwords

Hello

I am trying to check really simple passwords - and no matches found. May be I am doing something wrong?

const hibp = require('hibp');
const sha1 = require('sha1');
const shad = sha1('123456'); // the most simple password

const firstFive = shad.substr(0, 5);
const rest = shad.substr(5);
hibp
    .pwnedPasswordRange(firstFive)
    .then(data => {

        data.forEach(i => {

            if (i.suffix === rest) {
                console.log('FOUND');
            }
        });

    });

Remove source-map-support (and index.js)

There's really no need for this to be included in the project. We will still generate the appropriate source maps during the build process and any future debugging can install/register source-map-support prior to reproducing the error.

In addition to the good feeling ๐Ÿ˜ธ of removing a project dependency, it also reduces the size of the Node-targeting builds (CommonJS in lib and ES modules in es) substantially when included via a bundler. This is arguably a prerequisite to removing the browser field in package.json, another imminent goal.

Target browsers in Babel config for CJS/ESM builds

"browsers": [
  "> 1%",
  "last 2 versions"
],

This will be required if #8 is implemented, as the current CommonJS/ES module builds contain features that don't work across all the browsers this project aims to support (template literals, in particular).

It should really be added regardless, as people may even be wanting to circumvent the browser field already and explicitly import a non-UMD build on their own. Currently, when attempting to bundle a non-UMD build with webpack, the included UglifyJsPlugin will error during minification as it can't handle ES2015 features yet. (There are workarounds for this, such as bringing in the next version of UglifyJs or using a different minifier all together.)

Errors in web workers or extension background threads

Looks like all API methods fail when trying to call them from a web worker or extension background threads since window is undefined.

Looking at src/api/web-fetch.ts it looks like it assumes it is running in a NodeJS environment if window is undefined.

Perhaps a more accurate check to see if native fetch is available can be simply 'fetch' in globalThis

Action Required: Fix Renovate Configuration

There is an error with this repository's Renovate configuration that needs to be fixed. As a precaution, Renovate will stop PRs until it is resolved.

Error type: undefined. Note: this is a nested preset so please contact the preset author if you are unable to fix it yourself.

Uncaught ReferenceError: exports is not defined in 4.2.0

Including this file https://unpkg.com/[email protected]/dist/hibp.js in my HTML page gives me this error:

Uncaught ReferenceError: exports is not defined
    at Object.eval (hibp.js:237)
    at eval (hibp.js:238)
    at Object.<anonymous> (hibp.js:133)
    at __webpack_require__ (hibp.js:30)
    at eval (hibp.js:1)
    at Object.<anonymous> (hibp.js:283)
    at __webpack_require__ (hibp.js:30)
    at hibp.js:76
    at hibp.js:79
    at webpackUniversalModuleDefinition (hibp.js:9)

Which is happening in this line

/* harmony default export */ __webpack_exports__["default"] = (hibp);
module.exports = exports['default'];
/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(28)(module)))

With version 4.1.0 it's working fine

Refactor pwnedPasswordRange to resolve with object?

Following on from #24, what if the resolved value from pwnedPasswordRange was a simple object mapping the suffixes to the count (interface PwnedPasswordSuffix { [suffix: string]: number; })? E.g. the current test:

return expect(pwnedPasswordRange('5BAA6')).resolves.toEqual([
{
suffix: '003D68EB55068C33ACE09247EE4C639306B',
count: 3,
},
{
suffix: '1E4C9B93F3F0682250B6CF8331B7EE68FD8',
count: 3303003,
},
{
suffix: '01330C689E5D64F660D6947A93AD634EF8F',
count: 1,
},
]);

becomes:

      return expect(pwnedPasswordRange('5BAA6')).resolves.toEqual({
        '003D68EB55068C33ACE09247EE4C639306B': 3,
        '1E4C9B93F3F0682250B6CF8331B7EE68FD8': 3303003,
        '01330C689E5D64F660D6947A93AD634EF8F': 1,
      });

This would substantially simplify the most common usage, as expressed by the implementation of pwnedPassword, from:

return (
pwnedPasswordRange(prefix, options)
// filter to matching suffix
.then((arr) => arr.filter((item) => item.suffix === suffix))
// return count if match, 0 if not
.then((arr) => (arr[0] ? arr[0].count : 0))
);

to:

  return (
    pwnedPasswordRange(prefix, options)
      .then((arr) => (arr[suffix] || 0))
  );

which is also slightly more efficient than an O(n) scan of the result array.

I'm happy to PR an implementation if this is a direction people are happy with.

LogoType

Can you explain what the LogoType field in the breach data is (or could be) used for? I know what SVG and JPG are, but to what data do they refer? I don't see any reference to it in the source code.

Cannot use hibp modules in React Native development mode

I'm trying to use hibp in a React Native project, but I'm getting this error when importing the module and starting the app in dev mode:

In this environment the sources for assign MUST be an object. This error is a performance optimization and not spec compliant.

    Object.assign @ Object.es6.js:37:14
    <unknown> @ hibp.js:23:14
    loadModuleImplementation @ require.js:292:4
    guardedLoadModule @ require.js:186:11
    metroRequire @ require.js:115:72
    [โ€ฆ]

As far as I can see, this is caused by this RN polyfill, triggered by this line in hibp, which passes false as the second parameter to Object.assign because navigator is an object in this scenario (the navigator global of the browser attached for debugging).

Like the error message says, hibp isn't doing anything wrong here; but I guess this would be fairly simple to prevent, by modifying the Object.assign call to always pass an object?

Remove browser field from package.json

Currently, importing hibp in a project built with webpack will use the UMD build when targeting the web (the default behavior when webpack's target field is unspecified). This is suboptimal for various reasons and it should probably be removed for now (following redux's lead here).

It appears the unpkg CDN checks the unpkg field first when resolving the entry point if unspecified, so we should replace browser with that. Otherwise, users will have to include the dist/hibp.min.js file path in their <script> tags.

Update documentation for API v3

The API documentation (API.md) and types should update as the changes are implemented, but we may also need to update:

  • The README
  • The GitHub Pages site (/docs)
  • The RunKit example (/example)
  • The Migration guide

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Warning

These dependencies are deprecated:

Datasource Name Replacement PR?
npm @babel/plugin-proposal-class-properties Unavailable
npm @babel/plugin-proposal-object-rest-spread Unavailable

This repository currently has no open or pending branches.

Detected dependencies

github-actions
.github/workflows/bundlewatch-pr.yml
  • actions/checkout v4
  • actions/setup-node v4
  • jackyef/bundlewatch-gh-action 0.3.0
.github/workflows/bundlewatch-push.yml
  • actions/checkout v4
  • actions/setup-node v4
  • jackyef/bundlewatch-gh-action 0.3.0
.github/workflows/ci.yml
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/checkout v4
  • actions/setup-node v4
  • codecov/codecov-action v4
  • actions/checkout v4
  • actions/setup-node v4
  • actions/cache v4
  • actions/upload-artifact v4
  • actions/checkout v4
  • actions/setup-node v4
  • changesets/action v1
npm
package.json
  • jssha ^3.3.1
  • undici ^6.14.1
  • @arethetypeswrong/cli 0.15.3
  • @babel/core 7.24.9
  • @babel/parser 7.24.8
  • @babel/plugin-proposal-class-properties 7.18.6
  • @babel/plugin-proposal-object-rest-spread 7.20.7
  • @babel/preset-env 7.24.8
  • @babel/preset-typescript 7.24.7
  • @changesets/changelog-github 0.5.0
  • @changesets/cli 2.27.7
  • @playwright/test 1.45.2
  • @rollup/plugin-babel 6.0.4
  • @rollup/plugin-commonjs 26.0.1
  • @rollup/plugin-json 6.1.0
  • @rollup/plugin-node-resolve 15.2.3
  • @rollup/plugin-replace 5.0.7
  • @rollup/plugin-terser 0.4.4
  • @rollup/plugin-typescript 11.1.6
  • @types/common-tags 1.8.4
  • @types/debug 4.1.12
  • @types/node 20.14.11
  • @types/ws 8.5.11
  • @vitest/coverage-v8 2.0.3
  • @wkovacs64/eslint-config 7.2.5
  • @wkovacs64/prettier-config 4.1.1
  • babel-plugin-annotate-pure-calls 0.4.0
  • bundlewatch 0.3.3
  • common-tags 1.8.2
  • cpy-cli 5.0.0
  • cross-env 7.0.3
  • dts-bundle-generator 9.5.1
  • eslint 8.57.0
  • eslint-plugin-playwright 1.6.2
  • glob 11.0.0
  • jsdoc-babel 0.5.0
  • jsdoc-to-markdown 8.0.1
  • msw 2.3.1
  • npm-run-all2 6.2.2
  • prettier 3.3.3
  • rimraf 6.0.1
  • rollup 4.18.1
  • serve 14.2.3
  • tslib 2.6.3
  • typescript 5.5.3
  • vitest 2.0.3
  • node >= 18.0.0
nvm
.nvmrc
  • node 20

  • Check this box to trigger a request for Renovate to run again on this repository

Forbidden - no user agent has been specified in the request.

Symptom:

hibp requests made outside of a browser (e.g. Node.js) result in the following:

Error: Forbidden - no user agent has been specified in the request.

Synopsis:

As first noticed on 2018-06-26, the remote API seems to have started enforcing a long documented but never enforced rule requiring a User-Agent header be included in all API requests. hibp does not currently include this header (see below for reasons why).

Backstory:

I (original author of this library) had every intention of honoring this requirement, but ran into what I believe is a misconfiguration or partial implementation of CORS on the API side of things which prevented consumers from sending a custom User-Agent request header in the browser. I contacted the API author/maintainer and provided a very detailed analysis of my findings, but the CORS configuration for the API remained the same. As such, hibp does not currently send a User-Agent header in its requests, as I noticed the rule was not being enforced anyway.

Proposed Solution:

hibp can check if it's running outside the browser and include a custom User-Agent header in its requests. In a browser environment, it will continue to allow the browser to include its own User-Agent and thus avoid CORS.

Hudson Rock Cybercrime Intelligence Free Integration

Consider adding Hudson Rock's complimentary data to receive additional intelligence about an email address, or domain that was compromised in global Infostealer attacks.

Email sample: https://cavalier.hudsonrock.com/api/json/v2/osint-tools/[email protected]
Domain sample: https://cavalier.hudsonrock.com/api/json/v2/osint-tools/search-by-domain?domain=tesla.com

Free API key and full documentation is available here: https://cavalier.hudsonrock.com/docs

Thank you.

Refactor pwnedPassword.js to use hash range API

Depending on my availability over the next bit, I would be interested in trying to implement this feature.

Currently the pwnedPassword check uses the v1 api, but it would be nice to use the more secure v2 hash range api. This module could depend upon pwnedPasswordRange.js and provide the higher level API without needing to search through the results.

I was envisioning using this as a type of password strength tester for user signup beyond the basic length/character set, so there could be a case where you were ok with 5 pwns but not 5,000. I would add a maxPwns: number parameter to the options object (convenient it's already there!) to facilitate that behavior. Default maxPwns would be 1, and the method would return a boolean as it does currently.

Remove top-level default export

The mere presence of the default export appears to break webpack tree-shaking. Also, it has been suggested by Dr. Axel Rauschmayer that exporting an object as the "default"-named export is probably an anti-pattern when all you want to do is provide access to its properties.

See the 2016/04/26 update in Tim Oxley's ES Modules post.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.