
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Minimal, single-use one-time password (OTP) verification for Node.js apps.
It generates an OTP, stores a hashed record, emails it to the user, then validates exactly once and deletes it. MongoDB is the default storage; an optional SQLite path exists for small apps and tests. Email delivery uses AWS SES via Nodemailer.
validateStatus(): 'ok' | 'not_found' | 'expired' | 'blocked'npm run db:ensure-ttl)OTP_DB_DRIVER (mongodb or sqlite).createdAt for cleanup.See docs/ARCHITECTURE.md for a deeper dive.
npm install
npm run build
OTP_MONGO_CONNECTION=mongodb+srv://...
OTP_MONGO_DATABASE=myapp
OTP_MONGO_COLLECTION=otps
OTP_MESSAGE_FROM=noreply@example.com
OTP_MESSAGE_SUBJECT=Your verification code
OTP_URL=https://example.com/verify
OTP_EXPIRY=1800
OTP_LENGTH=6
OTP_DIGITS=true
const { MongoClient, ServerApiVersion } = require('mongodb')
const OneHitter = require('onehitter').default
const client = new MongoClient(process.env.OTP_MONGO_CONNECTION, {
serverApi: { version: ServerApiVersion.v1, strict: true, deprecationErrors: true },
})
await client.connect()
const one = new OneHitter()
const otp = one.make()
await one.create(client, { contact: 'user@example.com', otp, createdAt: new Date() })
await one.send('user@example.com', otp)
const ok = await one.validate(client, { contact: 'user@example.com', otp })
await client.close()
createdAt (see docs/DB.md).validateStatus() (see examples/validate-status.md).make(): string — generate an OTP according to env flags (OTP_LENGTH, OTP_*); values greater than 64 are capped at 64 characterscreate(client, { contact, otp, createdAt }): Promise<InsertOneResult> — MongoDBcreate({ contact, otp, createdAt }): Promise<InsertOneResult> — SQLite (no client)send(to, otp): Promise<void> — emails via SES; template customizablevalidate(...): Promise<boolean> — true only when consumed successfullyvalidateStatus(...): Promise<'ok' | 'not_found' | 'expired' | 'blocked'>Example: validateStatus
const status = await one.validateStatus(client, { contact: 'user@example.com', otp })
if (status === 'ok') {
// proceed
} else if (status === 'expired') {
// ask user to request a new OTP
} else if (status === 'blocked') {
// tell user to slow down
} else {
// not_found — wrong/already used/TTL-removed
}
MongoClient (construct, connect/close, pass to create/validate).OTP_DB_DRIVER=sqlite, optional SQLITE_PATH); good for tests/small apps.OTP_DB_DRIVER (optional): selects the storage driver.
mongodb (default): uses the MongoDB adapter and only requires the mongodb dependency.sqlite: uses the built-in SQLite adapter and requires the host app to install sqlite3 (for example, npm install sqlite3). When OTP_DB_DRIVER=mongodb, sqlite3 is not required and is not loaded.Details and tradeoffs: docs/DB.md
Storage drivers
Email transport
Expiry and cleanup
createdAt (run npm run db:ensure-ttl). Changing OTP_EXPIRY does not automatically change the TTL index—run the helper or recreate the index.Rate limiting
Security model
OTP_PEPPER) in production to protect OTP hashes. Email is not a confidential channel; OTP length/charset should be tuned for your risk profile.Concurrency and multiple OTPs
Time assumptions
Scope
This project is an open-source effort, and all contributions are welcome, big or small. Whether you're fixing a typo, squashing a nasty bug, writing documentation, or proposing a major new feature, your help can have a real impact on this project.
Here are a few ways you can support the OneHitter:
🐛 Reporting Bugs
If you find a bug, please check the existing issues list to see if it has already been reported. If not, open a new issue and include:
Steps to reproduce the bug.
The expected behavior versus the actual behavior.
The environment (OS, Node version, browser, etc.) where the bug occurred.
✨ Feature Requests
Have an idea for how OneHitter could be improved? Open an issue and use the "Feature Request" label. Describe the proposed feature, why it would be useful, and how you imagine it working.
💻 Code Contributions (Pull Requests)
We encourage you to submit Pull Requests (PRs). If you're ready to dive into the code, here's our simple workflow:
Fork the repository and clone it locally.
Create a new branch for your fix or feature:
git checkout -b feature/your-feature-name OR git checkout -b bugfix/issue-number
Make your changes. Please ensure your code follows the existing style, includes appropriate comments, and passes all existing tests.
Write tests for any new features or bug fixes.
Commit your changes with a descriptive commit message.
Push your branch and open a Pull Request against the main branch of this repository.
It's a simple seven step process.
I'm especially looking for ...
TypeScript Refactoring: Improving type safety and clarity across the codebase.
Performance Optimizations: Identifying and improving bottlenecks.
Security Improvements: Making sure the otp are as secure in the db and code as possible.
Databases: Currently OneHitter really only supports MongoDB. An adapter for Postgresql, MySQL/Maria, or any other databases.
Documentation: Adding more examples, tutorials, or clarifying existing docs.
Thank you for helping build great software. I look forward to reviewing your contributions.
If you don't want to write code, you can still help by sending me money via Venmo
FAQs
One-time password user validation package.
We found that onehitter 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.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.