npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@isl-lang/verifier-security

v0.1.1

Published

Security verifier - verify cryptographic invariants like session token entropy

Readme

@isl-lang/verifier-security

Security verifier for detecting timing attacks, insecure password comparisons, token entropy issues, and other security vulnerabilities in TypeScript code.

Installation

pnpm add @isl-lang/verifier-security

Invariants Verified

Constant-Time Password Comparison

Invariant: password comparison is constant-time

The security verifier enforces that password and hash comparisons use constant-time functions to prevent timing attacks.

Usage

Basic Verification

import { runSecurityRules } from '@isl-lang/verifier-security';

const codeMap = new Map([
  ['auth/login.ts', `
    async function login(password: string, storedHash: string) {
      return password === storedHash; // VIOLATION: timing attack!
    }
  `],
]);

const violations = runSecurityRules(codeMap);

console.log(violations);
// [{ ruleId: 'security/constant-time-compare', severity: 'critical', ... }]

Using the Verifier Class

import { SecurityVerifier } from '@isl-lang/verifier-security';

const verifier = new SecurityVerifier({
  config: {
    skipPatterns: ['*.fixture.ts'],
  },
});

const result = verifier.verify(codeMap);
console.log(result.verdict); // 'secure' | 'risky' | 'insecure'
console.log(result.score);   // 0-100

Constant-Time Comparison Rules

security/constant-time-compare

Description: Password and secret comparison must use constant-time functions to prevent timing attacks.

Detects:

  • Direct equality comparisons (===, !==, ==, !=) of password/hash variables
  • Buffer.equals() for hash comparison (NOT constant-time!)
  • String methods like startsWith(), includes(), indexOf() for secrets
  • localeCompare() for password strings

Approved helpers (no violation when using these):

  • crypto.timingSafeEqual() (Node.js)
  • bcrypt.compare() / bcrypt.compareSync()
  • bcryptjs.compare() / bcryptjs.compareSync()
  • argon2.verify()
  • scrypt.verify()
  • safeCompare(), constantTimeCompare(), secureCompare(), timingSafeCompare()

Example violations:

// ❌ VIOLATION: Direct equality comparison
if (inputHash === storedHash) {
  return true;
}

// ❌ VIOLATION: Buffer.equals is NOT constant-time
if (inputBuffer.equals(storedBuffer)) {
  return true;
}

// ❌ VIOLATION: String methods leak timing
if (password.startsWith(prefix)) {
  return true;
}

Correct usage:

// ✅ CORRECT: Using crypto.timingSafeEqual
import { timingSafeEqual } from 'crypto';

const inputBuf = Buffer.from(inputHash);
const storedBuf = Buffer.from(storedHash);

if (inputBuf.length !== storedBuf.length) {
  return false;
}
return timingSafeEqual(inputBuf, storedBuf);

// ✅ CORRECT: Using bcrypt.compare
import bcrypt from 'bcrypt';
const isValid = await bcrypt.compare(password, storedHash);

security/no-early-return-on-hash-mismatch

Description: Do not return early on hash comparison mismatches, as this creates a timing oracle.

Example violations:

// ❌ VIOLATION: Early return creates timing oracle
if (inputHash !== storedHash) return false;
return true;

// ❌ VIOLATION: Ternary with early throw
return hash !== expected ? throw new Error() : true;

Correct usage:

// ✅ CORRECT: Single branch after constant-time comparison
const isValid = timingSafeEqual(inputBuf, storedBuf);
if (!isValid) {
  return false;
}
return true;

Configuration

interface SecurityRuleConfig {
  /** File patterns to skip (e.g., ['*.test.ts', 'fixtures/']) */
  skipPatterns?: string[];
  
  /** Minimum token length in characters (default: 64 for 256-bit) */
  minTokenLength?: number;
  
  /** Minimum entropy bits required (default: 256) */
  minEntropyBits?: number;
}

Verification Result

interface SecurityVerifyResult {
  success: boolean;
  verdict: 'secure' | 'risky' | 'insecure';
  score: number; // 0-100
  staticViolations: SecurityViolation[];
  runtimeChecks: RuntimeTokenCheckResult[];
  coverage: SecurityCoverageInfo;
  timing: SecurityTimingInfo;
}

Why Constant-Time Comparison Matters

Regular string comparison (===) compares characters one by one and returns false as soon as a mismatch is found. This means:

  • If passwords differ at character 1, comparison returns faster
  • If passwords differ at character 10, comparison takes longer
  • Attackers can measure timing differences to guess passwords character by character

This is called a timing attack. Constant-time comparison functions always take the same amount of time regardless of where characters differ, preventing this attack vector.

References

License

MIT