Ozark-Security-Labs/SessionScope
GitHub: Ozark-Security-Labs/SessionScope
一款面向产品安全团队和开发者的防御性静态分析工具,通过对会话、Cookie、JWT 和 Token 全生命周期进行离线代码审计,系统性地发现身份验证配置缺陷与安全风险。
Stars: 0 | Forks: 0
# SessionScope
SessionScope 是一款防御性的产品安全工具,用于审计应用程序代码中的会话、cookie、JWT 和 token 生命周期行为。
它可以解答:
SessionScope 专为产品安全团队和开发人员设计,供那些需要对会话管理风险进行基于证据的审查,但又无需对运行中的系统发起攻击的人员使用。
## 问题
会话和 token 漏洞影响巨大且十分常见。团队通常依赖框架默认配置、分散的 middleware 或第三方库,但仍会无意中引入以下问题:
- cookie 缺少 `HttpOnly`、`Secure`、作用域受限的生命周期或 `SameSite`
- JWT 在未经颁发者或受众验证的情况下即被接受
- refresh token 从未进行轮换
- 登出路径未撤销服务端状态
- 长期有效的 token 未强制执行过期机制
- token 在信任边界之间被重用
- API 密钥或 bearer token 被存储在不安全的位置
- 密码重置或电子邮件验证 token 缺乏一次性使用语义
通过映射 token 生命周期路径和配置证据,可以对许多检查进行静态审查。
## 产品论点
身份验证安全不仅仅是“登录是否能正常工作?”。这是一个生命周期问题。
SessionScope 构建了一张涵盖 token 颁发、存储、验证、刷新、撤销和过期过程的映射图,以便审查人员能够清晰地看到生命周期中的漏洞。
## 初始范围
SessionScope 是一款适用于常见 Web 应用程序模式的 CLI 和 CI 友好型分析器。
初始目标:
- Express 会话/cookie/JWT middleware
- Next.js 身份验证/会话模式
- FastAPI 身份验证依赖项
- Django 会话和签名工具
- TypeScript 和 Python 中的 JWT 库
- 用于设置 cookie 的 API
初始输出:
- Markdown 生命周期报告
- JSON token 流量清单
- 针对高置信度问题的 SARIF 发现结果
- GitHub Actions 摘要
## 示例报告形式
```
Token: access_jwt
Issued at: src/auth/login.ts:44
Validation evidence:
- jwt.verify(token, publicKey)
- issuer check: present
- audience check: missing
- expiry check: library default
Storage evidence:
- Authorization bearer token expected
Risk: review_required
Reviewer question:
- Should this service enforce an audience claim?
```
```
Cookie: session
Set at: app/auth/session.py:71
Attributes:
- HttpOnly: present
- Secure: missing
- SameSite: lax
- Max-Age: 30 days
Risk: high_confidence_misconfiguration
Suggested fix:
- Set Secure in production cookie configuration.
```
## 核心概念
带有版本控制的清单和发现结果 schema 记录在
[`docs/SCHEMA.md`](docs/SCHEMA.md) 中。
### 生命周期阶段
SessionScope 通过以下阶段对身份验证产物进行建模:
- issue(颁发)
- store(存储)
- transmit(传输)
- validate(验证)
- refresh(刷新)
- revoke(撤销)
- expire(过期)
- introspect(内省)
### Token 类型
SessionScope 可分类:
- 会话 cookie
- 签名 cookie
- 访问 JWT
- 刷新 JWT
- 不透明的 bearer token
- API 密钥
- 服务 token
- 未知 token 流
- 密码重置 token
- 电子邮件验证 token
- 设备/会话记录
- token 作用域和信任边界证据
### 基于证据的发现结果
SessionScope 倾向于采用精确的表述:
- “在 JWT 验证附近未检测到受众验证证据。”
- “此 cookie 设置调用未设置 Secure。”
- “未找到 refresh token 轮换证据。”
除非有确定性证据证明,否则应避免使用诸如“身份验证绕过”之类缺乏依据的断言。
## CLI 概览
```
sessionscope init
sessionscope scan --path . --format markdown --output sessions.md
sessionscope scan --path . --include "src/**/*.ts" --exclude "**/*.test.ts" --format json --output sessions.json
sessionscope scan --path . --max-file-size 1000000
sessionscope explain FINDING_ID
sessionscope diff main...HEAD
sessionscope baseline create
```
JSON 报告是使用已记录在案的 schema 版本的机器可读清单。一份简明的 cookie 审计摘录如下所示:
```
{
"schema_version": "0.5.0",
"summary": {
"files_discovered": 1,
"files_scanned": 1,
"files_skipped": 0,
"diagnostics": []
},
"artifacts": [
{
"id": "artifact_...",
"artifact_type": "session_cookie",
"display_name": "session",
"locations": [{ "path": "src/app.ts", "line": 12, "column": 3 }],
"lifecycle_evidence": {
"issue": [],
"store": ["evidence_cookie_store"],
"transmit": ["evidence_cookie_secure"],
"validate": [],
"refresh": [],
"revoke": [],
"expire": [],
"introspect": []
},
"confidence": "high",
"framework_hints": ["express"],
"cookie_attributes": {
"http_only": {
"state": "missing",
"evidence_ids": ["evidence_cookie_http_only"],
"confidence": "high"
},
"secure": {
"state": "present",
"value": "true",
"evidence_ids": ["evidence_cookie_secure"],
"confidence": "high"
},
"same_site": {
"state": "present",
"value": "lax",
"evidence_ids": ["evidence_cookie_same_site"],
"confidence": "high"
},
"max_age": {
"state": "missing",
"evidence_ids": ["evidence_cookie_max_age"],
"confidence": "high"
},
"expires": {
"state": "missing",
"evidence_ids": ["evidence_cookie_expires"],
"confidence": "high"
},
"path": {
"state": "framework_default",
"value": "/",
"evidence_ids": ["evidence_cookie_path"],
"confidence": "low"
},
"domain": {
"state": "missing",
"evidence_ids": ["evidence_cookie_domain"],
"confidence": "high"
}
}
}
],
"evidence": [
{
"id": "evidence_cookie_store",
"lifecycle_stage": "store",
"location": { "path": "src/app.ts", "line": 12, "column": 3 },
"detector_id": "cookie.set",
"confidence": "high",
"excerpt": "response.cookie(\"session\", [REDACTED], ...)",
"dynamic": false,
"framework_default": false
}
],
"lifecycle_paths": [
{
"id": "lifecycle_path_...",
"artifact_ids": ["artifact_..."],
"stages": [
{
"stage": "store",
"evidence_ids": ["evidence_cookie_store"]
}
],
"confidence": "high",
"dynamic": false,
"reviewer_question": null
}
],
"findings": [
{
"id": "finding_...",
"category": "high_confidence_misconfiguration",
"severity": "high",
"artifact_ids": ["artifact_..."],
"evidence_ids": ["evidence_cookie_http_only"],
"title": "Session-like cookie `session` does not set HttpOnly",
"description": "No HttpOnly attribute evidence was detected for this cookie-setting call.",
"suggested_fix": "Set HttpOnly on session cookies so client-side scripts cannot read them.",
"reviewer_question": "Is this cookie intended to be inaccessible to browser JavaScript?"
}
],
"files": []
}
```
## GitHub Action 概览
```
name: SessionScope
on: [pull_request]
jobs:
sessionscope:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bjcorder/SessionScope@v0
with:
mode: advisory
output: markdown,sarif
```
## 配置
运行 `sessionscope init` 以创建一个可提交至版本控制的 `sessionscope.toml` 文件。该命令是非交互式的,不需要网络访问,并且在未传入 `--force` 参数的情况下拒绝覆盖现有配置。
初始化后的配置示例:
```
# SessionScope 配置
# 由 `sessionscope init` 生成。可安全提交。
# 请勿在此文件中放置 token 值、私钥、bearer 字符串、cookie 值或
# 特定环境的 secrets。
scan_paths = ["."]
include = ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx", "**/*.py", "**/*.json", "**/*.yaml", "**/*.yml", "**/*.toml"]
exclude = ["**/*.test.ts", "**/*.spec.ts", "**/__tests__/**"]
formats = ["markdown"]
mode = "advisory"
max_file_size_bytes = 1000000
framework_hints = ["express", "nextjs", "fastapi", "django"]
provider_hints = []
```
配置优先级依次为:
1. CLI 标志,例如 `--path`、`--include`、`--exclude`、`--format` 和 `--max-file-size`
2. `sessionscope.toml`
3. 内置默认值
`--include` 会替换已配置的包含模式,而 `--exclude` 则会追加到已配置的排除列表中。SessionScope 还会在实际可行的范围内遵循 `.gitignore` 规则,应用内置的 dependency/vendor/build 排除项,并在加载源代码之前跳过敏感路径(例如 env 文件和私钥材料)。
## 潜在检查项
- Cookie 缺少 `HttpOnly`
- Cookie 缺少 `Secure`
- 不安全或需要审查的 cookie 状态,包括生命周期过长、Domain/Path 作用域过宽以及 `SameSite=None` 的处理方式
- JWT 验证未进行颁发者验证
- JWT 验证未进行受众验证
- 颁发的 token 没有明确的过期时间
- Refresh token 缺少轮换证据
- 登出时缺少撤销证据
- 密码重置 token 缺少过期时间或一次性使用证据
- 会话固定风险信号
- 接受来自查询参数的 token
- 跨服务、环境或信任边界的 token 重用需要审查
## 非目标
SessionScope 不旨在:
- 利用身份验证系统
- 对 token 进行暴力破解
- 攻击正在运行的应用程序
- 窃取或解码机密信息
- 取代人工安全审查
## 开发
SessionScope 采用 Rust Cargo workspace 搭建脚手架,使用 Rust 2024 edition。在运行本地检查之前,请从 安装 stable Rust 工具链。
该 workspace 被拆分为多个专注的 crate,分别用于 CLI、核心扫描器 pipeline、共享模型、检测器、分类器、报告器和测试辅助工具。CLI 二进制文件命名为 `sessionscope`。
标准的本地检查命令:
```
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo check --workspace
cargo test --workspace --all-targets
```
开发过程中常用的 CLI 命令:
```
cargo run -p sessionscope-cli -- --help
cargo run -p sessionscope-cli -- version
cargo run -p sessionscope-cli -- scan --path . --format markdown
cargo run -p sessionscope-cli -- scan --path . --include "src/**/*.ts" --exclude "**/*.test.ts" --max-file-size 1000000 --format json
```
扫描器是防御性和纯离线运行的。请勿添加会打印 token 值、私钥、bearer 字符串、cookie 值或其他运行时机密信息的分析器行为。
## 脱敏信任边界
SessionScope 将源代码文本和检测器输出视为不受信任的内容,直到它们通过 `sessionscope-core::redaction` 处理。证据摘录和渲染后的报告应保留源码位置、发现结果 ID、生命周期阶段、声明名称和属性名称,但 token 值、cookie 值、bearer 字符串、私钥和高熵的类似机密字面量必须替换为 `[REDACTED]`。
脱敏是一种尽力而为的静态保护措施,不能保证任意源代码中都不包含机密。为了保持可审查性,稳定的 ID 和源码位置会被保留,且绝不能从运行时的 token 值、私钥、bearer 字符串、cookie 值或其他机密信息中生成。
## 状态
此代码库包含初始的产品文档和 Rust workspace 脚手架。目前 CLI、pipeline、检测器、分类器、报告器和测试辅助工具 crate 均已就绪,其中的检测器和分类器行为将在下一个里程碑中实现。
标签:API安全, AV绕过, CI/CD安全, Cookie安全, DevSecOps, Django, Express, FastAPI, JSON输出, JWT, Llama, LNA, Python, SAST, TypeScript, Web安全, 上游代理, 产品安全, 代码安全审计, 令牌生命周期, 会话安全, 可视化界面, 安全审查, 安全工程, 安全插件, 文档结构分析, 无后门, 盲注攻击, 蓝队分析, 通知系统, 防御加固, 静态应用安全测试