didrod205/jwtlens

GitHub: didrod205/jwtlens

jwtlens 是一个完全离线的 JWT 解码、安全审计与本地签名验证工具,解决开发者将敏感 token 粘贴到在线工具所带来的泄露风险。

Stars: 1 | Forks: 0

# 🔍 jwtlens ### 解码、审计并验证 JWT —— 完全离线。停止将有效的 token 粘贴到 jwt.io。 [![npm version](https://img.shields.io/npm/v/jwtlens.svg?color=success)](https://www.npmjs.com/package/jwtlens) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/06/7e008b8423010930.svg)](https://github.com/didrod205/jwtlens/actions/workflows/ci.yml) [![types](https://img.shields.io/npm/types/jwtlens.svg)](https://www.npmjs.com/package/jwtlens) [![license](https://img.shields.io/npm/l/jwtlens.svg)](./LICENSE) **[🌐 试用浏览器 playground →](https://didrod205.github.io/jwtlens/)**  ·  粘贴一个 JWT,查看其解码、审计和验证的结果。不会上传任何内容——所有操作均在客户端执行。
API 拒绝了你的请求,于是你从日志中提取出 JWT,并——为了读取它的 claims——将其粘贴到 **jwt.io**。该 token 是一个**生产环境凭证**,而你 刚刚把它发送给了第三方网站。然后你手动查看了 `exp`/`aud`/`alg`,而 要实际检查签名,你还需要在某处*加载*密钥。 **jwtlens 完全在你的机器上解码、安全审计并*验证* JWT。** 无需网站,无需 API 密钥,无需网络。解码 + lint 是纯函数;签名验证通过 `node:crypto` 在本地运行,使用**你自己的 secret、PEM 或 JWK**。 ``` echo "$TOKEN" | npx jwtlens scan --key public.pem ``` ``` Header alg "RS256" typ "JWT" kid "k1" Payload iss "https://auth.example.com" sub "user-4012" exp 1893456900 (in 15m) iat 1893456000 (in 0s) Status active Signature ✓ verified (RS256) — signature matches the supplied key Score 100/100 (A) ``` ## 为什么选择 jwtlens? - 🔒 **设计上完全离线。** 你的 token(以及签名密钥)永远不会离开你的 机器——这正是不要在生产凭证上使用 jwt.io 的全部理由。 - ✅ **它不仅解码,还会验证。** 针对真实环境的 `node:crypto` 签名检查支持 **HS256/384/512, RS*, PS*, ES256/384/512 和 EdDSA** —— 包括会让简单 的验证器出错的 ECDSA raw (P1363) 签名格式。 - 🛡️ **它会审计安全状况。** `alg: none`、带有已签名 header 但无签名的 情况、缺失/过长的 `exp`、未来的 `iat` 日期、缺失 `aud`/`iss`/`sub`/ `jti`,以及 HS↔RS **alg-confusion** 陷阱——每一项都会附带修复建议。 - 🤖 **确定性强且对 CI 友好。** 相同的 token → 相同的结果。在 CI 中为你的 issuer 设置门控:如果它发出过 `alg: none` 或永久有效的 token,则让构建失败。 为什么不问问 LLM?base64url、claim 的时间和**签名数学**都是精确的—— 聊天机器人无法(也不应该)持有你的 secret 来验证签名,而且你需要对 CI 中的 每一个 token 都执行此操作,而不是仅仅一次。 ## 安装 ``` # 立即运行 echo "$TOKEN" | npx jwtlens scan # 或添加它 npm install -g jwtlens # global CLI npm install -D jwtlens # CI / library ``` Node ≥ 18。解码 + lint 无需额外依赖且对浏览器安全;验证使用 `node:crypto`。 ## 快速开始 ``` jwtlens scan "$TOKEN" # decode + security lint echo "$TOKEN" | jwtlens scan # from stdin (Bearer prefix ok) jwtlens scan token.txt --key public.pem # + verify RS/ES/EdDSA jwtlens scan "$TOKEN" --secret "$HS_SECRET" # + verify HS* jwtlens verify token.txt --jwk jwks.json # just verify (exit 0/1) jwtlens scan "$TOKEN" --now 2030-01-01 # evaluate timing at a fixed date jwtlens scan "$TOKEN" --min-score 80 --md report.md # CI gate + report ``` 参见 [`examples/sample-report.md`](./examples/sample-report.md) 以及附带的 `examples/*.jwt.txt`(一个强 RS256 token、一个弱 HS256 token 和一个 `alg: none` token)。 ## 检查内容 | 组别 | 示例 | | ----- | -------- | | **签名与算法** | `alg: none` (错误),带有空签名的已签名 header,未知的 alg,对称 alg (alg-confusion) 警告 | | **过期与时间** | 缺失 `exp` (永不过期),生命周期过长,未来的 `iat` | | **Claims** | 缺失 `aud` / `iss` / `sub` / `jti` | | **Token 状态** | 已过期,尚未生效 (`nbf`),带有可读的 "3h ago" / "in 15m" | | **验证** | 使用 `--secret` / `--key` (PEM) / `--jwk` (JWK 或 JWKS,通过 `kid`) 进行本地签名检查 | 检查结果会汇总为 0–100 的分数以及 A–F 的评级,你可以在 CI 中将其用作门控。 ## 实际场景 **1. 安全地检查生产 token。** 从日志中提取它,通过管道传入,读取它的 claims 和时间——而无需将凭证交给网站。 ``` kubectl logs api | grep -o 'eyJ[^ ]*' | head -1 | jwtlens scan ``` **2. 在本地验证 token 的签名。** 使用公共 JWKS 离线确认 token 确实 来自你的 issuer: ``` jwtlens verify "$TOKEN" --jwk jwks.json && echo "authentic" ``` **3. 在 CI 中为你的 issuer 设置门控。** 断言你的身份验证服务生成的 token 是 格式良好的(已签名、生命周期短、已限定范围): ``` your-cli mint-test-token | npx jwtlens scan --min-score 85 ``` ## 配置 `jwtlens init` 会生成 `jwtlens.config.json`: ``` { "ignore": [], // rule ids to skip, e.g. ["no-jti"] "maxLifetimeSeconds": 86400, // warn above this token lifetime "clockSkewSeconds": 60, // tolerance for iat/nbf "in the future" "minScore": 0 // CI gate threshold } ``` ## 库 API ``` import { analyzeToken, verifyJwt, decodeJwt, DEFAULT_CONFIG } from "jwtlens"; const now = Math.floor(Date.now() / 1000); const { decoded, findings } = analyzeToken(token, DEFAULT_CONFIG, now); const result = verifyJwt(decoded, { secret: process.env.HS_SECRET }); console.log(result.valid, findings.map((f) => f.rule)); ``` `decodeJwt` 和 `lintJwt` 是纯函数(对浏览器安全);`verifyJwt` 使用 `node:crypto`。 ## 路线图 - 🤖 **可选的 `--ai` 层(自带 API key)** 用于结合上下文解释 token 的 claims。 核心功能保持 100% 离线且具有确定性。 - 从 `iss`/`.well-known` URL 获取 JWKS(需明确开启;默认关闭)。 - `x5c`/`x5t` 证书链感知以及密钥类型/alg 不匹配检查。 - 加密的 JWE 结构检查(仅限 header)。 - ✅ **一个浏览器 playground**,完全在客户端运行解码 + lint + 验证—— [在这里体验](https://didrod205.github.io/jwtlens/)(不上传任何内容)。 ## 💖 赞助 jwtlens 是免费且基于 MIT 协议的,利用业余时间构建和维护。如果它成功帮助你 避免了将有效的 token 发送给第三方网站,请考虑支持它: - ⭐ **为本仓库点 Star** —— 帮助他人发现它的最简单的免费方式。 - 🍋 **[通过 Lemon Squeezy 赞助](https://elab-studio.lemonsqueezy.com/checkout/buy/5d059b89-51d0-456b-b33a-ed56994f7010)** —— 一次性或周期性赞助。 ## 许可证 [MIT](./LICENSE) © jwtlens 贡献者
标签:GNU通用公共许可证, JWT, MITM代理, Node.js, SOC Prime, 开发工具, 暗色界面, 服务器监控, 离线验证, 自动化攻击