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

@wuipkg/security-review

v0.7.5

Published

面向构建前与 CI 阶段的安全审查工具包,提供 CLI、Vite、webpack 与 ESLint 子入口。旨在从代码规范、静态资源暴露、第三方依赖风险等多维度阻断潜在安全隐患。

Downloads

280

Readme

@wuipkg/security-review

面向构建前与 CI 阶段的安全审查工具包,提供 CLI、Vite、webpack 与 ESLint 子入口。旨在从代码规范、静态资源暴露、第三方依赖风险等多维度阻断潜在安全隐患。

核心特性

  • 多环节覆盖: 支持在 pre-commit (Git 暂存区), build (构建流程), post-build (构建产物检查) 及 ci 环境无缝运行。
  • 全链路适配: 提供 CLI 原生命令执行,同时内置无缝衔接 Vite 和 Webpack 的构建插件。
  • 框架覆盖: 源码扫描同时覆盖原生 JS/TS、Vue SFC 与 React JSX/TSX。
  • 丰富的审查规则: 内置 26 种前沿前端与 Node 服务安全审查规则,涵盖硬编码密钥、敏感凭证泄露、DOM XSS、表单劫持、动态导入、正则安全、构建产物策略检查等。
  • 灵活动态的配置: 支持 wui-security.config.ts 以及基于辅助函数的系统环境变量动态配置,快速适应复杂工程与自动化流水线。
  • 抑制机制: 支持 security-ignore 注释(JS/TS/JSX/TSX 行注释与 Vue 模板 HTML 注释),在人工审核后抑制特定发现。
  • 自定义检测: 通过 detect 回调函数扩展非标准 HTTP 客户端的凭证检测。

安装

pnpm add @wuipkg/security-review -D

规则清单

本工具内置以下 26 条安全审查规则,分为三大类:

源码规则 (Source Rules)

运行在 pre-commitbuildci 阶段,对源代码文件进行 AST 静态分析。

| 规则名 | 默认等级 | 描述 | | ---------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | hardcoded-secret | error | 检测源码中的明文 AccessKey、私钥、口令与内网地址。支持 AWS、GitHub、GitLab、Stripe、OpenAI、Google、npm Token 等 10+ 种密钥格式。 | | dangerous-dom-api | error | 检测 v-html、React dangerouslySetInnerHTMLinnerHTMLouterHTMLdocument.writeevalnew Function()setTimeout/setInterval 字符串参数。 | | postmessage-origin | error | 要求 window.addEventListener('message', ...) 处理器首行校验 event.origin。 | | unsafe-redirect | error | 基于 AST 精确匹配检测直接基于 URL 参数的 location.hreflocation.assign/replace、Vue Router 跳转,以及 React Router 常见导航语义(如 useNavigate() 返回的 navigate(...)<Navigate to={...} />)。支持 safeRedirectFunctions 安全函数白名单和 checkRouteParams 配置。 | | sensitive-storage | error | 检测 localStorage/sessionStorage.setItem 明文存储 token、idCard 等敏感字段。 | | unsafe-url-scheme | error | 拦截 href/src/actionwindow.open 中的 javascript:data:vbscript: 协议。 | | deprecated-crypto | error | 检测前端使用 CryptoJS.MD5/SHA1 等弱密码学算法。 | | postmessage-wildcard | error | 拦截 postMessage 使用通配符 '*' 作为 origin。 | | unsafe-deep-clone | warn | 检测未过滤 __proto__/constructor/prototype 的深拷贝实现。 | | unsafe-target-blank | warn | 检测 target="_blank" 缺失 rel="noopener"(Vue 模板、JSX/TSX、window.open)。 | | unsafe-regex | warn | 基于 AST 分析容易引发 ReDoS 攻击的正则表达式。 | | client-cookie-security | warn | 检测 document.cookie 及 Cookie 库 .set() 缺失 SecureSameSite 属性。 | | console-log-leak | warn | 检测 console.log/warn/error 等输出中包含敏感变量名(如 token、password、secret)的参数。 | | insecure-fetch-credentials | warn | 检测 fetch({ credentials: 'include' })axios.create({ withCredentials: true })xhr.withCredentials = true 等跨域凭证发送。 | | form-action-hijack | warn | 检测表单 action 属性指向外部域(静态 HTML、Vue :action/v-bind:action 绑定、JSX/TSX),并对 Vue / React 的动态绑定表达式给出显式风险提示。 | | iframe-allow-permissions | warn | 检测 iframe allow 是否显式授予摄像头、麦克风、定位等敏感权限,并对无法静态确认的动态绑定给出风险提示。原生 HTML 文件需显式把 .html/.htm 加入 sourceExtensions 后才会参与源码扫描。 | | unsafe-dynamic-import | warn | 检测动态 import() 参数为非字面量的情况,防止 SSR/Electron 场景下任意模块加载。 |

产物规则 (Output Rules)

运行在 post-buildbuildci 阶段,对构建产物和配置文件进行检查。

其中 HTML advisory 规则(csp-policysubresource-integrityreferrer-policy)遵循以下约定:

  • 配置为 .html / .htm 的文件时,只检查 outDirs 下的构建产物,不检查源码模板。
  • build 阶段不会对 HTML advisory 文件做判定,因为构建期动态注入尚未完成;请使用 post-buildci 获取最终结果。
  • 配置为 nginx.conf 之类的非 HTML 文件时,仍然按项目根目录下的配置文件读取。
  • subresource-integrity 可通过 ignoredDomains 跳过指定外部域名,域名按 hostname 精确匹配。

| 规则名 | 默认等级 | 描述 | | ------------------------ | -------- | ---------------------------------------------------------------------------------- | | source-map-leak | error | 检查发布产物目录是否残留 .map 文件或 sourceMappingURL 注释。 | | env-file-exposure | error | 扫描构建产物目录是否包含 .env 文件。 | | git-directory-exposure | error | 检测构建产物目录是否包含 .git 目录,防止源码泄露。 | | csp-policy | warn | 检测入口 HTML 是否存在 Content-Security-Policy 配置。 | | subresource-integrity | warn | 检测外部 script/link 标签是否包含 integrity 属性(SRI)。 | | referrer-policy | warn | 检测是否配置 Referrer-Policy: strict-origin-when-cross-origin。 |

依赖规则 (Dependency Rules)

| 规则名 | 默认等级 | 描述 | | -------------------------- | -------- | ------------------------------------------------------------- | | dependency-audit | error | 执行 npm audit / pnpm audit 检查已知漏洞。 | | lockfile-registry | error | 校验 .npmrc 及 lockfile 中的 npm 源域名是否在可信白名单内。 | | prototype-pollution-deps | error | 检测高风险原型链污染依赖。 |

全局配置 (wui-security.config.ts)

在项目根目录创建 wui-security.config.ts,这里将作为所有工具链检查逻辑的真相来源 (Single Source of Truth):

import { defineSecurityConfig } from '@wuipkg/security-review'

export default defineSecurityConfig({
  // 1. 指定 lockfile 与 .npmrc 允许出现的 npm 源域名
  allowedRegistryDomains: ['registry.npmjs.org', 'npm.company.com'],

  // 2. 指定执行 npm / pnpm audit 时使用的审计源
  audit: {
    registry: 'https://registry.npmjs.org'
  },

  // 3. 检查特定文件中是否忘记配置安全 Meta 标签或 SRI 属性
  //    - HTML 文件会映射到 outDirs 下的构建产物,例如 dist/index.html
  //    - 非 HTML 文件(如 nginx.conf)则直接按项目根目录读取
  advisoryFiles: {
    'csp-policy': ['index.html'],
    'subresource-integrity': ['index.html'],
    'referrer-policy': ['index.html']
  },

  // 4. 构建产物目录(用于 source-map-leak / env-file-exposure / git-directory-exposure
  //    以及 HTML advisory 规则定位最终产物文件)
  outDirs: ['dist', 'build'],

  // 5. 豁免的安全路由/持久化存储函数名单
  safeNavigationFunctions: ['safeNavigate', 'appNavigate', 'router.push'],
  safeStorageFunctions: ['encryptedStorage'],

  // 6. 扫描的目标源代码扩展名及需要过滤忽略的路径
  sourceExtensions: ['.js', '.jsx', '.ts', '.tsx', '.vue'],
  ignore: ['node_modules', '.git', 'dist', '.turbo'],

  // 7. Trufflehog (高价值密钥扫描器) 集成支持
  trufflehog: {
    enabled: false,
    command: 'trufflehog'
  },

  // 8. 导出离线 HTML 分析报告
  htmlReport: {
    enabled: false,
    outputFile: 'security-report.html',
    exposeScannedFiles: false
    // template: './custom-template.html'
  },

  // 9. 自定义各个规则等级与参数配置 (off | warn | error)
  rules: {
    'hardcoded-secret': 'error',
    'dependency-audit': 'error',
    'unsafe-deep-clone': 'warn',
    'sensitive-storage': {
      level: 'error',
      options: { sensitiveKeys: ['token', 'idCard', 'passport'] }
    },
    'source-map-leak': {
      level: 'error',
      options: { outDirs: ['dist'] }
    },
    'subresource-integrity': {
      level: 'warn',
      options: {
        files: ['index.html'],
        ignoredDomains: ['www.googletagmanager.com']
      }
    },
    // 新增规则配置示例
    'console-log-leak': {
      level: 'warn',
      options: {
        sensitiveIdentifiers: [
          'token',
          'password',
          'secret',
          'apiKey',
          'credential'
        ]
      }
    },
    'insecure-fetch-credentials': {
      level: 'warn',
      options: {
        httpClientNames: ['axios', 'http', 'request', 'api', 'service']
      }
    },
    'form-action-hijack': {
      level: 'warn',
      options: {
        allowedDomains: ['payment.company.com']
      }
    },
    'iframe-allow-permissions': {
      level: 'warn',
      options: {
        sensitivePermissions: [
          'camera',
          'microphone',
          'geolocation',
          'payment'
        ]
      }
    },
    'git-directory-exposure': 'error',
    'unsafe-dynamic-import': 'warn',
    'unsafe-redirect': {
      level: 'error',
      options: {
        // 声明项目中的安全校验函数,被这些函数包裹的跳转不会告警
        safeRedirectFunctions: ['validateUrl', 'sanitizeRedirect'],
        // 默认不检查 route.params(受路由表约束),设为 true 启用检查
        checkRouteParams: false
      }
    }
  }
})

自定义检测回调

对于非标准 HTTP 客户端(如公司内部封装的 myHttp 库),可通过 detect 回调函数扩展 insecure-fetch-credentials 规则的检测范围:

import type { CredentialDetectFn } from '@wuipkg/security-review'
import { defineSecurityConfig } from '@wuipkg/security-review'

const detectInsecureCredentials: CredentialDetectFn = (ctx) => {
  // 检测 myHttp.post(url, { sendCookies: true })
  if (
    ctx.callee === 'myHttp' &&
    ctx.property === 'sendCookies' &&
    ctx.value === true
  ) {
    return true
  }
  return false
}

export default defineSecurityConfig({
  rules: {
    'insecure-fetch-credentials': {
      level: 'warn',
      options: {
        detect: detectInsecureCredentials
      }
    }
  }
})

detect 回调的上下文参数 (CredentialDetectContext):

| 字段 | 类型 | 描述 | | ---------- | --------------------------- | ----------------------------------------------------------- | | callee | string | 调用者变量名,如 'myHttp''customFetch' | | method | string \| null | 方法名(成员调用时),如 'post'。直接调用时为 null | | property | string | 配置对象中当前属性名 | | value | boolean \| string \| null | 属性值(仅 BooleanLiteral 或 StringLiteral,其余为 null) |

行内抑制 (security-ignore)

在人工确认安全后,可使用行内注释抑制特定规则的报告。注释需放在目标代码的上一行

JS/TS 文件

// security-ignore insecure-fetch-credentials
axios.create({ withCredentials: true }) // 已确认仅对同源 API 生效

// security-ignore console-log-leak
console.log(token) // 仅开发环境使用,生产构建已配置 drop_console

React / JSX / TSX

const html = '<p>controlled</p>'

// security-ignore dangerous-dom-api 已确认仅受控富文本渲染
export const Preview = () => <div dangerouslySetInnerHTML={{ __html: html }} />

Vue 模板 (<template>)

<!-- security-ignore form-action-hijack -->
<form :action="paymentUrl">
  <input type="text" name="card" />
</form>

行为规则

  • 注释仅抑制紧邻的下一行的匹配发现,不会跨行生效
  • 规则名必须精确匹配,// security-ignore unsafe-regex 不会抑制 console-log-leak
  • 无行号信息的 finding(如 source-map-leak)不可被抑制

报告展示

抑制的发现不会被静默丢弃,而是:

  • 终端报告: 在 summary 下方显示 "已忽略 N 条",并在明细区列出每条被抑制的 finding
  • HTML 报告: 在底部以 "Suppressed Findings" 区块展示,并列出每条被抑制的 finding 与忽略理由
  • API 返回: 通过 report.suppressedFindings 数组获取,report.summary.suppressed 记录条数

环境变量与动态配置

在 Node.js 运行时,wui-security.config.ts 会被动态加载解析。你可以直接通过 process.env 配合辅助函数灵活读取字符串、布尔及数组类型变量。

// wui-security.config.ts
import { defineSecurityConfig } from '@wuipkg/security-review'

/**
 * 辅助函数:将以逗号分隔的字符串转换为去重、无空值的纯净数组
 */
const parseEnvToArray = (
  envValue?: string,
  fallback: string[] = []
): string[] => {
  if (!envValue) return fallback
  return envValue
    .split(',')
    .map((item) => item.trim())
    .filter(Boolean)
}

export default defineSecurityConfig({
  allowedRegistryDomains: parseEnvToArray(
    process.env.SECURITY_ALLOWED_DOMAINS,
    ['registry.npmjs.org']
  ),
  audit: {
    registry: process.env.SECURITY_AUDIT_REGISTRY
  },
  outDirs: parseEnvToArray(process.env.SECURITY_OUT_DIRS, ['dist'])
})

在执行具体构建或 CLI 命令时,你可以通过注入环境变量来覆盖默认值(Node 20+ 环境直接注入 --env-file=.env 会更方便):

SECURITY_ALLOWED_DOMAINS="npm.company.com,registry.npmjs.org" pnpm wui-security-review check --phase build

说明:

  • allowedRegistryDomains 只用于校验 .npmrcpackage-lock.jsonpnpm-lock.yamlyarn.lock 中出现的源域名是否可信
  • audit.registry 只用于指定 npm audit / pnpm audit 请求的审计接口地址

使用指南

本工具库为您提供了在开发、提交以及 CI 等任意环节切入审查的能力:

1. CLI 命令行直接使用

推荐直接跑在 CI 流水线或通过 Husky 的 pre-commit 钩子调用:

# 全局全量源文件构建前审查
pnpm wui-security-review check --phase build

# 自动适配 CI 阶段(使用 json 格式化输出方便程序化解析截断流水线)
pnpm wui-security-review check --phase ci --format json

# 针对 Husky / lint-staged(通过 --staged 指令,仅检查 git 暂存区发生变更的文件提升速度)
pnpm wui-security-review check --phase pre-commit --staged

# 检查并额外输出可视化 HTML 大屏报告(默认输出至项目根目录 security-report.html)
pnpm wui-security-review check --phase build --html

# 指定独立输出 HTML 报告的自定义路径
pnpm wui-security-review check --phase build --html ./reports/dashboard.html

# CLI 默认会打印扫描文件列表;需要脱敏时可显式隐藏
pnpm wui-security-review check --phase build --hide-scanned-files

# 当扫描文件很多时,进一步展开完整列表
pnpm wui-security-review check --phase build --expand-files

2. Vite 插件集成

如果不希望额外配 CLI,你可以把它当成普通打包环节的 Plugin 挂载,使得开发(dev)或生产构建(build)时同步报错拦截。

// vite.config.ts
import { defineConfig } from 'vite'
import { createViteSecurityPlugin } from '@wuipkg/security-review/vite'

export default defineConfig({
  plugins: [
    // 默认会自动寻址当前工程下的 wui-security.config.ts 全局配置
    createViteSecurityPlugin()
  ]
})

React + Vite

React 项目无需单独的 React 子入口,直接复用同一个 Vite 插件即可:

// vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { createViteSecurityPlugin } from '@wuipkg/security-review/vite'

export default defineConfig({
  plugins: [react(), createViteSecurityPlugin()]
})

3. Webpack 插件集成

为传统的 Webpack 工程提供完全一致的使用体验:

// webpack.config.ts
import { createWebpackSecurityPlugin } from '@wuipkg/security-review/webpack'

export default {
  plugins: [createWebpackSecurityPlugin()]
}

React + Webpack

// webpack.config.ts
import { createWebpackSecurityPlugin } from '@wuipkg/security-review/webpack'

export default {
  module: {
    rules: [
      // 你的 tsx / jsx loader 配置
    ]
  },
  plugins: [createWebpackSecurityPlugin()]
}

4. ESLint 静态代码提示并轨

我们将可做静态 AST 分析的安全规则单独整理到了此配置下,让你在写代码的第一时间就在 IDE 收到红色波浪线提示:

// eslint.config.js (ESM flat config)
import lint from '@wuipkg/lint/eslint'
import securityReview from '@wuipkg/security-review/eslint'

export default [
  ...lint,
  // 接入专属的 AST 静态安全审查引擎池
  ...securityReview
]

React + ESLint

React / TSX 工程同样使用这一子入口,但需要宿主 ESLint 配置先具备 JSX / TSX parser 能力;在本仓库里推荐直接与 @wuipkg/lint/eslint 组合使用:

// eslint.config.js
import lint from '@wuipkg/lint/eslint'
import securityReview from '@wuipkg/security-review/eslint'

export default [...lint, ...securityReview]

注意: @wuipkg/security-review/eslint 负责导出安全规则本身,不会额外注入 React / TSX parser。 React Router 的 open redirect 检测(例如 useNavigate()<Navigate />)仅由源码扫描规则覆盖, 需要通过 CLI / runSecurityReview / Vite / Webpack 接入;/eslint 子入口不负责这部分语义分析。

React 典型风险示例

// 1. DOM XSS
export const Preview = ({ html }) => (
  <div dangerouslySetInnerHTML={{ __html: html }} />
)

// 2. Reverse Tabnabbing
export const Link = () => <a href="https://a.com" target="_blank">Open</a>

// 3. 表单外链劫持
export const PaymentForm = ({ externalUrl }) => (
  <form action={externalUrl}></form>
)

// 4. Open Redirect
import { useNavigate } from 'react-router-dom'

export const Login = () => {
  const navigate = useNavigate()
  const redirect = new URLSearchParams(window.location.search).get('redirect')
  navigate(redirect || '/')
  return null
}

ESLint 规则清单

| 规则名 | 默认等级 | 描述 | | ------------------------------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | @wuipkg/security-review/no-dangerous-dom-api | error | 禁止 innerHTMLouterHTML 属性赋值,document.writeeval 调用;React 项目应同时配合源码规则检查 dangerouslySetInnerHTML。 | | @wuipkg/security-review/require-message-origin-check | error | 要求 window.addEventListener('message', ...) 处理器首条语句校验 event.origin。 | | @wuipkg/security-review/no-unsafe-redirect | error | 禁止直接把 URL 参数(location.search$route.query 等)写入 location.href 或传给 location.assign/replace。支持递归检查调用链、模板字符串、逻辑表达式等复合表达式。 | | @wuipkg/security-review/no-sensitive-storage | error | 禁止 localStorage/sessionStorage.setItemtokenidCardphone 等敏感词作为 key 明文存储。 |

API 导出

本包通过主入口 @wuipkg/security-review 导出以下类型和函数:

函数

| 导出名 | 描述 | | -------------------------------- | ------------------------------------------ | | defineSecurityConfig(config) | 配置辅助函数,提供完整类型提示 | | loadSecurityConfig(options?) | 从 wui-security.config.ts 加载并解析配置 | | resolveSecurityConfig(config?) | 将用户配置与默认值合并为完整配置 | | runSecurityReview(options) | 执行安全审查,返回完整报告 | | createReporter(format) | 创建格式化报告器 ('pretty' | 'json') | | formatPrettyReport(report) | 格式化为终端可读的彩色报告 | | shouldFailReport(report) | 判断报告是否包含错误级别发现 |

类型

| 导出类型 | 描述 | | ------------------------------ | ---------------------------------------------------------------------------- | | SecurityReviewConfig | 用户配置接口 | | ResolvedSecurityReviewConfig | 合并后的完整配置 | | ResolvedSecurityRuleSetting | 单条规则解析后的设置(含 leveloptions) | | SecurityRuleName | 所有规则名联合类型 | | SecurityRuleLevel | 'off' \| 'warn' \| 'error' | | SecurityRuleInput | 规则配置输入类型(SecurityRuleLevel \| { level?, options? } \| undefined) | | SecurityFinding | 单条审查发现 | | SecurityReviewReport | 完整审查报告(含 findingssuppressedFindingssummary) | | SecurityPhase | 'pre-commit' \| 'build' \| 'post-build' \| 'ci' | | SecurityReporter | 报告器接口(含 formatrender) | | SecurityReporterFormat | 报告器格式类型('pretty' \| 'json') | | CredentialDetectContext | detect 回调的上下文参数 | | CredentialDetectFn | detect 回调的函数签名 | | RunSecurityReviewOptions | runSecurityReview 的选项 |

License

MIT