@zhuma4/cli 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +18 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +11 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/scan.d.ts +3 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +96 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/scan_appid.d.ts +20 -0
- package/dist/commands/scan_appid.d.ts.map +1 -0
- package/dist/commands/scan_appid.js +301 -0
- package/dist/commands/scan_appid.js.map +1 -0
- package/dist/commands/scan_manifest.d.ts +13 -0
- package/dist/commands/scan_manifest.d.ts.map +1 -0
- package/dist/commands/scan_manifest.js +103 -0
- package/dist/commands/scan_manifest.js.map +1 -0
- package/dist/engine/api-submit.d.ts +16 -0
- package/dist/engine/api-submit.d.ts.map +1 -0
- package/dist/engine/api-submit.js +66 -0
- package/dist/engine/api-submit.js.map +1 -0
- package/dist/engine/batch_scan.d.ts +36 -0
- package/dist/engine/batch_scan.d.ts.map +1 -0
- package/dist/engine/batch_scan.js +192 -0
- package/dist/engine/batch_scan.js.map +1 -0
- package/dist/engine/config.d.ts +12 -0
- package/dist/engine/config.d.ts.map +1 -0
- package/dist/engine/config.js +27 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/errors.d.ts +36 -0
- package/dist/engine/errors.d.ts.map +1 -0
- package/dist/engine/errors.js +99 -0
- package/dist/engine/errors.js.map +1 -0
- package/dist/engine/filter.d.ts +13 -0
- package/dist/engine/filter.d.ts.map +1 -0
- package/dist/engine/filter.js +64 -0
- package/dist/engine/filter.js.map +1 -0
- package/dist/engine/finding_classifier.d.ts +108 -0
- package/dist/engine/finding_classifier.d.ts.map +1 -0
- package/dist/engine/finding_classifier.js +440 -0
- package/dist/engine/finding_classifier.js.map +1 -0
- package/dist/engine/incremental/engine.d.ts +25 -0
- package/dist/engine/incremental/engine.d.ts.map +1 -0
- package/dist/engine/incremental/engine.js +337 -0
- package/dist/engine/incremental/engine.js.map +1 -0
- package/dist/engine/incremental/git-diff.d.ts +19 -0
- package/dist/engine/incremental/git-diff.d.ts.map +1 -0
- package/dist/engine/incremental/git-diff.js +175 -0
- package/dist/engine/incremental/git-diff.js.map +1 -0
- package/dist/engine/incremental/types.d.ts +33 -0
- package/dist/engine/incremental/types.d.ts.map +1 -0
- package/dist/engine/incremental/types.js +11 -0
- package/dist/engine/incremental/types.js.map +1 -0
- package/dist/engine/manifest_scanner.d.ts +48 -0
- package/dist/engine/manifest_scanner.d.ts.map +1 -0
- package/dist/engine/manifest_scanner.js +599 -0
- package/dist/engine/manifest_scanner.js.map +1 -0
- package/dist/engine/project.d.ts +22 -0
- package/dist/engine/project.d.ts.map +1 -0
- package/dist/engine/project.js +279 -0
- package/dist/engine/project.js.map +1 -0
- package/dist/engine/sarif.d.ts +13 -0
- package/dist/engine/sarif.d.ts.map +1 -0
- package/dist/engine/sarif.js +44 -0
- package/dist/engine/sarif.js.map +1 -0
- package/dist/engine/sca-integration.d.ts +36 -0
- package/dist/engine/sca-integration.d.ts.map +1 -0
- package/dist/engine/sca-integration.js +91 -0
- package/dist/engine/sca-integration.js.map +1 -0
- package/dist/engine/scanner.d.ts +18 -0
- package/dist/engine/scanner.d.ts.map +1 -0
- package/dist/engine/scanner.js +138 -0
- package/dist/engine/scanner.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/report/render.d.ts +23 -0
- package/dist/report/render.d.ts.map +1 -0
- package/dist/report/render.js +335 -0
- package/dist/report/render.js.map +1 -0
- package/package.json +41 -0
- package/rules/android/mobile-cleartext-traffic.yaml +46 -0
- package/rules/android/mobile-component-security.yaml +107 -0
- package/rules/android/mobile-crypto-weakness.yaml +139 -0
- package/rules/android/mobile-cwe-1021-tapjacking.yaml +81 -0
- package/rules/android/mobile-cwe-114-dynamic-dex-loading.yaml +41 -0
- package/rules/android/mobile-cwe-200-clipboard-data-leak.yaml +66 -0
- package/rules/android/mobile-cwe-200-debug-builds.yaml +111 -0
- package/rules/android/mobile-cwe-200-log-sensitive-data.yaml +61 -0
- package/rules/android/mobile-cwe-200-webview-debugging.yaml +56 -0
- package/rules/android/mobile-cwe-200-webview-universal-access.yaml +30 -0
- package/rules/android/mobile-cwe-200-window-flags.yaml +96 -0
- package/rules/android/mobile-cwe-22-content-provider-openfile.yaml +73 -0
- package/rules/android/mobile-cwe-22-path-traversal.yaml +86 -0
- package/rules/android/mobile-cwe-287-biometric-weakness.yaml +102 -0
- package/rules/android/mobile-cwe-295-cert-pinning-missing.yaml +78 -0
- package/rules/android/mobile-cwe-295-webview-ssl-bypass.yaml +104 -0
- package/rules/android/mobile-cwe-312-cleartext-storage.yaml +109 -0
- package/rules/android/mobile-cwe-319-cleartext-communication.yaml +84 -0
- package/rules/android/mobile-cwe-321-hardcoded-crypto-keys.yaml +132 -0
- package/rules/android/mobile-cwe-326-short-rsa.yaml +108 -0
- package/rules/android/mobile-cwe-327-rc4-3des.yaml +107 -0
- package/rules/android/mobile-cwe-329-cbc-padding-oracle.yaml +76 -0
- package/rules/android/mobile-cwe-470-reflection-injection.yaml +39 -0
- package/rules/android/mobile-cwe-489-root-detection-weak.yaml +125 -0
- package/rules/android/mobile-cwe-489-stetho-debug.yaml +107 -0
- package/rules/android/mobile-cwe-502-insecure-deserialization.yaml +76 -0
- package/rules/android/mobile-cwe-552-world-readable-files.yaml +63 -0
- package/rules/android/mobile-cwe-749-webview-java-objects.yaml +78 -0
- package/rules/android/mobile-cwe-749-webview-jsbridge.yaml +57 -0
- package/rules/android/mobile-cwe-749-webview-loadurl-injection.yaml +80 -0
- package/rules/android/mobile-cwe-78-command-injection.yaml +77 -0
- package/rules/android/mobile-cwe-780-rsa-no-oaep.yaml +80 -0
- package/rules/android/mobile-cwe-79-webview-setdata.yaml +78 -0
- package/rules/android/mobile-cwe-79-webview-xss.yaml +65 -0
- package/rules/android/mobile-cwe-798-hardcoded-credentials.yaml +108 -0
- package/rules/android/mobile-cwe-89-sql-injection.yaml +100 -0
- package/rules/android/mobile-cwe-927-implicit-intent.yaml +121 -0
- package/rules/android/mobile-cwe-927-ipc-file-provider.yaml +102 -0
- package/rules/android/mobile-cwe-939-deeplink-validation.yaml +76 -0
- package/rules/android/mobile-sdk-google-firebase-open.yaml +117 -0
- package/rules/android/mobile-sdk-tencent-tpns-config-leak.yaml +131 -0
- package/rules/android/mobile-secrets-storage.yaml +136 -0
- package/rules/android/mobile-webview-security.yaml +88 -0
- package/rules/common/cwe-200-sensitive-data-exposure.yaml +61 -0
- package/rules/common/cwe-22-path-traversal.yaml +47 -0
- package/rules/common/cwe-295-ssl-bypass.yaml +217 -0
- package/rules/common/cwe-295-ssl-verification-disabled.yaml +64 -0
- package/rules/common/cwe-306-missing-authentication.yaml +44 -0
- package/rules/common/cwe-326-weak-key-size.yaml +107 -0
- package/rules/common/cwe-327-weak-crypto.yaml +177 -0
- package/rules/common/cwe-328-weak-hash.yaml +96 -0
- package/rules/common/cwe-329-cbc-mode.yaml +26 -0
- package/rules/common/cwe-352-csrf.yaml +23 -0
- package/rules/common/cwe-434-unrestricted-file-upload.yaml +41 -0
- package/rules/common/cwe-502-insecure-deserialization.yaml +44 -0
- package/rules/common/cwe-601-url-redirect.yaml +110 -0
- package/rules/common/cwe-611-xxe.yaml +70 -0
- package/rules/common/cwe-732-incorrect-permission.yaml +49 -0
- package/rules/common/cwe-770-resource-exhaustion.yaml +44 -0
- package/rules/common/cwe-78-os-command-injection.yaml +43 -0
- package/rules/common/cwe-787-out-of-bounds-write.yaml +37 -0
- package/rules/common/cwe-79-xss.yaml +51 -0
- package/rules/common/cwe-862-missing-authorization.yaml +40 -0
- package/rules/common/cwe-89-sqli.yaml +89 -0
- package/rules/common/cwe-918-ssrf.yaml +45 -0
- package/rules/common/cwe-94-code-injection.yaml +59 -0
- package/rules/common/zm-go-cwe22-path-traversal-fs.yaml +117 -0
- package/rules/common/zm-go-cwe22-path-traversal.yaml +103 -0
- package/rules/common/zm-go-cwe307-brute-force.yaml +129 -0
- package/rules/common/zm-go-cwe326-weak-crypto.yaml +124 -0
- package/rules/common/zm-go-cwe327-weak-cipher.yaml +152 -0
- package/rules/common/zm-go-cwe384-session-fixation.yaml +128 -0
- package/rules/common/zm-go-cwe502-deserialization.yaml +120 -0
- package/rules/common/zm-go-cwe78-command-injection.yaml +95 -0
- package/rules/common/zm-go-cwe79-xss.yaml +104 -0
- package/rules/common/zm-go-cwe798-hardcoded-creds.yaml +153 -0
- package/rules/common/zm-go-cwe89-sqli.yaml +89 -0
- package/rules/common/zm-go-cwe918-ssrf.yaml +117 -0
- package/rules/common/zm-java-cwe117-log-injection.yaml +83 -0
- package/rules/common/zm-java-cwe117-logforging.yaml +153 -0
- package/rules/common/zm-java-cwe200-actuator-exposure.yaml +8 -0
- package/rules/common/zm-java-cwe200-info-disclosure.yaml +91 -0
- package/rules/common/zm-java-cwe22-file-depth.yaml +135 -0
- package/rules/common/zm-java-cwe22-path-traversal-spring.yaml +81 -0
- package/rules/common/zm-java-cwe284-missing-auth-spring.yaml +131 -0
- package/rules/common/zm-java-cwe295-webview-ssl.yaml +123 -0
- package/rules/common/zm-java-cwe327-weakcrypto.yaml +197 -0
- package/rules/common/zm-java-cwe347-jwt.yaml +30 -0
- package/rules/common/zm-java-cwe352-csrf-depth.yaml +107 -0
- package/rules/common/zm-java-cwe352-csrf-disabled.yaml +15 -0
- package/rules/common/zm-java-cwe501-trust-boundary.yaml +124 -0
- package/rules/common/zm-java-cwe502-deserial-depth.yaml +128 -0
- package/rules/common/zm-java-cwe502-fastjson.yaml +137 -0
- package/rules/common/zm-java-cwe502-gadget.yaml +158 -0
- package/rules/common/zm-java-cwe502-jndi-injection.yaml +91 -0
- package/rules/common/zm-java-cwe502-shiro.yaml +108 -0
- package/rules/common/zm-java-cwe601-url-redirect-spring.yaml +85 -0
- package/rules/common/zm-java-cwe611-xxe-enhanced.yaml +80 -0
- package/rules/common/zm-java-cwe611-xxe-transformer.yaml +85 -0
- package/rules/common/zm-java-cwe639-idor.yaml +123 -0
- package/rules/common/zm-java-cwe79-xss-depth.yaml +98 -0
- package/rules/common/zm-java-cwe862-authz-depth.yaml +127 -0
- package/rules/common/zm-java-cwe915-mass-assignment.yaml +16 -0
- package/rules/common/zm-java-cwe917-expression-injection.yaml +120 -0
- package/rules/common/zm-java-cwe918-resttemplate.yaml +67 -0
- package/rules/common/zm-java-cwe918-ssrf-depth.yaml +103 -0
- package/rules/common/zm-java-cwe918-ssrf-resttemplate.yaml +77 -0
- package/rules/common/zm-java-cwe918-webclient.yaml +44 -0
- package/rules/common/zm-java-cwe94-ognl.yaml +66 -0
- package/rules/common/zm-java-cwe94-spel-injection.yaml +85 -0
- package/rules/common/zm-java-cwe94-spel.yaml +112 -0
- package/rules/common/zm-java-cwe94-ssti.yaml +22 -0
- package/rules/common/zm-java-cwe942-cors.yaml +15 -0
- package/rules/common/zm-js-cwe1321-prototype-pollution.yaml +61 -0
- package/rules/common/zm-js-cwe200-info-disclosure.yaml +95 -0
- package/rules/common/zm-js-cwe22-path-traversal-fs.yaml +113 -0
- package/rules/common/zm-js-cwe22-pathtraversal.yaml +111 -0
- package/rules/common/zm-js-cwe307-brute-force.yaml +136 -0
- package/rules/common/zm-js-cwe345-postmessage.yaml +75 -0
- package/rules/common/zm-js-cwe347-jwt-weak.yaml +95 -0
- package/rules/common/zm-js-cwe352-csrf.yaml +52 -0
- package/rules/common/zm-js-cwe384-session-fixation.yaml +132 -0
- package/rules/common/zm-js-cwe502-deserialization.yaml +119 -0
- package/rules/common/zm-js-cwe611-xxe.yaml +108 -0
- package/rules/common/zm-js-cwe639-idor.yaml +122 -0
- package/rules/common/zm-js-cwe693-helmet-missing.yaml +46 -0
- package/rules/common/zm-js-cwe78-exec.yaml +37 -0
- package/rules/common/zm-js-cwe78-spawn.yaml +37 -0
- package/rules/common/zm-js-cwe79-domxss.yaml +84 -0
- package/rules/common/zm-js-cwe79-react-xss.yaml +18 -0
- package/rules/common/zm-js-cwe79-xss-ejs.yaml +70 -0
- package/rules/common/zm-js-cwe89-sqli.yaml +153 -0
- package/rules/common/zm-js-cwe915-mass-assignment.yaml +111 -0
- package/rules/common/zm-js-cwe918-ssrf-fetch.yaml +134 -0
- package/rules/common/zm-js-cwe918-ssrf.yaml +132 -0
- package/rules/common/zm-js-cwe94-template-injection.yaml +130 -0
- package/rules/common/zm-js-cwe942-cors.yaml +49 -0
- package/rules/common/zm-js-cwe943-nosql-injection.yaml +52 -0
- package/rules/common/zm-js-cwe95-eval.yaml +59 -0
- package/rules/common/zm-js-cwe95-function-ctor.yaml +31 -0
- package/rules/common/zm-py-cwe22-path-traversal.yaml +86 -0
- package/rules/common/zm-py-cwe327-weak-crypto.yaml +103 -0
- package/rules/common/zm-py-cwe502-pickle.yaml +92 -0
- package/rules/common/zm-py-cwe611-xxe.yaml +100 -0
- package/rules/common/zm-py-cwe78-command-injection.yaml +121 -0
- package/rules/common/zm-py-cwe79-xss.yaml +123 -0
- package/rules/common/zm-py-cwe798-hardcoded-creds.yaml +86 -0
- package/rules/common/zm-py-cwe89-sqli.yaml +59 -0
- package/rules/common/zm-py-cwe918-ssrf.yaml +123 -0
- package/rules/common/zm-py-cwe94-ssti.yaml +87 -0
- package/rules/common/zm-py-cwe943-nosql-injection.yaml +123 -0
- package/rules/iac/ansible/zm-ansible-cwe269-privilege-escalation.yaml +63 -0
- package/rules/iac/ansible/zm-ansible-cwe78-command-injection.yaml +67 -0
- package/rules/iac/ansible/zm-ansible-cwe798-hardcoded-creds.yaml +93 -0
- package/rules/iac/terraform/zm-tf-cwe200-s3-bucket-public.yaml +100 -0
- package/rules/iac/terraform/zm-tf-cwe284-sg-wide-open.yaml +88 -0
- package/rules/iac/terraform/zm-tf-cwe311-iam-wildcard.yaml +83 -0
- package/rules/iac/terraform/zm-tf-cwe319-rds-public.yaml +72 -0
- package/rules/iac/terraform/zm-tf-cwe798-hardcoded-creds.yaml +102 -0
- package/rules/iac/zm-docker-cwe250-root-user.yaml +50 -0
- package/rules/iac/zm-docker-cwe400-resource-limit.yaml +92 -0
- package/rules/iac/zm-docker-security.yaml +104 -0
- package/rules/iac/zm-k8s-cwe200-service-account.yaml +83 -0
- package/rules/iac/zm-k8s-cwe250-privileged.yaml +56 -0
- package/rules/iac/zm-k8s-security.yaml +79 -0
- package/rules/rules_index.yaml.off +477 -0
- package/rules/semgrep-registry/anonymous-ldap-bind.yaml +34 -0
- package/rules/semgrep-registry/bad-hexa-conversion.yaml +32 -0
- package/rules/semgrep-registry/blowfish-insufficient-key-size.yaml +39 -0
- package/rules/semgrep-registry/cbc-padding-oracle.yaml +38 -0
- package/rules/semgrep-registry/command-injection-formatted-runtime-call.yaml +90 -0
- package/rules/semgrep-registry/command-injection-process-builder.yaml +148 -0
- package/rules/semgrep-registry/cookie-missing-httponly.yaml +38 -0
- package/rules/semgrep-registry/cookie-missing-secure-flag.yaml +38 -0
- package/rules/semgrep-registry/crlf-injection-logs.yaml +86 -0
- package/rules/semgrep-registry/dangerous-groovy-shell.yaml +46 -0
- package/rules/semgrep-registry/el-injection.yaml +137 -0
- package/rules/semgrep-registry/formatted-sql-string.yaml +95 -0
- package/rules/semgrep-registry/http-response-splitting.yaml +44 -0
- package/rules/semgrep-registry/index.txt +1 -0
- package/rules/semgrep-registry/insecure-smtp-connection.yaml +34 -0
- package/rules/semgrep-registry/java-reverse-shell.yaml +43 -0
- package/rules/semgrep-registry/jdbc-sql-formatted-string.yaml +120 -0
- package/rules/semgrep-registry/ldap-entry-poisoning.yaml +41 -0
- package/rules/semgrep-registry/ldap-injection.yaml +82 -0
- package/rules/semgrep-registry/md5-used-as-password.yaml +44 -0
- package/rules/semgrep-registry/object-deserialization.yaml +34 -0
- package/rules/semgrep-registry/ognl-injection.yaml +839 -0
- package/rules/semgrep-registry/overly-permissive-file-permission.yaml +49 -0
- package/rules/semgrep-registry/permissive-cors.yaml +77 -0
- package/rules/semgrep-registry/script-engine-injection.yaml +66 -0
- package/rules/semgrep-registry/tainted-cmd-from-http-request.yaml +74 -0
- package/rules/semgrep-registry/tainted-env-from-http-request.yaml +46 -0
- package/rules/semgrep-registry/tainted-ldapi-from-http-request.yaml +42 -0
- package/rules/semgrep-registry/tainted-session-from-http-request.yaml +70 -0
- package/rules/semgrep-registry/tainted-xpath-from-http-request.yaml +38 -0
- package/rules/semgrep-registry/unsafe-reflection.yaml +39 -0
- package/rules/semgrep-registry/unvalidated-redirect.yaml +127 -0
- package/rules/semgrep-registry/url-rewriting.yaml +82 -0
- package/rules/semgrep-registry/weak-ssl-context.yaml +34 -0
- package/rules/semgrep-registry/xml-decoder.yaml +53 -0
- package/rules/semgrep-registry/xssrequestwrapper-is-insecure.yaml +40 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 逐码 CLI 错误处理 — 友好提示 + 排查建议
|
|
3
|
+
*
|
|
4
|
+
* 设计原则:
|
|
5
|
+
* 1. 所有错误输出为汉语 + 排查建议
|
|
6
|
+
* 2. 区分用户错误 (4xx) vs 系统错误 (5xx)
|
|
7
|
+
* 3. 不崩堆栈 — 仅在 --debug 模式输出完整 trace
|
|
8
|
+
*/
|
|
9
|
+
export class ZhumaError extends Error {
|
|
10
|
+
/** 错误码: 4xx=用户侧, 5xx=系统侧 */
|
|
11
|
+
code;
|
|
12
|
+
/** 排查建议 (面向终端用户) */
|
|
13
|
+
suggestion;
|
|
14
|
+
constructor(code, message, suggestion) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'ZhumaError';
|
|
17
|
+
this.code = code;
|
|
18
|
+
this.suggestion = suggestion;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Semgrep 未安装 */
|
|
22
|
+
export function semgrepNotFound(err) {
|
|
23
|
+
return new ZhumaError(500, '未找到 Semgrep CLI', `请执行: pip install semgrep\n` +
|
|
24
|
+
`验证安装: semgrep --version\n` +
|
|
25
|
+
`如果已安装仍报错,检查 PATH 环境变量是否包含 Semgrep 所在目录`);
|
|
26
|
+
}
|
|
27
|
+
/** 目标路径不存在 */
|
|
28
|
+
export function targetNotFound(target) {
|
|
29
|
+
return new ZhumaError(404, `目标路径不存在: ${target}`, `请检查路径拼写是否正确\n` +
|
|
30
|
+
`提示: 使用绝对路径 (如 C:\\projects\\my-app) 可避免相对路径歧义`);
|
|
31
|
+
}
|
|
32
|
+
/** Semgrep 扫描超时 */
|
|
33
|
+
export function scanTimeout(target, timeoutSec) {
|
|
34
|
+
return new ZhumaError(504, `扫描超时 (${timeoutSec}秒): ${target}`, `项目过大或文件过多导致超时\n` +
|
|
35
|
+
`建议:\n` +
|
|
36
|
+
` 1. 使用 --quick 快速模式 (仅运行 L0 高优先级规则)\n` +
|
|
37
|
+
` 2. 使用 --timeout 增加超时时间\n` +
|
|
38
|
+
` 3. 排除测试目录: zhuma config set exclude "**/test/**"`);
|
|
39
|
+
}
|
|
40
|
+
/** Semgrep 非零退出 (非1) */
|
|
41
|
+
export function semgrepCrashed(exitCode, stderr) {
|
|
42
|
+
return new ZhumaError(500, `Semgrep 扫描异常退出 (exit ${exitCode})`, `错误详情:\n${stderr.slice(-500)}\n\n` +
|
|
43
|
+
`常见原因:\n` +
|
|
44
|
+
` 1. Semgrep 版本过旧 → pip install --upgrade semgrep\n` +
|
|
45
|
+
` 2. 规则文件语法错误 → 检查自定义规则 YAML\n` +
|
|
46
|
+
` 3. 目标项目编译错误 → 先确保项目能正常编译\n` +
|
|
47
|
+
` 4. 内存不足 → 尝试 --quick 模式或增加系统内存`);
|
|
48
|
+
}
|
|
49
|
+
/** SARIF JSON 解析失败 */
|
|
50
|
+
export function sarifParsedFailed(context) {
|
|
51
|
+
return new ZhumaError(500, `Semgrep 输出解析失败`, `Semgrep 产生的 SARIF JSON 无法解析\n\n` +
|
|
52
|
+
`输出快照:\n${context.slice(0, 300)}\n\n` +
|
|
53
|
+
`请确认 Semgrep 版本 ≥ 1.168.0\n` +
|
|
54
|
+
`如问题持续,运行 semgrep scan --debug 查看完整输出`);
|
|
55
|
+
}
|
|
56
|
+
/** 规则目录不存在 */
|
|
57
|
+
export function rulesNotFound(rulesPath) {
|
|
58
|
+
return new ZhumaError(404, `规则目录不存在: ${rulesPath}`, `请检查 --rules 参数指定的路径\n` +
|
|
59
|
+
`默认规则目录: packages/rules/common/\n` +
|
|
60
|
+
`列出可用规则: zhuma config show`);
|
|
61
|
+
}
|
|
62
|
+
/** 不支持的输出格式 */
|
|
63
|
+
export function unsupportedFormat(format) {
|
|
64
|
+
return new ZhumaError(400, `不支持的输出格式: ${format}`, `支持的格式: json | html | sarif\n` +
|
|
65
|
+
`示例: zhuma scan ./src -o html`);
|
|
66
|
+
}
|
|
67
|
+
/** 项目初始化失败 */
|
|
68
|
+
export function initFailed(reason) {
|
|
69
|
+
return new ZhumaError(500, `项目初始化失败: ${reason}`, `请检查:\n` +
|
|
70
|
+
` 1. 目标目录是否有读写权限\n` +
|
|
71
|
+
` 2. 磁盘空间是否充足\n` +
|
|
72
|
+
` 3. 是否已有 .zhuma.yaml (先删除后重试)`);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 全局错误拦截 — 打印友好错误 + 退出
|
|
76
|
+
*/
|
|
77
|
+
export function handleError(err, debug = false) {
|
|
78
|
+
if (err instanceof ZhumaError) {
|
|
79
|
+
console.error(`\n❌ 错误 (${err.code}): ${err.message}\n`);
|
|
80
|
+
console.error(`💡 排查建议:\n${err.suggestion}\n`);
|
|
81
|
+
if (debug) {
|
|
82
|
+
console.error('--- DEBUG ---');
|
|
83
|
+
console.error(err.stack);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (err instanceof Error) {
|
|
87
|
+
console.error(`\n❌ 未预期错误: ${err.message}\n`);
|
|
88
|
+
console.error('请使用 --debug 查看完整堆栈\n');
|
|
89
|
+
if (debug) {
|
|
90
|
+
console.error('--- DEBUG ---');
|
|
91
|
+
console.error(err.stack);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
console.error(`\n❌ 未知错误: ${String(err)}\n`);
|
|
96
|
+
}
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/engine/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 白名单过滤器 — SDK / 框架类 / 已知噪声过滤
|
|
3
|
+
*
|
|
4
|
+
* 从 V3.3 filter_findings.js 迁移 + 方法级白名单扩展
|
|
5
|
+
*/
|
|
6
|
+
import type { Finding } from '@zhuma4/sdk';
|
|
7
|
+
/**
|
|
8
|
+
* 过滤 SDk 和已知噪声发现
|
|
9
|
+
* @param findings 原始发现列表
|
|
10
|
+
* @returns 过滤后的结果
|
|
11
|
+
*/
|
|
12
|
+
export declare function filterFindings(findings: Finding[]): Finding[];
|
|
13
|
+
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/engine/filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAoC3C;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAyB7D"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 白名单过滤器 — SDK / 框架类 / 已知噪声过滤
|
|
3
|
+
*
|
|
4
|
+
* 从 V3.3 filter_findings.js 迁移 + 方法级白名单扩展
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 已知无害的包路径前缀 (SDK / 框架类)
|
|
8
|
+
*/
|
|
9
|
+
const SDK_WHITELIST = [
|
|
10
|
+
'android.',
|
|
11
|
+
'androidx.',
|
|
12
|
+
'com.google.',
|
|
13
|
+
'com.facebook.',
|
|
14
|
+
'com.amazon.',
|
|
15
|
+
'io.netty.',
|
|
16
|
+
'org.springframework.test.',
|
|
17
|
+
'com.fasterxml.jackson.',
|
|
18
|
+
'org.hibernate.',
|
|
19
|
+
'junit.',
|
|
20
|
+
'org.junit.',
|
|
21
|
+
'org.mockito.',
|
|
22
|
+
'com.sun.',
|
|
23
|
+
'sun.',
|
|
24
|
+
'java.',
|
|
25
|
+
'javax.',
|
|
26
|
+
];
|
|
27
|
+
/**
|
|
28
|
+
* 已知无害的方法/模式 (产生噪声的框架方法)
|
|
29
|
+
*/
|
|
30
|
+
const METHOD_WHITELIST = [
|
|
31
|
+
'toString()',
|
|
32
|
+
'equals(Object)',
|
|
33
|
+
'hashCode()',
|
|
34
|
+
'clone()',
|
|
35
|
+
'finalize()',
|
|
36
|
+
'readObject(ObjectInputStream)',
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* 过滤 SDk 和已知噪声发现
|
|
40
|
+
* @param findings 原始发现列表
|
|
41
|
+
* @returns 过滤后的结果
|
|
42
|
+
*/
|
|
43
|
+
export function filterFindings(findings) {
|
|
44
|
+
const before = findings.length;
|
|
45
|
+
const filtered = findings.filter((f) => {
|
|
46
|
+
// 文件级白名单
|
|
47
|
+
for (const prefix of SDK_WHITELIST) {
|
|
48
|
+
if (f.file.includes(prefix.replace(/\./g, '/'))) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// 方法级白名单 (如果 message 中包含匹配)
|
|
53
|
+
for (const method of METHOD_WHITELIST) {
|
|
54
|
+
if (f.message.includes(method)) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
});
|
|
60
|
+
// TODO: V4.0 日志
|
|
61
|
+
// console.log(`[逐码] filter: ${before} → ${filtered.length} (${Math.round(filtered.length/before*100)}%)`);
|
|
62
|
+
return filtered;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../src/engine/filter.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,MAAM,aAAa,GAAG;IACpB,UAAU;IACV,WAAW;IACX,aAAa;IACb,eAAe;IACf,aAAa;IACb,WAAW;IACX,2BAA2B;IAC3B,wBAAwB;IACxB,gBAAgB;IAChB,QAAQ;IACR,YAAY;IACZ,cAAc;IACd,UAAU;IACV,MAAM;IACN,OAAO;IACP,QAAQ;CACT,CAAC;AAEF;;GAEG;AACH,MAAM,gBAAgB,GAAG;IACvB,YAAY;IACZ,gBAAgB;IAChB,YAAY;IACZ,SAAS;IACT,YAAY;IACZ,+BAA+B;CAChC,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAmB;IAChD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAE/B,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACrC,SAAS;QACT,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;gBAChD,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,4BAA4B;QAC5B,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IAEH,gBAAgB;IAChB,2GAA2G;IAE3G,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApplicationId-aware Finding Classifier — APP vs SDK vs UNKNOWN
|
|
3
|
+
*
|
|
4
|
+
* V4.1 AppID Boundary Engine
|
|
5
|
+
*
|
|
6
|
+
* 核心问题:
|
|
7
|
+
* jadx 反编译 APK → 80%+ Java 文件是三方 SDK/库代码
|
|
8
|
+
* 当前静态包白名单过滤不可靠(混入/混淆框架无效)
|
|
9
|
+
*
|
|
10
|
+
* 方案:
|
|
11
|
+
* 解析 AndroidManifest.xml 提取 applicationId + 组件声明包前缀
|
|
12
|
+
* 对每条 Semgrep finding 基于文件路径分类为 APP/SDK/UNKNOWN
|
|
13
|
+
*
|
|
14
|
+
* 分类优先级:
|
|
15
|
+
* EXACT match (appId 前缀) → APP very-high
|
|
16
|
+
* COMPONENT match (声明的组件前缀) → APP high
|
|
17
|
+
* SDK whitelist match → SDK very-high
|
|
18
|
+
* Nested SDK (app 包内嵌入 SDK) → SDK medium
|
|
19
|
+
* Fallback → UNKNOWN low
|
|
20
|
+
*/
|
|
21
|
+
/** Semgrep --json 输出的单条 finding */
|
|
22
|
+
export interface SemgrepResult {
|
|
23
|
+
check_id: string;
|
|
24
|
+
path: string;
|
|
25
|
+
start: {
|
|
26
|
+
line: number;
|
|
27
|
+
col: number;
|
|
28
|
+
};
|
|
29
|
+
end?: {
|
|
30
|
+
line: number;
|
|
31
|
+
col: number;
|
|
32
|
+
};
|
|
33
|
+
extra: {
|
|
34
|
+
severity: string;
|
|
35
|
+
message: string;
|
|
36
|
+
metadata?: Record<string, unknown>;
|
|
37
|
+
lines?: string;
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/** 分类后的 finding */
|
|
41
|
+
export interface ClassifiedFinding {
|
|
42
|
+
path: string;
|
|
43
|
+
package: string;
|
|
44
|
+
check_id: string;
|
|
45
|
+
severity: string;
|
|
46
|
+
line: number;
|
|
47
|
+
message: string;
|
|
48
|
+
classification: 'APP' | 'SDK' | 'UNKNOWN';
|
|
49
|
+
confidence: 'very-high' | 'high' | 'medium' | 'low';
|
|
50
|
+
source: 'exact-appid' | 'component-list' | 'sdk-whitelist' | 'nested-sdk' | 'fallback';
|
|
51
|
+
reason: string;
|
|
52
|
+
}
|
|
53
|
+
/** 分类统计 */
|
|
54
|
+
export interface ClassificationStats {
|
|
55
|
+
total: number;
|
|
56
|
+
app: number;
|
|
57
|
+
sdk: number;
|
|
58
|
+
unknown: number;
|
|
59
|
+
byConfidence: Record<string, number>;
|
|
60
|
+
bySource: Record<string, number>;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* 从 AndroidManifest.xml 提取 applicationId (package 属性)
|
|
64
|
+
*/
|
|
65
|
+
export declare function extractApplicationId(manifestPath: string): string;
|
|
66
|
+
/**
|
|
67
|
+
* 从 AndroidManifest.xml 提取所有声明的组件包前缀
|
|
68
|
+
*
|
|
69
|
+
* 解析 <activity>/<service>/<receiver>/<provider> 的 android:name 属性
|
|
70
|
+
* 提取其包前缀 (最后一段类名之前的包路径)
|
|
71
|
+
*
|
|
72
|
+
* 处理相对类名: 如果 android:name 以 "." 开头,拼接 applicationId
|
|
73
|
+
*/
|
|
74
|
+
export declare function getComponentPackages(manifestPath: string): Set<string>;
|
|
75
|
+
/**
|
|
76
|
+
* 将 jadx 反编译文件路径转换为 Java 包名
|
|
77
|
+
*
|
|
78
|
+
* 输入: "sources/com/jxd/whj_learn/utils/AesUtils.java"
|
|
79
|
+
* 输出: "com.jxd.whj_learn.utils"
|
|
80
|
+
*
|
|
81
|
+
* 容错: 路径可能不含 "sources/" 前缀 (Semgrep 输出路径取决于扫描根目录)
|
|
82
|
+
*/
|
|
83
|
+
export declare function pathToPackage(filePath: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* 对单条 Semgrep finding 进行分类
|
|
86
|
+
*/
|
|
87
|
+
export declare function classifyFinding(finding: SemgrepResult, appId: string, componentPrefixes: Set<string>): ClassifiedFinding;
|
|
88
|
+
/**
|
|
89
|
+
* 批量分类 Semgrep findings
|
|
90
|
+
*
|
|
91
|
+
* @param findings - Semgrep --json 输出的 results 数组
|
|
92
|
+
* @param manifestPath - jadx 输出中的 AndroidManifest.xml 路径
|
|
93
|
+
* @returns 带分类标签的 finding 列表
|
|
94
|
+
*/
|
|
95
|
+
export declare function classifyFindings(findings: SemgrepResult[], manifestPath: string): ClassifiedFinding[];
|
|
96
|
+
/**
|
|
97
|
+
* 按分类筛选 findings
|
|
98
|
+
*
|
|
99
|
+
* @param findings - 已分类的 findings
|
|
100
|
+
* @param classifications - 要保留的分类列表 (e.g. ['APP', 'UNKNOWN'])
|
|
101
|
+
* @returns 筛选后的 findings
|
|
102
|
+
*/
|
|
103
|
+
export declare function filterByClassification(findings: ClassifiedFinding[], classifications: string[]): ClassifiedFinding[];
|
|
104
|
+
/**
|
|
105
|
+
* 生成分类统计摘要
|
|
106
|
+
*/
|
|
107
|
+
export declare function getClassificationStats(findings: ClassifiedFinding[]): ClassificationStats;
|
|
108
|
+
//# sourceMappingURL=finding_classifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finding_classifier.d.ts","sourceRoot":"","sources":["../../src/engine/finding_classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,mCAAmC;AACnC,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,GAAG,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnC,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AAED,mBAAmB;AACnB,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;IAC1C,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACpD,MAAM,EAAE,aAAa,GAAG,gBAAgB,GAAG,eAAe,GAAG,YAAY,GAAG,UAAU,CAAC;IACvF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,WAAW;AACX,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAqKD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAejE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,YAAY,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CA0CtE;AAID;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAmBtD;AA2CD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC7B,iBAAiB,CAoFnB;AAID;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,aAAa,EAAE,EACzB,YAAY,EAAE,MAAM,GACnB,iBAAiB,EAAE,CAKrB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,eAAe,EAAE,MAAM,EAAE,GACxB,iBAAiB,EAAE,CAGrB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,mBAAmB,CAwBzF"}
|