Metadata-Version: 2.4
Name: jintang
Version: 26.9.1
Summary: 固若金汤（Jintang）—— 多合一 Web 安全 SDK（Python），为你的应用披上铠甲
Author: FALLEN ALLEN & ima Copilot
License: MIT
Project-URL: Repository, https://gitee.com/fallen-allen/jintang
Project-URL: Issues, https://gitee.com/fallen-allen/jintang/issues
Project-URL: Changelog, https://gitee.com/fallen-allen/jintang/blob/master/CHANGELOG.md
Keywords: web-security,xss-prevention,sql-injection,ssrf,sanitizer,waf,html-sanitizer,input-validation,honeypot,rbac
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=40.0
Requires-Dist: nh3>=0.2.15
Provides-Extra: test
Requires-Dist: pytest>=7.0; extra == "test"
Requires-Dist: cryptography>=40.0; extra == "test"
Requires-Dist: nh3>=0.2.15; extra == "test"
Provides-Extra: nh3
Requires-Dist: nh3>=0.2.15; extra == "nh3"
Provides-Extra: full
Requires-Dist: nh3>=0.2.15; extra == "full"
Requires-Dist: cryptography>=40.0; extra == "full"
Dynamic: license-file

# 固若金汤 · Jintang

**给 Python Web 应用加一层输入层防御的嵌入式安全库** —— 消毒、认证、访问控制、限流、加密存储、告警，一个类接进去。

[![version](https://img.shields.io/badge/version-26.9.0-4a90d9)](https://gitee.com/fallen-allen/jintang/blob/master/CHANGELOG.md)
[![license](https://img.shields.io/badge/license-MIT-green)](https://gitee.com/fallen-allen/jintang/blob/master/LICENSE)
[![python](https://img.shields.io/badge/python-3.8%2B-blue)](https://gitee.com/fallen-allen/jintang/blob/master/pyproject.toml)
[![tests](https://img.shields.io/badge/tests-21%20passed-brightgreen)](https://gitee.com/fallen-allen/jintang/tree/master/tests)
[![fuzz](https://img.shields.io/badge/atheris-300k%20runs%20%2F%200%20crash-orange)](https://gitee.com/fallen-allen/jintang/blob/master/SECURITY_ASSESSMENT.md)

> 定位先说清楚：**它是"内衬"，不是"城墙"。** 装在应用里面挡输入层的常见攻击，不是反向代理级 WAF，也不替代 DOMPurify / ModSecurity。它最适合的场景是**内部后台、中小项目、以及教学与学习**。

---

## 先看效果（不用写一行代码）

```bash
pip install jintang
python -m jintang.demo
```

然后打开 **http://127.0.0.1:5000** —— 页面上直接点「试试 XSS」「试试 SQL 注入」「试试路径穿越」，看它怎么拦、告警怎么记。打开 `/alarms` 能看到分级记录。

> 它会自动生成一个临时主密码，不写配置、不改任何东西，Ctrl+C 就停。
> 看懂效果了，再往下接你自己的项目。

---

## 30 秒上手（写代码）

```bash
pip install jintang
```

```python
import os
os.environ["JINTANG_MASTER"] = "换成一个足够长的随机主密码"   # 必须设置，否则拒绝启动

from jintang import Jintang
b = Jintang()

result = b.process(filename="report.docx", content="<p>用户提交的内容</p>",
                   username="alice", token="会话token", ip="127.0.0.1")
print(result)      # "OK" 放行；其他为拦截原因
```

完整可运行示例：[`examples/flask_demo.py`](https://gitee.com/fallen-allen/jintang/blob/master/examples/flask_demo.py)、[`examples/fastapi_demo.py`](https://gitee.com/fallen-allen/jintang/blob/master/examples/fastapi_demo.py)、[`examples/django_demo.py`](https://gitee.com/fallen-allen/jintang/blob/master/examples/django_demo.py)。

### 常见困惑：为什么全返回 `ZERO_TRUST_BOUNCED`？

零信任内核**默认拒绝一切没有有效会话的请求**，所以必须按顺序来：

```python
b = Jintang()
b.register("alice", "YourStr0ngPass!")
token = b.login("alice", "YourStr0ngPass!", "web", "1.2.3.4")   # 先拿会话
b.process(..., username="alice", token=token, ip="1.2.3.4")     # 再带会话调用
```

不传 `token`/`username`/`ip` 时，`process()` 一律返回 `ZERO_TRUST_BOUNCED`——这是设计行为，不是装坏了。

---

## 它解决什么

| 场景 | 没有它 | 有它 |
|---|---|---|
| 后台接收富文本 / 文件名 | 自己拼正则，随手漏一个 `onerror=` | 前置检测 + nh3(Rust) 解析器级消毒 + 后置复检 |
| 登录接口被人拿字典撞 | 自己写限流，写错方向就是误锁用户 | PBKDF2(60万轮) + 弱口令黑名单 + 单 IP 滑动窗锁定 + 抗枚举的时间恒定比较 |
| 一个后台三种角色 | 每个视图手写 `if role == ...` | RBAC 四级 + 先鉴权后解密 + 越权写拦截 |
| 要存一点敏感配置 | 明文写进 `.env` 或数据库 | AES-256-GCM + HKDF 分离 enc/mac + 口令分片恢复 |
| 想知道"有没有人打我" | 翻 nginx 日志猜 | 分级告警 + 同源事件关联（语义攻击链）+ 蜜罐账号 |

---

## 防护矩阵（按代码事实，不按宣传）

| 威胁 | 覆盖 | 实现方式 |
|---|---|---|
| XSS / mXSS 变体 | ✅ | 前置特征检测 → nh3 Rust 消毒 → 解码收敛/NFKC → 后置复检；CSS 属性白名单过滤 `expression`/`-moz-binding`/`@import` |
| SQL 注入 | ✅ 检测 | OWASP CRS 规则 942 分层：UNION+SELECT / 高危关键字 / 布尔等值 / 注释混淆。**是检测拦截，不是参数化查询的替代品** |
| 路径穿越 | ✅ | 文件名规范化 + `..`/分隔符/空字节校验 |
| 认证爆破、用户枚举 | ✅ | PBKDF2-SHA256 60 万轮、单 IP 滑动窗锁定、dummy hash 时间恒定比较 |
| 越权读写 | ✅ | RBAC 四级 + owner 校验 + 先鉴权后解密 |
| SSRF（内网探测） | ⚠️ 部分 | 字面量 IP 全形态覆盖（点分/十进制/十六进制/`127.1` 简写/`[::1]`/CGNAT 100.64/10）；**域名级解析默认关闭**（`JINTANG_SSRF_DNS=1` 开启，带 1s 超时与缓存） |
| 暴力频率 | ⚠️ 部分 | 分用户 + 时间窗滑窗；空 IP 场景的聚合仍有已知缺陷 |
| 敏感数据落盘 | ⚠️ 库级 | AES-256-GCM + PBKDF2 + HKDF + 密钥分片；**不替代 KMS / 密钥托管** |
| 攻击感知 | ⚠️ 内存态 | 分级告警 + 语义攻击链；重启即丢，建议接外部日志 |

---

## 它不防什么（诚实清单）

| 不防 | 你该用什么 |
|---|---|
| **CSRF** | 框架自带 CSRF 中间件 + `SameSite` Cookie |
| **DDoS / CC** | CDN、反向代理、网关级限流 |
| **文件内容恶意** | 服务端 MIME 真实校验、杀毒扫描、沙箱解析 |
| **反序列化攻击** | 不反序列化不可信数据；用 `json` 而非 `pickle` |
| **业务逻辑漏洞** | 代码评审、威胁建模，工具代替不了 |
| **浏览器端 DOM XSS** | DOMPurify（服务端消毒无法覆盖浏览器解析差异） |
| **依赖链漏洞** | `pip-audit`、`dependabot` |

---

## 可信度：我们怎么验证自己

不靠嘴说"安全"，靠可复现的检查：

| 检查 | 工具 | 结果 |
|---|---|---|
| 单元 / 回归测试 | pytest | **21 passed**（认证、加密、并发、SSRF、分片、越权） |
| 静态分析 | Bandit 1.9.4 | High **0** / Medium 2（B104 硬编码绑定地址，误报）/ Low 0 |
| 依赖漏洞 | pip-audit 2.10.1 | 4 个依赖，**0 漏洞** |
| 模糊测试 | Atheris（libFuzzer） | **30 万次 / 0 crash / 0 slow unit** |
| 动态扫描 | OWASP ZAP 2.17 | **High 0**；Medium 6 与 Low 6 全部为宿主应用缺安全响应头 |
| 自建 DAST | Flask 靶机 + 9 条真实攻击 | 9/9 符合预期 |

**已修复的可公开缺陷（含我们自己挖出来的）**

| 编号 | 问题 | 发现方式 | 状态 |
|---|---|---|---|
| J-01 | `_ssrf_blocked()` 把用户输入交给无超时的 `getaddrinfo()`，单请求可阻塞 19.4 秒（放大后 57.9 秒）→ DoS | Atheris 模糊测试（人工四轮审计未发现） | 26.9.0 已修，现 0.002 秒 |
| — | salt 未持久化，重启后磁盘保险箱永久无法解密 | 人工审计 | 已修 |
| — | 先解密后鉴权（可被越权尝试） | 人工审计 | 已修 |
| — | enc/mac 同密钥 | 人工审计 | 已修（HKDF 分离） |

完整报告：[`SECURITY_ASSESSMENT.md`](https://gitee.com/fallen-allen/jintang/blob/master/SECURITY_ASSESSMENT.md)（含 ASVS 5.0 对照与复现命令）、[`CHANGELOG.md`](https://gitee.com/fallen-allen/jintang/blob/master/CHANGELOG.md)。

> 说明：以上均为**本机、本地闭环**的自动化检查，**不等于第三方专业渗透测试**。生产核心资产请自行做独立评估。

---

## 与同类的关系

| | Jintang | nh3 / bleach | DOMPurify | ModSecurity |
|---|---|---|---|---|
| 形态 | Python 库（嵌入式） | Python 库 | JS（浏览器/Node） | 反向代理模块 |
| 强项 | 输入消毒 + 认证 + 权限 + 加密 + 告警的组合 | 单一但极稳的 HTML 消毒 | 浏览器端 XSS 标杆 | 网关级规则引擎 |
| 消毒内核 | 复用 nh3（Rust） | 自身 | 自身（DOM） | 规则 |
| 建议 | 需要"一层够用"的组合防御时用 | 只需要消毒时，直接用它们 | 前端渲染不可信 HTML 时用 | 需要网关级防护时用 |

**它不是 nh3 的替代品，nh3 是它的依赖。**

---

## 适合 / 不适合

**适合**：内部管理后台、中小型 Python 项目、爬虫数据入库前的清洗、安全课程与毕设、想读懂"防御怎么落地"的学习者。

**不适合**：高并发公网网关（用 nginx + WAF）、需要过等保/合规审计的核心系统（需要商用产品与 SLA）、只想要一个消毒函数（直接 `nh3.clean()`）。

---

## 文档

- [`docs/INTEGRATION.md`](https://gitee.com/fallen-allen/jintang/blob/master/docs/INTEGRATION.md) —— 开发者接入指南（三种调用方式、参数、四个集成陷阱）
- [`docs/USAGE_zh.md`](https://gitee.com/fallen-allen/jintang/blob/master/docs/USAGE_zh.md) —— 中文使用说明（环境变量、返回码、保险箱、告警、RBAC）
- [`docs/SECURITY_GUIDE.md`](https://gitee.com/fallen-allen/jintang/blob/master/docs/SECURITY_GUIDE.md) —— 攻击样例 → 拦截点 → 对应代码位置（教材向）
- [`docs/ROADMAP.md`](https://gitee.com/fallen-allen/jintang/blob/master/docs/ROADMAP.md) —— 拆包计划、发布节奏、维护承诺
- [`CHANGELOG.md`](https://gitee.com/fallen-allen/jintang/blob/master/CHANGELOG.md) —— 每个版本改了什么、为什么改
- [`SECURITY_ASSESSMENT.md`](https://gitee.com/fallen-allen/jintang/blob/master/SECURITY_ASSESSMENT.md) —— 安全评估报告

---

## 名字与版本

**固若金汤**出自《汉书·蒯通传》："皆为金城汤池，不可攻也。" 版本号沿用元素周期表（V21 Sc → V26 Fe），寓意防御体系逐版演进。

## 致谢上游

DOMPurify（cure53）教会"让解析器干活"；nh3 / ammonia 提供 Rust 消毒内核；sanitize-html 提供 transformTags 思路；OWASP Java HTML Sanitizer 提供策略预编译；雷池 SafeLine 启发语义分析；ModSecurity / OWASP CRS 规则 942 是 SQL 注入检测的老师；Django / LeWAF 是中间件管道范本。

没有这些项目，就没有 Jintang。

## 关于作者

一个中学生写的项目。代码是学来的，把学到的东西整理成能跑的东西，再交出去——仅此而已。

**一个学生写的东西，如果能让另一个人学会一点安全，它就有价值。**

---

## 免责声明

- MIT 许可，可自由使用、修改、分发，作者不承担任何责任
- **禁止**用于任何未授权的攻击、渗透或破坏行为
- 未经独立第三方安全审计，**不建议直接用于核心生产资产**
- 安全组件的正确性依赖正确集成：请阅读上文"它不防什么"

---

*每一面盾，都值得被看见。*
