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

@hafizhpratama/stryx

v0.6.0

Published

Stack-aware security scanner for JavaScript and TypeScript backends.

Readme

@hafizhpratama/stryx

Stack-aware security for JavaScript and TypeScript backends.

A stack-aware security scanner for JavaScript and TypeScript backends. Stryx detects runtime, framework, database, validation, auth, and LLM SDK surfaces, then catches missing input validation, leaked secrets, weak auth, SQL injection, command injection, SSRF, open redirects, path traversal, and unsafe LLM prompt handling using cross-file taint analysis that single-file linters can't match.

License npm

Install

npm install -g @hafizhpratama/stryx
# or one-off
npx @hafizhpratama/stryx scan

The package ships prebuilt native binaries for macOS (x64 / arm64), Linux (x64 / arm64-gnu), and Windows (x64-msvc). npm picks the right platform binary at install time via optionalDependencies — total download is ~1.5 MB per user.

Quick start

cd your-typescript-project
npx @hafizhpratama/stryx scan

Output:

critical flow/sql-injection  app/api/search/route.ts:14:22
         Untrusted request input reaches a raw-SQL call as the query
         string without parameterisation (OWASP A03 / CWE-89).
         help: Switch to `prisma.$queryRaw`...`` (tagged template),
               which binds values instead of splicing.

1 finding(s): 1 critical, 0 high, 0 medium, 0 low, 0 info

Exit code is non-zero when any finding meets or exceeds the --fail-on threshold (default: high). Drop it into CI to gate deploys.

Flags

| Flag | Default | Description | |---|---|---| | --format | human | Output format: human or json | | --fail-on | high | Minimum severity for non-zero exit: info / low / medium / high / critical | | --version | — | Show version | | --help | — | Show help |

npx @hafizhpratama/stryx scan ./src --format=json
npx @hafizhpratama/stryx scan . --fail-on=medium

What it catches

47 rules in the registry. Highlights below — see the full rule library for the complete set across flow/, auth/, crypto/, express/, and generic/ categories:

| Rule | Severity | Catches | |---|---|---| | flow/sql-injection | Critical | Body taint → $queryRawUnsafe / sql.raw / db.sequelize.query / raw query (with first-arg SQL-shape gate) | | flow/command-injection-via-exec | Critical | Body taint → child_process exec/spawn — distinct severity for shell-parsed vs argv-form sinks | | flow/eval-injection | Critical | Body taint → eval / Function / setTimeout-with-string + dynamic require(...) / await import(...) | | flow/insecure-deserialize | Critical | Body taint → unserialize / yaml.load / vm.runInX + prototype-pollution shapes (Object.assign(target, src) / lodash merge / jQuery extend) | | auth/jwt-hardcoded-secret | Critical | Literal secret passed to jwt.sign / jwt.verify (jsonwebtoken) or expressJwt({ secret }) (express-jwt) | | auth/session-hardcoded-secret | Critical | Literal secret passed to session({ secret }) (express-session) or cookieSession({ secret }) (cookie-session) | | flow/ssrf-via-fetch | High/Medium | Body taint → fetch / axios / got / needle / request / http(s).X | | flow/nosql-injection | High | Body-shaped object → MongoDB collection.find/update/delete (DI-service receivers like this.articleService.findOne rejected) | | flow/redirect-open | High | Body taint → NextResponse.redirect etc. (same-origin path literals + explicit safety wrappers recognised) | | flow/unvalidated-body-to-db | High | Body → Prisma/Drizzle/TypeORM/Mongoose/NestJS injected service without zod/valibot/yup | | flow/auth-bypass-via-wrapper | High | withAuth(...) wrapper that doesn't actually check | | flow/secret-to-response | High | process.env.X reaching response body | | flow/path-traversal | High | Body taint → fs.<method> path | | flow/prompt-injection | High | Body taint → LLM prompt content (OpenAI / Anthropic) | | flow/xss-via-dangerously-set-inner-html | High | Body taint → React dangerouslySetInnerHTML | | generic/hardcoded-secret | Critical/High | Provider-prefix tokens (AWS / Anthropic / Stripe / GitHub / OpenAI) + credential-named bindings with Shannon-entropy + identifier-shape gating; test / i18n / translations / locales paths skipped |

Eleven rules trace flows across files — a route handler in app/api/.../route.ts that hands data to a helper in lib/<x>.ts which then sinks to a DB / fetch / exec call is caught at the route's call site, even though no single file shows the full path. The three new v0.4.0 categories (eval / NoSQL / deserialize) gained cross-file flow in v0.5.0.

See the full rule library on GitHub.

Each rule page is also a fix guide: it explains the concrete safe pattern and what Stryx recognizes as fixed.

How it works

JavaScript / TypeScript source + package.json + lockfiles + configs
    ↓
Project profile: detect runtime / framework / data layer /
                 validator / auth / LLM SDK / deployment from
                 package metadata (no source parsing)
    ↓
Layer 1: oxc parser → arena AST (per file, parallel)
    ↓
Layer 2: project semantic index + 22 stack adapters + AST rules
         + taint engine (adapters consume the profile; rules consult
         the active adapter set during taint propagation)
    ↓
Layer 3 (optional): LLM escalation on flagged uncertain zones, cached
    ↓
Findings (JSON or human text), prepended by a compact stack block:
    stack: language: typescript • runtime: bun • framework: hono • ...

Most findings come from deterministic Rust analysis in milliseconds. Genuinely ambiguous zones (a custom helper whose intent the engine can't decide statically) escalate to an LLM check — bring your own API key, or omit and stay fully local.

Architecture deep-dive →

Suppress false positives

Inline:

// stryx-disable-next-line flow/sql-injection -- signed webhook

File-level:

// stryx-disable flow/sql-injection

Found a false positive? Open an issue with the real code that triggered it.

Performance

  • ≤ 10 ms per 500-line TS file (p99)
  • ≤ 30 s for a 10k-file repo with no LLM
  • Sub-1 ms per rule per file

Status

v0.6.0 — source-origin classification + 31 new rules across 6 batches (16 → 47 registered). Closes every category where Semgrep OSS measurably wins for JS/TS BE security per the gap analysis: JWT algorithm/verification flaws, CORS misconfiguration, prototype-pollution loop, vm2 sandbox, cookie security attributes, ReDoS, crypto correctness (GCM tag length, AEAD final, pseudo-random bytes, argon2 config, buffer noAssert), server-template XSS (Pug / EJS / Mustache / Handlebars / response-write / res.render), XXE / XML-parsing (xml2json / libxmljs / sax / expat), Express middleware config (csurf presence + ordering, directory listing, X-Frame-Options, res.sendFile path-traversal), and JWT payload-data exposure / non-revocation / passport / HMAC hardcoded-secret. ADR 0015 Phase 1 source-origin classifier ships in stryx_taint::origin; 22 rules opt into a per-rule accepts_origin policy. Cross-file ConfigDerived (Phase 3) deferred to v0.7.0 — it's what would close the remaining 64 redirect-open findings in better-auth's OAuth provider files structurally. An official GitHub Action with sticky PR comments + annotations, plus a stryx install subcommand that writes per-agent backend-security rule files for Claude Code, Cursor, Codex, OpenCode, and the AGENTS.md convention. APIs follow SemVer. See the changelog for release-by-release detail, the calibration record for per-target dogfood verification, and the roadmap for what's next.

Links