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

ciphersins

v1.3.2

Published

Static scanner for JWT, timing, RNG, and password-hashing footguns in Node/TS app code.

Downloads

1,254

Readme

CipherSins

core node rules tests ci status

Static analysis for cryptographic misuse in Node/TS app code — broken JWT verification, timing-unsafe compares, weak entropy, and legacy hashing in the paths that guard your users.

Like gitleaks for dangerous crypto call patterns — not secrets buried in strings, but how your app uses crypto libraries: decode-only JWT auth, timing-unsafe compares, Math.random() in auth paths, MD5/SHA1 password storage, and weak bcrypt cost.

Catch jwt.decode() without jwt.verify() before it reaches production — not another regex grep on node_modules.

Status: 1.3.2 — single npm package (ciphersins) with CLI + programmatic API + GitHub Action and 19 rules.


Contents


Why not regex (or npm audit)?

Most crypto vulnerabilities in app code do not look like secrets. They look like ordinary API calls — until an attacker forges a token, guesses an HMAC byte-by-byte, or walks in through a decode-only auth path.

| Approach | Security focus | What it misses | | ------------------------------------------ | ---------------------------------------------------- | ------------------------------------------------------------------------------- | | Secret scanners (gitleaks, trufflehog) | Exposed keys and credentials in the repo | Decode-only JWT auth, weak compare, bad RNG — no string to leak | | npm audit | Known CVEs in dependency versions | Correct library, wrong cryptographic use in your handlers | | Regex on source | Obvious decode( or Math.random string hits | Import aliases, destructured require, inline require('jsonwebtoken').decode | | CipherSins | Cryptographic API misuse with import-aware AST rules | Cross-file call graphs (v1 same-file scope) |

CipherSins sits between dependency scanning and manual security review: it flags how your code uses JWT, compare, RNG, and hash primitives before those mistakes become auth bypasses.

What breaks without it

  1. Integrity skippedjwt.decode() reads payload bytes but never validates signature, issuer, audience, or expiry.
  2. Timing side-channels=== / == on tokens, secrets, or hashes when a crypto/auth import is present (CS-CMP-01).
  3. Predictable entropyMath.random() in auth-named functions or bindings (CS-RNG-01).
  4. Broken password storage — MD5/SHA1 createHash or weak-digest PBKDF2 in password-named code (CS-HASH-01); weak bcrypt cost (CS-HASH-02).
  5. Algorithm confusionverify() without pinning allowed algorithms (CS-JWT-02); accepting or signing with none (CS-JWT-03, critical); disabling expiry checks (CS-JWT-04).

Each rule ships with bad/good fixtures and vitest IDs so crypto regressions are caught in CI, not in incident response.


Why use this

  • Import-aware AST rules — ties decode, verify, and compare calls to their real module bindings (default/namespace/named import, require, inline require).
  • Conservative auth scope (v1) — same-file analysis; any jwt.verify() in the file suppresses decode-only findings.
  • Actionable security output — severity, source snippet (API), line:column, and rule doc with fix guidance; CLI prints relative paths and message (snippet via ciphersins API).
  • Purpose-built rule set — JWT, timing, RNG, and hash categories instead of generic lint noise.
  • Fixture-proven — every rule has fixtures/<rule-id>/{bad,good}/ and numbered tests so cryptographic edge cases stay covered.

Architecture

Your application source is resolved by glob, parsed into a TypeScript AST, and checked by registered rules that encode known cryptographic anti-patterns — not generic syntax warnings.

End-to-end scan pipeline

Design constraints: AST + binding analysis (no regex-only detection); each finding carries severity and a link to remediation docs; cross-file taint tracking is out of scope for v1.

Rule example (CS-JWT-01)

CS-JWT-01 detection flow

Diagram sources: docs/img/ (Mermaid .mmd + committed SVG). Regenerate with pnpm diagrams:build.

Package layout:

| Export | Role | | ------------------ | ------------------------------------------------ | | ciphersins (npm) | CLI binary + import { scan } from "ciphersins" |


Rules at a glance

MVP coverage targets the most common crypto footguns in Node auth and data-protection code:

| ID | Severity | Title | Status | | ---------------------------------------- | -------- | ---------------------------- | ----------- | | CS-JWT-01 | high | JWT decode without verify | implemented | | CS-JWT-02 | high | Verify without algorithms | implemented | | CS-JWT-03 | critical | Algorithm none / bypass | implemented | | CS-JWT-04 | medium | Missing exp validation | implemented | | CS-JWT-05 | medium | JWT sign without expiry | implemented | | CS-JWT-06 | medium | JWT sign with noTimestamp | implemented | | CS-CMP-01 | high | Timing-unsafe compare | implemented | | CS-RNG-01 | high | Math.random in auth context | implemented | | CS-RNG-02 | high | randomBytes length too small | implemented | | CS-HASH-01 | high | MD5/SHA1 for password | implemented | | CS-HASH-02 | medium | Weak bcrypt cost | implemented | | CS-HASH-03 | medium | PBKDF2 iterations too low | implemented | | CS-HASH-04 | medium | scrypt parameters too low | implemented | | CS-HASH-05 | medium | argon2 parameters too low | implemented | | CS-ENC-01 | medium | Hardcoded cipher key or IV | implemented | | CS-ENC-02 | high | AES-GCM static or reused IV | implemented | | CS-ENC-03 | high | Weak cipher algorithm | implemented | | CS-ENC-04 | high | ECB mode cipher | implemented | | CS-DEC-01 | medium | Deprecated createDecipher | implemented |

Full index: docs/rules/README.md.


Install

npm (recommended)

npm install -g ciphersins
# or one-off:
npx ciphersins scan ./src

Library API: npm install ciphersins

Requirements: Node.js 20+

GitHub Action (CI)

- uses: 01laky/CipherSins/.github/actions/[email protected]
  with:
    path: ./src
    fail-on: high
    format: sarif
    upload-sarif: true

Full reference: docs/github-action.md

From source (contributors)

git clone https://github.com/01laky/CipherSins.git
cd ciphersins
pnpm install
./scripts/setup-githooks.sh
pnpm verify

Requires pnpm 9.15.9 (or npm install after clone).

Publish workflow for maintainers: docs/releasing.md.


First success in 30 seconds

After pnpm verify, scan intentionally insecure JWT handling in the bad fixtures:

pnpm exec ciphersins scan fixtures/cs-jwt-01/bad
fixtures/cs-jwt-01/bad/default-import-decode-only.ts:4:9  CS-JWT-01  high
  jwt.decode() used without jwt.verify() in the same function scope.
  https://github.com/01laky/CipherSins/blob/main/docs/rules/CS-JWT-01.md

The good fixtures show the same APIs used with proper verification — expect No findings.:

pnpm exec ciphersins scan fixtures/cs-jwt-01/good

Quickstart

Point the scanner at your auth, API, or middleware layer — anywhere tokens and digests are handled:

# From repo root after pnpm install + build
pnpm exec ciphersins scan ./src

# Or scan a specific path
pnpm exec ciphersins scan path/to/your/app

Default scan root when no path is passed: ./src if it exists, otherwise ..

Include globs: **/*.{ts,tsx,js,jsx} (and uppercase variants).
Exclude: node_modules, dist, *.test.*, *.spec.*.


Documentation

| Doc | Description | | ------------------------------------------------------- | ------------------------------------------ | | About | Product positioning, tagline, what we find | | Scope | Non-goals, rule philosophy, test tiers | | Archived proposal | Original v1.0 implementation spec | | Rules index | Per-rule docs and implementation status | | CS-JWT-01 | JWT integrity — decode without verify | | CS-JWT-02 | JWT verify without algorithms allowlist | | CS-JWT-03 | JWT none algorithm bypass (critical) | | CS-JWT-04 | JWT verify with ignoreExpiration: true | | CS-CMP-01 | Timing-unsafe compare on auth material | | CS-RNG-01 | Math.random in auth context | | CS-HASH-01 | MD5/SHA1 password hashing | | CS-HASH-02 | Weak bcrypt cost | | Comparison | vs gitleaks, npm audit, Semgrep, ESLint | | Architecture | Scan pipeline and rule detection diagrams | | CLI reference | Commands, output format, exit codes | | Architecture diagrams | Mermaid sources and SVG regeneration | | FAQ | Common questions | | Development | Contributor setup, adding rules | | Config example | Config schema and example | | Releasing | npm publish checklist for maintainers | | Contributing | Commit standards, git hooks |


How this compares

| | CipherSins | gitleaks / trufflehog | npm audit | Semgrep / ESLint | | --------------------- | -------------------------------- | --------------------- | --------------- | ----------------------- | | Target | Cryptographic misuse in app code | Secrets in repo | Dependency CVEs | General patterns / lint | | Example hit | jwt.decode() without verify | AWS key in .env | lodash CVE | Custom rule dependent | | TS import context | Yes (AST + bindings) | N/A | N/A | Varies | | npm package | Published (v1.3.2) | Published | Built-in | Published |

Full matrix: docs/comparison.md.


Examples

Scan JWT bad fixtures (should report findings)

pnpm exec ciphersins scan fixtures/cs-jwt-01/bad

Covers decode-only auth paths: default/named/namespace import, require, destructured require, inline require, TSX, type annotations, local wrappers.

Scan JWT good fixtures (should be clean)

pnpm exec ciphersins scan fixtures/cs-jwt-01/good

Covers verified tokens: decode+verify in same function, verify in nested/dead code, verify-only, local decode() not from jsonwebtoken, decode only in strings/comments. Flags decode in helper functions even when verify exists elsewhere in the file.

Programmatic scan (core API)

import { scan } from "ciphersins";

const result = await scan({ paths: ["./src"], cwd: process.cwd() });
console.log(result.findings, result.summary);

Use in custom CI steps when you need structured findings before gating a deploy on crypto rule severity.


Non-goals

  • Not a secret scanner — does not hunt API keys, private keys, or passwords in strings.
  • Not npm audit — does not report dependency CVEs or transitive package risk.
  • Not a full SAST suite — focused MVP rule set for crypto and auth primitive misuse.
  • No cross-file call graphs in v1 — same-file scope per rule unless noted.
  • Findings do not fail CI by default — use --fail-on high (or config failOn) for gating (docs/cli.md).
  • Inline suppressions// ciphersins-ignore-next-line with optional --allow-critical-ignore for CS-JWT-03 (docs/cli.md).

Development

pnpm install
./scripts/setup-githooks.sh
pnpm verify

| Command | Description | | ---------------------------------- | ------------------------------------------------------------------------------------------- | | pnpm verify | format → typecheck → build → test → CLI smoke | | pnpm test | Vitest — unit, per-rule, integration, CLI, audit, generated exhaustive (7777 at v1.3.2) | | pnpm run generate:tests | Regenerate test/generated/ from scripts/generate-exhaustive-tests.mjs | | pnpm exec ciphersins scan [path] | Run linked CLI | | pnpm diagrams:build | Regenerate SVGs from docs/img/*.mmd | | pnpm format:fix | Apply Prettier (tabs) |

Adding a rule: docs/development.md#adding-a-rule.


Author

Ladislav Kostolny[email protected] · GitHub @01laky


License

MIT — see LICENSE. Copyright (c) 2026 Ladislav Kostolny.