security-scan
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSecurity Scan
安全扫描
Core Principles
核心原则
-
Defense in depth — Scan multiple layers: packages, source code, configuration, and infrastructure. A project with zero CVEs can still have hardcoded secrets, SQL injection, and missing auth. Each layer catches different vulnerability classes.
-
Prioritize by exploitability — A Critical SQL injection in a public endpoint is more urgent than a Low-severity info disclosure in an admin-only page. Prioritize findings by: exploitability (how easy to exploit), impact (what an attacker gains), and exposure (public vs internal endpoint).
-
No false sense of security — This is static analysis, not a penetration test. It catches known patterns but misses business logic flaws, authorization bypass through complex flows, and runtime-only vulnerabilities. State this clearly in every report.
-
Actionable findings — Every issue includes severity, file and line, description of the vulnerability, impact if exploited, and specific remediation code. "Fix the security issue" is not a finding. "OrderController.cs:23 — Missingon
[Authorize]. Impact: unauthenticated users can delete orders. Fix: AddDELETE /orders/{id}" is.[Authorize(Policy = \"OrderAdmin\")] -
Follow OWASP Top 10 — Structure the scan around known vulnerability categories. The OWASP Top 10 is the industry baseline for web application security. Every finding should map to an OWASP category.
-
纵深防御 —— 扫描多个层面:包、源代码、配置和基础设施。没有CVE漏洞的项目仍可能存在硬编码密钥、SQL注入和缺失身份验证的问题。每个层面会检测不同类型的漏洞。
-
按可利用性优先级排序 —— 公共端点中的严重SQL注入比仅管理员页面中的低严重性信息泄露更紧急。按以下维度对检测结果排序:可利用性(攻击难度)、影响(攻击者可获得的权限)和暴露范围(公开端点 vs 内部端点)。
-
避免虚假安全感 —— 这是静态分析,而非渗透测试。它能检测已知模式,但会遗漏业务逻辑缺陷、复杂流程导致的授权绕过以及仅运行时存在的漏洞。需在每份报告中明确说明这一点。
-
可执行的检测结果 —— 每个问题都包含严重等级、文件及行号、漏洞描述、被利用后的影响,以及具体的修复代码。“修复安全问题”不属于有效检测结果,而“OrderController.cs:23 ——缺少
DELETE /orders/{id}。影响:未认证用户可删除订单。修复:添加[Authorize]”才是有效结果。[Authorize(Policy = "OrderAdmin")] -
遵循OWASP Top 10 —— 围绕已知漏洞类别构建扫描流程。OWASP Top 10是Web应用安全的行业基准,每个检测结果都应映射到一个OWASP类别。
Patterns
扫描模式
6-Layer Security Scan Pipeline
6层安全扫描流水线
Execute all 6 layers. Each produces findings rated Critical, High, Medium, or Low.
Layer 1: Package Vulnerabilities
bash
dotnet list package --vulnerable --include-transitiveCheck for known CVEs in direct and transitive dependencies.
Severity mapping:
- Critical: CVSS 9.0-10.0 — Remote code execution, authentication bypass
- High: CVSS 7.0-8.9 — Privilege escalation, data exposure
- Medium: CVSS 4.0-6.9 — Denial of service, information disclosure
- Low: CVSS 0.1-3.9 — Minor information leakage
Remediation pattern:
xml
<!-- BEFORE — vulnerable package -->
<PackageReference Include="System.Text.Json" Version="8.0.0" />
<!-- AFTER — patched version -->
<PackageReference Include="System.Text.Json" Version="10.0.0" />If a patch isn't available, document the risk and apply compensating controls.
Layer 2: Secrets Detection
Scan all , , , , , and files for hardcoded secrets.
.cs.json.yml.yaml.xml.configPatterns to detect:
HIGH-CONFIDENCE PATTERNS (almost always a real secret):
- "Password=" or "Pwd=" in connection strings outside appsettings.Development.json
- "Bearer " followed by a base64 token in source code
- "-----BEGIN PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"
- AWS: "AKIA" followed by 16 alphanumeric characters
- Azure: strings matching Azure Storage/Service Bus key patterns
MEDIUM-CONFIDENCE PATTERNS (need context to determine):
- "ApiKey", "Secret", "Token" as variable names with string literal assignments
- Base64-encoded strings longer than 40 characters in source code
- Connection strings with server addresses in non-Development config files
FALSE-POSITIVE INDICATORS (skip these):
- Values in appsettings.Development.json (development-only)
- Placeholder values: "your-key-here", "changeme", "TODO", empty strings
- Test fixtures with obviously fake values
- User secrets references: "UserSecretsId" in .csprojRemediation:
csharp
// BAD — hardcoded connection string
var connectionString = "Server=prod-db;Database=Orders;User=admin;Password=S3cret!";
// GOOD — configuration with user secrets / environment variables
var connectionString = builder.Configuration.GetConnectionString("OrdersDb");
// Store actual values in:
// - Development: dotnet user-secrets set "ConnectionStrings:OrdersDb" "..."
// - Production: Environment variable or Azure Key VaultLayer 3: OWASP Code Patterns
Scan source code for vulnerability patterns mapped to OWASP Top 10.
A03:2021 — Injection
Detect: String concatenation in SQL queries, raw SQL with user input
Pattern: FromSqlRaw($"SELECT * FROM Orders WHERE Id = '{userInput}'")
Fix: FromSqlInterpolated($"SELECT * FROM Orders WHERE Id = {userInput}")
or use parameterized queries / LINQ
A07:2021 — Cross-Site Scripting (XSS)
Detect: Raw HTML output without encoding in Razor/Blazor
Pattern: @Html.Raw(userInput)
Fix: Use Razor's default encoding (@userInput) or sanitize explicitly
A08:2021 — Insecure Deserialization
Detect: BinaryFormatter, JsonConvert with TypeNameHandling.All
Pattern: JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings
{ TypeNameHandling = TypeNameHandling.All })
Fix: Use System.Text.Json (no type name handling by default)
If Newtonsoft is required: TypeNameHandling.None + explicit type converters
A02:2021 — Cryptographic Failures
Detect: MD5, SHA1 for security purposes, ECB mode, hardcoded encryption keys
Pattern: MD5.Create().ComputeHash(...)
Fix: Use SHA256 minimum, prefer HMACSHA256 for authentication
Use AES-GCM for encryption, derive keys from passwords using Rfc2898DeriveBytes
A04:2021 — Insecure Direct Object References
Detect: Endpoints that use user-supplied IDs without ownership verification
Pattern: GET /orders/{id} — returns any order regardless of who owns it
Fix: Add ownership check: where o.Id == id && o.CustomerId == currentUser.IdLayer 4: Auth Configuration
Review authentication and authorization setup across the application.
CHECKLIST:
1. All endpoints have explicit auth attributes
- MCP: find_references(symbolName: "AllowAnonymous") — list deliberately public endpoints
- MCP: find_references(symbolName: "Authorize") — list protected endpoints
- Gap: endpoints with neither attribute (implicit policy depends on global config)
2. JWT validation settings are secure
- ValidateIssuer: true (prevents token from wrong issuer)
- ValidateAudience: true (prevents token meant for another app)
- ValidateLifetime: true (prevents expired tokens)
- ValidateIssuerSigningKey: true (prevents tampered tokens)
- ClockSkew: TimeSpan.FromMinutes(1) max (default 5 min is too generous)
3. Authorization policies are specific
- BAD: [Authorize] with no policy — just checks "is authenticated"
- GOOD: [Authorize(Policy = "OrderAdmin")] — role/claim-based authorization
4. No auth bypass patterns
- Middleware ordering: UseAuthentication() before UseAuthorization()
- No global AllowAnonymous that accidentally opens everything
- API key validation in middleware, not in each controllercsharp
// BAD — JWT configuration with weak validation
builder.Services.AddAuthentication().AddJwtBearer(options =>
{
options.TokenValidationParameters = new()
{
ValidateIssuer = false, // Anyone can issue tokens
ValidateAudience = false, // Token works for any app
ValidateLifetime = false, // Expired tokens accepted
IssuerSigningKey = new SymmetricSecurityKey(
"short-key"u8.ToArray()) // Key too short (< 256 bits)
};
});
// GOOD — secure JWT configuration
builder.Services.AddAuthentication().AddJwtBearer(options =>
{
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidateAudience = true,
ValidAudience = builder.Configuration["Jwt:Audience"],
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(1),
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Convert.FromBase64String(builder.Configuration["Jwt:Key"]!))
};
});Layer 5: CORS Configuration
Review Cross-Origin Resource Sharing policy for misconfigurations.
csharp
// CRITICAL — wildcard origin with credentials
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyOrigin() // Any website can call this API
.AllowCredentials(); // ...and send cookies/auth headers
// This is a security vulnerability — browsers block this combo,
// but it signals a misunderstanding of CORS
});
});
// HIGH — wildcard origin without credentials
policy.AllowAnyOrigin() // Any website can read API responses
.AllowAnyHeader()
.AllowAnyMethod();
// Acceptable ONLY for truly public APIs (e.g., public data feeds)
// GOOD — explicit origins
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins(
builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>()!)
.AllowCredentials()
.WithMethods("GET", "POST", "PUT", "DELETE")
.WithHeaders("Content-Type", "Authorization");
});
});Check for:
- Wildcard origins () — should be restricted to specific domains
AllowAnyOrigin - Exposed headers that leak internal information
- Overly broad methods (allowing PATCH, OPTIONS when only GET/POST needed)
- CORS in development vs production — different policies for different environments
Layer 6: Data Protection
Scan for PII and sensitive data handling issues.
CHECKS:
1. PII in logs — email, phone, SSN, credit card in logging statements
Pattern: logger.LogInformation("User {Email} placed order", user.Email)
Fix: logger.LogInformation("User {UserId} placed order", user.Id)
Rule: Log identifiers (IDs), not identity data (email, name, phone)
2. Sensitive data in responses — returning more data than needed
Pattern: Returning full User entity (with password hash) from an endpoint
Fix: Use a response DTO that excludes sensitive fields
3. Missing Data Protection API — storing sensitive data without encryption
Pattern: Storing API keys as plain text in the database
Fix: Use IDataProtector to encrypt before storage
4. Unencrypted sensitive configuration — secrets in appsettings.json
Pattern: "SmtpPassword": "actualpassword" in appsettings.json
Fix: Use user secrets (dev), Key Vault (prod), or environment variablescsharp
// BAD — PII in logs
logger.LogInformation("Order placed by {Email} for {CreditCard}",
order.CustomerEmail, order.PaymentCard);
// GOOD — identifiers only
logger.LogInformation("Order {OrderId} placed by customer {CustomerId}",
order.Id, order.CustomerId);执行全部6个层面的扫描,每个层面都会生成标记为严重、高、中或低等级的检测结果。
第一层:包漏洞
bash
dotnet list package --vulnerable --include-transitive检查直接和间接依赖项中的已知CVE漏洞。
严重等级映射:
- 严重:CVSS 9.0-10.0 —— 远程代码执行、身份验证绕过
- 高:CVSS 7.0-8.9 —— 权限提升、数据暴露
- 中:CVSS 4.0-6.9 —— 拒绝服务、信息泄露
- 低:CVSS 0.1-3.9 —— 轻微信息泄露
修复示例:
xml
<!-- 修复前 —— 存在漏洞的包 -->
<PackageReference Include="System.Text.Json" Version="8.0.0" />
<!-- 修复后 —— 已打补丁的版本 -->
<PackageReference Include="System.Text.Json" Version="10.0.0" />如果暂无补丁,需记录风险并应用补偿控制措施。
第二层:密钥检测
扫描所有 、、、、 和 文件中的硬编码密钥。
.cs.json.yml.yaml.xml.config需检测的模式:
高置信度模式(几乎都是真实密钥):
- appsettings.Development.json 之外的连接字符串中包含 "Password=" 或 "Pwd="
- 源代码中 "Bearer " 后跟base64令牌
- "-----BEGIN PRIVATE KEY-----" 或 "-----BEGIN RSA PRIVATE KEY-----"
- AWS:"AKIA" 后跟16位字母数字字符
- Azure:匹配Azure存储/服务总线密钥模式的字符串
中置信度模式(需结合上下文判断):
- 变量名为 "ApiKey"、"Secret"、"Token" 且赋值为字符串字面量
- 源代码中长度超过40字符的base64编码字符串
- 非开发配置文件中包含服务器地址的连接字符串
误报标识(跳过这些):
- appsettings.Development.json 中的值(仅用于开发环境)
- 占位符值:"your-key-here"、"changeme"、"TODO"、空字符串
- 明显为假值的测试夹具
- .csproj 中的用户密钥引用:"UserSecretsId"修复示例:
csharp
// 不良示例 —— 硬编码连接字符串
var connectionString = "Server=prod-db;Database=Orders;User=admin;Password=S3cret!";
// 良好示例 —— 使用用户密钥/环境变量配置
var connectionString = builder.Configuration.GetConnectionString("OrdersDb");
// 实际值存储位置:
// - 开发环境:dotnet user-secrets set "ConnectionStrings:OrdersDb" "..."
// - 生产环境:环境变量或Azure Key Vault第三层:OWASP代码模式
扫描源代码中映射到OWASP Top 10的漏洞模式。
A03:2021 —— 注入
检测:SQL查询中的字符串拼接、包含用户输入的原生SQL
模式:FromSqlRaw($"SELECT * FROM Orders WHERE Id = '{userInput}'")
修复:使用FromSqlInterpolated($"SELECT * FROM Orders WHERE Id = {userInput}")
或使用参数化查询/LINQ
A07:2021 —— 跨站脚本(XSS)
检测:Razor/Blazor中未编码的原始HTML输出
模式:@Html.Raw(userInput)
修复:使用Razor默认编码(@userInput)或显式清理
A08:2021 —— 不安全的反序列化
检测:BinaryFormatter、设置TypeNameHandling.All的JsonConvert
模式:JsonConvert.DeserializeObject<T>(json, new JsonSerializerSettings
{ TypeNameHandling = TypeNameHandling.All })
修复:使用System.Text.Json(默认无类型名称处理)
如果必须使用Newtonsoft:设置TypeNameHandling.None + 显式类型转换器
A02:2021 —— 加密失败
检测:用于安全场景的MD5、SHA1,ECB模式,硬编码加密密钥
模式:MD5.Create().ComputeHash(...)
修复:至少使用SHA256,优先选择HMACSHA256进行身份验证
使用AES-GCM进行加密,通过Rfc2898DeriveBytes从密码派生密钥
A04:2021 —— 不安全的直接对象引用
检测:使用用户提供的ID但未验证所有权的端点
模式:GET /orders/{id} —— 返回任意订单,无论归属
修复:添加所有权检查:where o.Id == id && o.CustomerId == currentUser.Id第四层:身份验证配置
审查应用中的身份验证和授权设置。
检查清单:
1. 所有端点都有明确的身份验证属性
- MCP: find_references(symbolName: "AllowAnonymous") —— 列出故意公开的端点
- MCP: find_references(symbolName: "Authorize") —— 列出受保护的端点
- 缺口:既无AllowAnonymous也无Authorize属性的端点(隐式策略取决于全局配置)
2. JWT验证设置安全
- ValidateIssuer: true(防止来自错误发行方的令牌)
- ValidateAudience: true(防止令牌被用于其他应用)
- ValidateLifetime: true(防止过期令牌)
- ValidateIssuerSigningKey: true(防止被篡改的令牌)
- ClockSkew: 最大TimeSpan.FromMinutes(1)(默认5分钟过于宽松)
3. 授权策略具体明确
- 不良示例:无策略的 [Authorize] —— 仅检查“是否已认证”
- 良好示例:[Authorize(Policy = "OrderAdmin")] —— 基于角色/声明的授权
4. 无身份验证绕过模式
- 中间件顺序:UseAuthentication() 在 UseAuthorization() 之前
- 无全局AllowAnonymous意外开放所有端点
- API密钥验证在中间件中实现,而非每个控制器csharp
// 不良示例 —— JWT配置验证较弱
builder.Services.AddAuthentication().AddJwtBearer(options =>
{
options.TokenValidationParameters = new()
{
ValidateIssuer = false, // 任意发行方都可颁发令牌
ValidateAudience = false, // 令牌可用于任意应用
ValidateLifetime = false, // 接受过期令牌
IssuerSigningKey = new SymmetricSecurityKey(
"short-key"u8.ToArray()) // 密钥过短(<256位)
};
});
// 良好示例 —— 安全的JWT配置
builder.Services.AddAuthentication().AddJwtBearer(options =>
{
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidateAudience = true,
ValidAudience = builder.Configuration["Jwt:Audience"],
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(1),
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(
Convert.FromBase64String(builder.Configuration["Jwt:Key"]!))
};
});第五层:CORS配置
审查跨域资源共享(CORS)策略的配置错误。
csharp
// 严重风险 —— 通配符源+凭据支持
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyOrigin() // 任意网站都可调用此API
.AllowCredentials(); // ...并发送Cookie/身份验证头
// 这是安全漏洞 —— 浏览器会阻止这种组合,
// 但表明对CORS存在误解
});
});
// 高风险 —— 无凭据的通配符源
policy.AllowAnyOrigin() // 任意网站都可读取API响应
.AllowAnyHeader()
.AllowAnyMethod();
// 仅适用于真正的公开API(如公共数据feed)
// 良好示例 —— 明确指定源
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.WithOrigins(
builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>()!)
.AllowCredentials()
.WithMethods("GET", "POST", "PUT", "DELETE")
.WithHeaders("Content-Type", "Authorization");
});
});检查要点:
- 通配符源()—— 应限制为特定域名
AllowAnyOrigin - 泄露内部信息的暴露头
- 过于宽泛的方法(仅需GET/POST时允许PATCH、OPTIONS)
- 开发环境与生产环境的CORS策略差异
第六层:数据保护
扫描PII(个人可识别信息)和敏感数据处理问题。
检查项:
1. 日志中的PII —— 日志语句中的邮箱、电话、社保号、信用卡信息
模式:logger.LogInformation("User {Email} placed order", user.Email)
修复:logger.LogInformation("User {UserId} placed order", user.Id)
规则:记录标识符(ID),而非身份数据(邮箱、姓名、电话)
2. 响应中的敏感数据 —— 返回超出需求的数据
模式:从端点返回完整的User实体(包含密码哈希)
修复:使用排除敏感字段的响应DTO
3. 缺失数据保护API —— 未加密存储敏感数据
模式:在数据库中明文存储API密钥
修复:使用IDataProtector在存储前加密
4. 未加密的敏感配置 —— appsettings.json中的密钥
模式:appsettings.json中包含 "SmtpPassword": "actualpassword"
修复:使用用户密钥(开发环境)、Key Vault(生产环境)或环境变量csharp
// 不良示例 —— 日志中包含PII
logger.LogInformation("Order placed by {Email} for {CreditCard}",
order.CustomerEmail, order.PaymentCard);
// 良好示例 —— 仅记录标识符
logger.LogInformation("Order {OrderId} placed by customer {CustomerId}",
order.Id, order.CustomerId);Full Scan Report
完整扫描报告
Each finding uses format: with OWASP Category, Description, Impact, and Remediation (with code before/after).
#### [SEVERITY] File:Line — Titlemarkdown
undefined每个检测结果格式为:,包含OWASP类别、描述、影响和修复方案(含修复前后代码)。
#### [严重等级] 文件:行号 —— 标题markdown
undefinedSecurity Scan Report
安全扫描报告
Project: MyApp | Date: 2026-03-04 | Scanner: Claude (static analysis)
This is a static analysis scan. It catches known patterns but does not replace penetration testing, dynamic analysis, or threat modeling.
项目: MyApp | 日期: 2026-03-04 | 扫描器: Claude(静态分析)
这是静态分析扫描。它能检测已知模式,但不能替代 渗透测试、动态分析或威胁建模。
Summary
摘要
| Severity | Count |
|---|---|
| Critical | 0 |
| High | 2 |
| Medium | 3 |
| Low | 1 |
| 严重等级 | 数量 |
|---|---|
| 严重 | 0 |
| 高 | 2 |
| 中 | 3 |
| 低 | 1 |
Findings
检测结果
[HIGH] src/Orders/Features/SearchOrders.cs:34 — SQL Injection
[高] src/Orders/Features/SearchOrders.cs:34 —— SQL注入
...
...
[HIGH] src/Api/Program.cs:12 — Missing Authorization on DELETE endpoint
[高] src/Api/Program.cs:12 —— DELETE端点缺失授权
...
...
Layer Results
各层结果
| Layer | Status | Findings |
|---|---|---|
| 1. Package Vulnerabilities | PASS | 0 CVEs |
| 2. Secrets Detection | PASS | No hardcoded secrets |
| 3. OWASP Code Patterns | FAIL | 1 SQL injection, 1 insecure deserialization |
| 4. Auth Configuration | WARN | 2 endpoints missing explicit auth |
| 5. CORS Configuration | PASS | Origins properly restricted |
| 6. Data Protection | WARN | PII found in 2 log statements |
undefined| 层面 | 状态 | 检测结果数量 |
|---|---|---|
| 1. 包漏洞 | 通过 | 0个CVE |
| 2. 密钥检测 | 通过 | 无硬编码密钥 |
| 3. OWASP代码模式 | 失败 | 1个SQL注入,1个不安全反序列化 |
| 4. 身份验证配置 | 警告 | 2个端点缺失明确身份验证 |
| 5. CORS配置 | 通过 | 源已正确限制 |
| 6. 数据保护 | 警告 | 2条日志语句中存在PII |
undefinedAnti-patterns
反模式
Only Scanning Packages
仅扫描包
undefinedundefinedBAD — NuGet packages are clean, declare victory
不良示例 —— NuGet包无漏洞就宣称胜利
dotnet list package --vulnerable → "No vulnerable packages found"
"Security scan passed!"
dotnet list package --vulnerable → "未发现易受攻击的包"
"安全扫描通过!"
Missed: hardcoded password in appsettings.json, SQL injection in SearchOrders,
遗漏:appsettings.json中的硬编码密码、SearchOrders中的SQL注入、
missing [Authorize] on 3 endpoints, PII in logs
3个端点缺失[Authorize]、日志中的PII
GOOD — all 6 layers for complete coverage
良好示例 —— 扫描全部6层以获得完整覆盖
Layer 1 (Packages): PASS
Layer 2 (Secrets): Found connection string in appsettings.Production.json
Layer 3 (OWASP): SQL injection in SearchOrders.cs:34
Layer 4 (Auth): 3 endpoints without [Authorize]
Layer 5 (CORS): Wildcard origin in production config
Layer 6 (Data): Customer email logged at Information level
undefined第一层(包):通过
第二层(密钥):在appsettings.Production.json中发现连接字符串
第三层(OWASP):SearchOrders.cs:34存在SQL注入
第四层(身份验证):3个端点无[Authorize]
第五层(CORS):生产环境配置中存在通配符源
第六层(数据):客户邮箱被记录在信息级别日志中
undefinedEverything is Critical
所有问题都标记为严重
undefinedundefinedBAD — alert fatigue from over-classification
不良示例 —— 过度分类导致警报疲劳
[CRITICAL] Missing XML comment on public method
[CRITICAL] Using var instead of explicit type
[CRITICAL] Connection string in appsettings.Development.json
[严重] 公共方法缺失XML注释
[严重] 使用var而非显式类型
[严重] appsettings.Development.json中存在连接字符串
GOOD — severity matches actual risk
良好示例 —— 严重等级匹配实际风险
[LOW] Missing XML comment on public method (not a security issue)
[INFO] appsettings.Development.json has connection string (expected for dev)
[HIGH] appsettings.Production.json has hardcoded password (real secret exposure)
undefined[低] 公共方法缺失XML注释(非安全问题)
[信息] appsettings.Development.json包含连接字符串(开发环境预期情况)
[高] appsettings.Production.json存在硬编码密码(真实密钥暴露)
undefinedScanning Without Context
无上下文扫描
undefinedundefinedBAD — flagging test fixtures as security issues
不良示例 —— 将测试夹具标记为安全问题
[HIGH] Tests/OrderTests.cs:15 — Hardcoded API key: "test-key-12345"
[高] Tests/OrderTests.cs:15 —— 硬编码API密钥:"test-key-12345"
This is a test fixture with a fake value, not a real secret
这是测试夹具中的假值,不是真实密钥
GOOD — context-aware scanning
良好示例 —— 上下文感知扫描
Skip files in test projects for secret detection (test data is expected to be fake).
Flag only if the pattern matches a real secret format (e.g., starts with "AKIA" for AWS).
undefined跳过测试项目的密钥检测(测试数据预期为假值)。
仅当模式匹配真实密钥格式时才标记(如AWS密钥以"AKIA"开头)。
undefinedNo Remediation Steps
无修复步骤
undefinedundefinedBAD — finding without a fix
不良示例 —— 无修复方案的检测结果
[HIGH] SQL Injection in SearchOrders.cs:34
"Fix this."
[高] SearchOrders.cs:34存在SQL注入
"修复此问题。"
GOOD — finding with specific remediation
良好示例 —— 带具体修复方案的检测结果
[HIGH] SQL Injection in SearchOrders.cs:34
Current: FromSqlRaw($"SELECT * FROM Orders WHERE Name LIKE '%{search}%'")
Fix: Use parameterized query:
db.Orders.Where(o => EF.Functions.Like(o.Name, $"%{search}%"))
Impact: Attacker can read/modify/delete any data in the database.
undefined[高] SearchOrders.cs:34存在SQL注入
当前代码:FromSqlRaw($"SELECT * FROM Orders WHERE Name LIKE '%{search}%'")
修复:使用参数化查询:
db.Orders.Where(o => EF.Functions.Like(o.Name, $"%{search}%"))
影响:攻击者可读取/修改/删除数据库中的任意数据。
undefinedDecision Guide
决策指南
| Scenario | Layers | Notes |
|---|---|---|
| Pre-release security gate | All 6 | Full scan, non-negotiable before production |
| After dependency update | 1 | Package vulnerabilities only |
| New endpoint added | 3, 4, 5 | OWASP, auth, CORS for the new endpoint |
| Auth system changes | 4 | Deep auth configuration review |
| Config file changes | 2 | Secrets detection in changed configs |
| Logging changes | 6 | Check for PII in new log statements |
| Pre-pentest preparation | All 6 | Fix static issues before paying for a pentest |
| Incident response | All 6 | Full scan after a security incident |
| Quarterly security review | All 6 | Regular cadence, also useful for onboarding |
| Public API exposure | 3, 4, 5 | Focus on external attack surface |
| Internal service | 1, 2, 3 | Lower CORS/auth scrutiny if truly internal |
| 场景 | 扫描层面 | 说明 |
|---|---|---|
| 预发布安全网关 | 全部6层 | 生产前必须完成完整扫描 |
| 依赖更新后 | 第1层 | 仅扫描包漏洞 |
| 添加新端点后 | 第3、4、5层 | 针对新端点扫描OWASP、身份验证、CORS |
| 身份验证系统变更后 | 第4层 | 深度审查身份验证配置 |
| 配置文件变更后 | 第2层 | 扫描变更配置中的密钥 |
| 日志变更后 | 第6层 | 检查新日志语句中的PII |
| 渗透测试准备前 | 全部6层 | 支付渗透测试费用前修复静态问题 |
| 事件响应后 | 全部6层 | 安全事件后完成完整扫描 |
| 季度安全审查 | 全部6层 | 定期执行,也适用于新员工入职培训 |
| 公开API暴露 | 第3、4、5层 | 重点关注外部攻击面 |
| 内部服务 | 第1、2、3层 | 若确为内部服务,可降低CORS/身份验证审查严格度 |