GrantTrace 审计报告

目标:http://127.0.0.1:59519
生成时间:2026-10-13 22:54:53 +0800
v2.5.3
规范端点
5
确认漏洞
2
扫描错误
0
结论不确定
0
尝试覆盖率
100.0%
确定性覆盖率
100.0%

端点按 HTTP 方法与规范路径的组合计数;结果记录数可以多于端点数。尝试覆盖率按至少尝试一次 HTTP 请求的端点计算,包含网络失败;请求前的安全拦截、配置或参数失败不算请求尝试。确定性覆盖率仅计 CONFIRMED、SECURE、PUBLIC 和 AUTHORIZED,SUSPICIOUS 与 INCONCLUSIVE 不计入。两种覆盖率均以全部规范端点为分母,确认漏洞数量不代表检测成功率。本次尝试端点 5/5,确定性端点 5/5。

检查结果记录 5 条(包含单独记录的恢复核验结果);已尝试的主检查 5 条,确定性主检查 5 条。

CONFIRMED: 2 · SECURE: 2 · PUBLIC: 1 · AUTHORIZED: 0 · SUSPICIOUS: 0 · INCONCLUSIVE: 0 · SKIPPED: 0 · ERROR: 0

端点结果 5/5 条 · 确认漏洞 2/2 条

端点结果

结论检查端点访问与变化说明
SECUREBOLAGET /api/documents/{doc_uuid}

Visitor 身份访问配置为 Owner 的资源:http://127.0.0.1:59519/api/documents/550e8400-e29b-41d4-a716-446655440000。

本次对照显示未授权身份的访问被拒绝;结论仅限所测身份和资源。

执行分类:已完成有效检查并获得确定结论 · 请求尝试:4 次。

依据:访客跨资源请求与匿名请求均被明确拒绝且正文无业务数据:HTTP 鉴权拒绝状态码 403

修复方向、复验步骤和证据

修复方向:服务端按当前登录身份校验资源归属、团队共享和管理员权限;未获授权时拒绝返回资源数据。

安全复验步骤
  1. 在测试环境准备 Owner、Visitor 两个独立账户和各自的有效资源;先明确各身份按业务策略应被允许还是拒绝。
  2. 分别用 Owner、Visitor 和 Anonymous 读取 Owner 的同一资源,核对允许与拒绝结果及响应数据。凭据从本地安全配置加载。
  3. 同时验证 Visitor 可访问自身资源,以及合法团队共享、管理员访问按策略成功;重新扫描并比较结论。
{
  "requests_attempted": 4,
  "target_url": "http://127.0.0.1:59519/api/documents/550e8400-e29b-41d4-a716-446655440000",
  "visitor_self_url": "http://127.0.0.1:59519/api/documents/7d444840-9dc0-11d1-b245-5ffdce74fad2",
  "owner": {
    "status": 200,
    "body": "{\"content\": \"[REDACTED]\", \"id\": \"550e8400-e29b-41d4-a716-446655440000\", \"owner_id\": \"1001\", \"title\": \"[REDACTED]\"}",
    "sha256": "b93942ad955470a72b38f87a4b9e353caadac44614e4ab79ad6fcf3cfd0d8b52",
    "truncated": false,
    "error": null
  },
  "visitor_cross": {
    "status": 403,
    "body": "{\"code\": 403, \"error\": \"Forbidden\"}",
    "sha256": "8b0a6238de200b26459309970c3539c86a387fe04c6cd953bb31fc13474e6670",
    "truncated": false,
    "error": null
  },
  "anonymous": {
    "status": 401,
    "body": "{\"code\": 401, \"error\": \"Unauthorized\"}",
    "sha256": "2f67a496c42e029b18142f8153e3cb599c5402f3df237fdd05b95f937e6ede3a",
    "truncated": false,
    "error": null
  },
  "visitor_self": {
    "status": 200,
    "body": "{\"content\": \"[REDACTED]\", \"id\": \"7d444840-9dc0-11d1-b245-5ffdce74fad2\", \"owner_id\": \"1002\", \"title\": \"[REDACTED]\"}",
    "sha256": "5adef504266413baea03b6097afeabdee0195487b06e79343216476c12d1df69",
    "truncated": false,
    "error": null
  },
  "metrics": {
    "confidence": 1.0,
    "similarity": 0.0
  },
  "decision_evidence": {
    "responses": {
      "owner": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "visitor_cross": {
        "kind": "AUTH_DENIED",
        "status_code": 403,
        "is_auth_denial": true,
        "reason": "HTTP 鉴权拒绝状态码 403"
      },
      "anonymous": {
        "kind": "AUTH_DENIED",
        "status_code": 401,
        "is_auth_denial": true,
        "reason": "HTTP 鉴权拒绝状态码 401"
      },
      "visitor_self": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      }
    },
    "anonymous_denied": true,
    "anonymous_exact_match": false,
    "anonymous_value_similarity": 0.0,
    "structure_similarity": 0.0,
    "value_similarity": 0.0,
    "exact_value_match": false,
    "owner_meaningful_value_count": 2,
    "visitor_meaningful_value_count": 0,
    "shared_value_count": 0,
    "owner_specific_shared_value_count": 0,
    "owner_specific_shared_value_paths": [],
    "shared_resource_identifier_count": 0,
    "shared_resource_identifier_paths": [],
    "owner_only_shared_resource_identifier_count": 0,
    "owner_only_shared_resource_identifier_paths": [],
    "visitor_self_provided": true,
    "visitor_self_exact_match": false,
    "visitor_self_value_similarity": 0.0,
    "visitor_self_shared_resource_identifier_count": 0,
    "owner_baseline_valid": true,
    "visitor_cross_baseline_valid": false,
    "visitor_self_baseline_valid": true,
    "owner_self_distinct": true,
    "object_access_signals": [],
    "confirmation_signals": [],
    "expected_public": false,
    "requires_auth": true,
    "trusted_resource_id_paths": [
      "id"
    ],
    "denial_body_conflict": false,
    "visitor_denial_body_clean": true,
    "anonymous_denial_body_clean": true,
    "anonymous_authentication_violation": false,
    "anonymous_owner_value_match": false,
    "anonymous_owner_identifier_match": false,
    "owner_shared_nonpublic_value_paths": [],
    "missing_evidence": [],
    "expected_visitor_access": "deny",
    "policy_scope": "Configured Owner/Visitor identities and selected resource pair only"
  },
  "reason_category": "conclusive"
}
CONFIRMEDBOLAGET /api/users/{user_id}/profile

Visitor 身份访问配置为 Owner 的资源:http://127.0.0.1:59519/api/users/1001/profile。

已确认对象级越权:双方响应的业务值一致;双方响应存在较高的非公开业务值重合。

执行分类:已完成有效检查并获得确定结论 · 请求尝试:4 次。

依据:匿名请求被明确拒绝,而未授权访客获得了与所有者资源一致的具体值或资源标识。

修复方向、复验步骤和证据

修复方向:服务端按当前登录身份校验资源归属、团队共享和管理员权限;未获授权时拒绝返回资源数据。

安全复验步骤
  1. 在测试环境准备 Owner、Visitor 两个独立账户和各自的有效资源;先明确各身份按业务策略应被允许还是拒绝。
  2. 分别用 Owner、Visitor 和 Anonymous 读取 Owner 的同一资源,核对允许与拒绝结果及响应数据。凭据从本地安全配置加载。
  3. 同时验证 Visitor 可访问自身资源,以及合法团队共享、管理员访问按策略成功;重新扫描并比较结论。
{
  "requests_attempted": 4,
  "target_url": "http://127.0.0.1:59519/api/users/1001/profile",
  "visitor_self_url": "http://127.0.0.1:59519/api/users/1002/profile",
  "owner": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1001\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "bef2104fbbc72d3fa3cae9524eb0dd5d3a7d29460d7f5709f2d7c14fe2a10ea9",
    "truncated": false,
    "error": null
  },
  "visitor_cross": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1001\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "bef2104fbbc72d3fa3cae9524eb0dd5d3a7d29460d7f5709f2d7c14fe2a10ea9",
    "truncated": false,
    "error": null
  },
  "anonymous": {
    "status": 401,
    "body": "{\"code\": 401, \"error\": \"Authentication required\"}",
    "sha256": "47a5198d709698ac15790fa7ac68c8ab6e4ce1eaeab7a421c22b69e5d07949cd",
    "truncated": false,
    "error": null
  },
  "visitor_self": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "01200488fa4628c0bfa9830d04748bdca682787072cbf1a44d73600872847e2e",
    "truncated": false,
    "error": null
  },
  "metrics": {
    "confidence": 0.99,
    "similarity": 1.0
  },
  "decision_evidence": {
    "responses": {
      "owner": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "visitor_cross": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "anonymous": {
        "kind": "AUTH_DENIED",
        "status_code": 401,
        "is_auth_denial": true,
        "reason": "HTTP 鉴权拒绝状态码 401"
      },
      "visitor_self": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      }
    },
    "anonymous_denied": true,
    "anonymous_exact_match": false,
    "anonymous_value_similarity": 0.0,
    "structure_similarity": 1.0,
    "value_similarity": 1.0,
    "exact_value_match": true,
    "owner_meaningful_value_count": 4,
    "visitor_meaningful_value_count": 4,
    "shared_value_count": 4,
    "owner_specific_shared_value_count": 3,
    "owner_specific_shared_value_paths": [
      "department",
      "name",
      "salary"
    ],
    "shared_resource_identifier_count": 0,
    "shared_resource_identifier_paths": [],
    "owner_only_shared_resource_identifier_count": 0,
    "owner_only_shared_resource_identifier_paths": [],
    "visitor_self_provided": true,
    "visitor_self_exact_match": false,
    "visitor_self_value_similarity": 0.142857,
    "visitor_self_shared_resource_identifier_count": 0,
    "owner_baseline_valid": true,
    "visitor_cross_baseline_valid": true,
    "visitor_self_baseline_valid": true,
    "owner_self_distinct": true,
    "object_access_signals": [
      "exact_business_value_match",
      "high_business_value_overlap"
    ],
    "confirmation_signals": [
      "exact_business_value_match",
      "high_business_value_overlap"
    ],
    "expected_public": false,
    "requires_auth": true,
    "trusted_resource_id_paths": [],
    "denial_body_conflict": false,
    "visitor_denial_body_clean": null,
    "anonymous_denial_body_clean": true,
    "anonymous_authentication_violation": false,
    "anonymous_owner_value_match": false,
    "anonymous_owner_identifier_match": false,
    "owner_shared_nonpublic_value_paths": [
      "department",
      "name",
      "role",
      "salary"
    ],
    "missing_evidence": [],
    "expected_visitor_access": "deny",
    "policy_scope": "Configured Owner/Visitor identities and selected resource pair only"
  },
  "reason_category": "conclusive"
}
PUBLICBOLAGET /api/public/articles/{article_id}

Visitor 身份访问配置为 Owner 的资源:http://127.0.0.1:59519/api/public/articles/101。

本次结果为按配置允许公开访问,请核对该资源的公开范围。

执行分类:已完成有效检查并获得确定结论 · 请求尝试:3 次。

依据:端点显式配置为公开,所有者、访客与匿名响应的完整 JSON 数据完全一致。

修复方向、复验步骤和证据

修复方向:服务端按当前登录身份校验资源归属、团队共享和管理员权限;未获授权时拒绝返回资源数据。

安全复验步骤
  1. 在测试环境准备 Owner、Visitor 两个独立账户和各自的有效资源;先明确各身份按业务策略应被允许还是拒绝。
  2. 分别用 Owner、Visitor 和 Anonymous 读取 Owner 的同一资源,核对允许与拒绝结果及响应数据。凭据从本地安全配置加载。
  3. 同时验证 Visitor 可访问自身资源,以及合法团队共享、管理员访问按策略成功;重新扫描并比较结论。
{
  "requests_attempted": 3,
  "target_url": "http://127.0.0.1:59519/api/public/articles/101",
  "visitor_self_url": null,
  "owner": {
    "status": 200,
    "body": "{\"author\": \"Security Team\", \"id\": 101, \"public\": true, \"title\": \"[REDACTED]\"}",
    "sha256": "c4bd14501a490beafb21b04c96e74eabce3f2526220bda155306100bd9875a0c",
    "truncated": false,
    "error": null
  },
  "visitor_cross": {
    "status": 200,
    "body": "{\"author\": \"Security Team\", \"id\": 101, \"public\": true, \"title\": \"[REDACTED]\"}",
    "sha256": "c4bd14501a490beafb21b04c96e74eabce3f2526220bda155306100bd9875a0c",
    "truncated": false,
    "error": null
  },
  "anonymous": {
    "status": 200,
    "body": "{\"author\": \"Security Team\", \"id\": 101, \"public\": true, \"title\": \"[REDACTED]\"}",
    "sha256": "c4bd14501a490beafb21b04c96e74eabce3f2526220bda155306100bd9875a0c",
    "truncated": false,
    "error": null
  },
  "metrics": {
    "confidence": 1.0,
    "similarity": 1.0
  },
  "decision_evidence": {
    "responses": {
      "owner": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "visitor_cross": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "anonymous": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "visitor_self": null
    },
    "anonymous_denied": false,
    "anonymous_exact_match": true,
    "anonymous_value_similarity": 1.0,
    "structure_similarity": 1.0,
    "value_similarity": 1.0,
    "exact_value_match": true,
    "owner_meaningful_value_count": 3,
    "visitor_meaningful_value_count": 3,
    "shared_value_count": 3,
    "owner_specific_shared_value_count": 3,
    "owner_specific_shared_value_paths": [
      "author",
      "public",
      "title"
    ],
    "shared_resource_identifier_count": 0,
    "shared_resource_identifier_paths": [],
    "owner_only_shared_resource_identifier_count": 0,
    "owner_only_shared_resource_identifier_paths": [],
    "visitor_self_provided": false,
    "visitor_self_exact_match": false,
    "visitor_self_value_similarity": 0.0,
    "visitor_self_shared_resource_identifier_count": 0,
    "owner_baseline_valid": true,
    "visitor_cross_baseline_valid": true,
    "visitor_self_baseline_valid": false,
    "owner_self_distinct": false,
    "object_access_signals": [],
    "confirmation_signals": [],
    "expected_public": true,
    "requires_auth": false,
    "trusted_resource_id_paths": [],
    "denial_body_conflict": false,
    "visitor_denial_body_clean": null,
    "anonymous_denial_body_clean": null,
    "anonymous_authentication_violation": false,
    "anonymous_owner_value_match": true,
    "anonymous_owner_identifier_match": false,
    "owner_shared_nonpublic_value_paths": [],
    "missing_evidence": [],
    "expected_visitor_access": "deny",
    "policy_scope": "Configured Owner/Visitor identities and selected resource pair only"
  },
  "reason_category": "conclusive"
}
CONFIRMEDMASS_ASSIGNMENTPATCH /api/users/{user_id}/settings

写入检查:Visitor 提交字段 role;测试资源:http://127.0.0.1:59519/api/users/1002/settings。

独立读回确认该字段的测试值已持久保存。原状态已通过读回核验。

执行分类:已完成有效检查并获得确定结论 · 请求尝试:5 次。

依据:Privilege field 'role' persisted after mutation

修复方向、复验步骤和证据

修复方向:为当前身份明确允许更新的字段;在服务端拒绝或忽略权限、角色等未授权字段,并按业务策略校验更新权限。

安全复验步骤
  1. 仅在可恢复的测试资源上复验;先保存完整原状态,确认独立读回和恢复路径可用。恢复未核验时先处理恢复问题。
  2. 用 Visitor 提交该字段的最小测试修改,再由独立读取接口核对持久状态;未授权字段应保持原值,允许更新的字段应正常工作。
  3. 恢复原状态并再次读取核验;若结果不一致或无法核验,暂停后续写入测试并人工恢复。
{
  "field": "role",
  "readback_field": "role",
  "target_url": "http://127.0.0.1:59519/api/users/1002/settings",
  "readback_url": "http://127.0.0.1:59519/api/users/1002/profile",
  "request_content_type": "application/json",
  "snapshot_fields": [
    "role"
  ],
  "verification_scope": "Full readback document except explicitly ignored volatile paths",
  "ignored_readback_paths": [],
  "mutation": {
    "status": 200,
    "body": "{\"data\": {\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"admin\", \"salary\": \"[REDACTED]\"}, \"status\": \"success\"}",
    "sha256": "5c51f4b94305bb140842fbcb4b4b12ab45fc5dd84c42031a1bdbd7f594a9b1e4",
    "truncated": false,
    "error": null
  },
  "after": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"admin\", \"salary\": \"[REDACTED]\"}",
    "sha256": "22218090e97259835a63a6c065f10c7b5d0f33b7d6aeba5009a3904a13939b0a",
    "truncated": false,
    "error": null
  },
  "rollback": {
    "status": 200,
    "body": "{\"data\": {\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}, \"status\": \"success\"}",
    "sha256": "adcfe2b7e9dbdd1d13898a4fa175439852f3d475303833711abcab6d75ef4d61",
    "truncated": false,
    "error": null
  },
  "restored": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "01200488fa4628c0bfa9830d04748bdca682787072cbf1a44d73600872847e2e",
    "truncated": false,
    "error": null
  },
  "rollback_verified": true,
  "recovery_sent": true,
  "tested_fields": [
    "role"
  ],
  "untested_fields": [],
  "readback_consistency": "strong",
  "requests_attempted": 5,
  "reason_category": "conclusive"
}
SECUREMASS_ASSIGNMENTPATCH /api/users/{user_id}/nickname

写入检查:Visitor 提交字段 role;测试资源:http://127.0.0.1:59519/api/users/1002/nickname。

本次强一致读回未发现配置字段持久变化;结论仅限已执行的字段。原状态已通过读回核验。

执行分类:已完成有效检查并获得确定结论 · 请求尝试:5 次。

依据:Strongly consistent readback showed no persistence for all configured fields

修复方向、复验步骤和证据

修复方向:为当前身份明确允许更新的字段;在服务端拒绝或忽略权限、角色等未授权字段,并按业务策略校验更新权限。

安全复验步骤
  1. 仅在可恢复的测试资源上复验;先保存完整原状态,确认独立读回和恢复路径可用。恢复未核验时先处理恢复问题。
  2. 用 Visitor 提交该字段的最小测试修改,再由独立读取接口核对持久状态;未授权字段应保持原值,允许更新的字段应正常工作。
  3. 恢复原状态并再次读取核验;若结果不一致或无法核验,暂停后续写入测试并人工恢复。
{
  "tested_fields": [
    "role"
  ],
  "safe_fields": [
    "role"
  ],
  "unverified": [],
  "configured_fields": [
    "role"
  ],
  "target_url": "http://127.0.0.1:59519/api/users/1002/nickname",
  "cases": [
    {
      "field": "role",
      "readback_field": "role",
      "persisted": false,
      "rollback_verified": true,
      "recovery_sent": false
    }
  ],
  "rollback_verified": true,
  "recovery_sent": false,
  "ignored_readback_paths": [],
  "requests_attempted": 5,
  "reason_category": "conclusive"
}

确认的漏洞

#1 · CWE-639

BOLA (Broken Object Level Authorization)

GET /api/users/{user_id}/profile
High

Visitor 身份访问配置为 Owner 的资源:http://127.0.0.1:59519/api/users/1001/profile。

已确认对象级越权:双方响应的业务值一致;双方响应存在较高的非公开业务值重合。

依据:匿名请求被明确拒绝,而未授权访客获得了与所有者资源一致的具体值或资源标识。

修复方向:服务端按当前登录身份校验资源归属、团队共享和管理员权限;未获授权时拒绝返回资源数据。

安全复验步骤
  1. 在测试环境准备 Owner、Visitor 两个独立账户和各自的有效资源;先明确各身份按业务策略应被允许还是拒绝。
  2. 分别用 Owner、Visitor 和 Anonymous 读取 Owner 的同一资源,核对允许与拒绝结果及响应数据。凭据从本地安全配置加载。
  3. 同时验证 Visitor 可访问自身资源,以及合法团队共享、管理员访问按策略成功;重新扫描并比较结论。

cURL 复现模板(请填入授权测试凭据)

curl --globoff -X GET http://127.0.0.1:59519/api/users/1001/profile -H 'Authorization: Bearer <VISITOR_TOKEN>'

POSIX shell cURL template · 仅用于明确授权的测试环境。

POSIX shell;认证值为 Visitor 占位符,请填入授权测试凭据。

查看已最小化的证据
{
  "requests_attempted": 4,
  "target_url": "http://127.0.0.1:59519/api/users/1001/profile",
  "visitor_self_url": "http://127.0.0.1:59519/api/users/1002/profile",
  "owner": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1001\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "bef2104fbbc72d3fa3cae9524eb0dd5d3a7d29460d7f5709f2d7c14fe2a10ea9",
    "truncated": false,
    "error": null
  },
  "visitor_cross": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1001\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "bef2104fbbc72d3fa3cae9524eb0dd5d3a7d29460d7f5709f2d7c14fe2a10ea9",
    "truncated": false,
    "error": null
  },
  "anonymous": {
    "status": 401,
    "body": "{\"code\": 401, \"error\": \"Authentication required\"}",
    "sha256": "47a5198d709698ac15790fa7ac68c8ab6e4ce1eaeab7a421c22b69e5d07949cd",
    "truncated": false,
    "error": null
  },
  "visitor_self": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "01200488fa4628c0bfa9830d04748bdca682787072cbf1a44d73600872847e2e",
    "truncated": false,
    "error": null
  },
  "metrics": {
    "confidence": 0.99,
    "similarity": 1.0
  },
  "decision_evidence": {
    "responses": {
      "owner": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "visitor_cross": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      },
      "anonymous": {
        "kind": "AUTH_DENIED",
        "status_code": 401,
        "is_auth_denial": true,
        "reason": "HTTP 鉴权拒绝状态码 401"
      },
      "visitor_self": {
        "kind": "VALID",
        "status_code": 200,
        "is_auth_denial": false,
        "reason": "有效 JSON 业务响应"
      }
    },
    "anonymous_denied": true,
    "anonymous_exact_match": false,
    "anonymous_value_similarity": 0.0,
    "structure_similarity": 1.0,
    "value_similarity": 1.0,
    "exact_value_match": true,
    "owner_meaningful_value_count": 4,
    "visitor_meaningful_value_count": 4,
    "shared_value_count": 4,
    "owner_specific_shared_value_count": 3,
    "owner_specific_shared_value_paths": [
      "department",
      "name",
      "salary"
    ],
    "shared_resource_identifier_count": 0,
    "shared_resource_identifier_paths": [],
    "owner_only_shared_resource_identifier_count": 0,
    "owner_only_shared_resource_identifier_paths": [],
    "visitor_self_provided": true,
    "visitor_self_exact_match": false,
    "visitor_self_value_similarity": 0.142857,
    "visitor_self_shared_resource_identifier_count": 0,
    "owner_baseline_valid": true,
    "visitor_cross_baseline_valid": true,
    "visitor_self_baseline_valid": true,
    "owner_self_distinct": true,
    "object_access_signals": [
      "exact_business_value_match",
      "high_business_value_overlap"
    ],
    "confirmation_signals": [
      "exact_business_value_match",
      "high_business_value_overlap"
    ],
    "expected_public": false,
    "requires_auth": true,
    "trusted_resource_id_paths": [],
    "denial_body_conflict": false,
    "visitor_denial_body_clean": null,
    "anonymous_denial_body_clean": true,
    "anonymous_authentication_violation": false,
    "anonymous_owner_value_match": false,
    "anonymous_owner_identifier_match": false,
    "owner_shared_nonpublic_value_paths": [
      "department",
      "name",
      "role",
      "salary"
    ],
    "missing_evidence": [],
    "expected_visitor_access": "deny",
    "policy_scope": "Configured Owner/Visitor identities and selected resource pair only"
  }
}
#2 · CWE-915

Mass Assignment (independent readback confirmed)

PATCH /api/users/{user_id}/settings
Critical

写入检查:Visitor 提交字段 role;测试资源:http://127.0.0.1:59519/api/users/1002/settings。

独立读回确认该字段的测试值已持久保存。原状态已通过读回核验。

依据:Privilege field 'role' persisted after mutation

修复方向:为当前身份明确允许更新的字段;在服务端拒绝或忽略权限、角色等未授权字段,并按业务策略校验更新权限。

安全复验步骤
  1. 仅在可恢复的测试资源上复验;先保存完整原状态,确认独立读回和恢复路径可用。恢复未核验时先处理恢复问题。
  2. 用 Visitor 提交该字段的最小测试修改,再由独立读取接口核对持久状态;未授权字段应保持原值,允许更新的字段应正常工作。
  3. 恢复原状态并再次读取核验;若结果不一致或无法核验,暂停后续写入测试并人工恢复。

cURL 复现模板(请填入授权测试凭据)

curl --globoff -X PATCH http://127.0.0.1:59519/api/users/1002/settings -H 'Authorization: Bearer <VISITOR_TOKEN>' -H 'Content-Type: application/json' --data '{"role":"admin"}'

POSIX shell cURL template · 仅用于明确授权的测试环境。

POSIX shell;认证值为 Visitor 占位符,请填入授权测试凭据。

查看已最小化的证据
{
  "field": "role",
  "readback_field": "role",
  "target_url": "http://127.0.0.1:59519/api/users/1002/settings",
  "readback_url": "http://127.0.0.1:59519/api/users/1002/profile",
  "request_content_type": "application/json",
  "snapshot_fields": [
    "role"
  ],
  "verification_scope": "Full readback document except explicitly ignored volatile paths",
  "ignored_readback_paths": [],
  "mutation": {
    "status": 200,
    "body": "{\"data\": {\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"admin\", \"salary\": \"[REDACTED]\"}, \"status\": \"success\"}",
    "sha256": "5c51f4b94305bb140842fbcb4b4b12ab45fc5dd84c42031a1bdbd7f594a9b1e4",
    "truncated": false,
    "error": null
  },
  "after": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"admin\", \"salary\": \"[REDACTED]\"}",
    "sha256": "22218090e97259835a63a6c065f10c7b5d0f33b7d6aeba5009a3904a13939b0a",
    "truncated": false,
    "error": null
  },
  "rollback": {
    "status": 200,
    "body": "{\"data\": {\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}, \"status\": \"success\"}",
    "sha256": "adcfe2b7e9dbdd1d13898a4fa175439852f3d475303833711abcab6d75ef4d61",
    "truncated": false,
    "error": null
  },
  "restored": {
    "status": 200,
    "body": "{\"department\": \"[REDACTED]\", \"id\": \"1002\", \"name\": \"[REDACTED]\", \"role\": \"user\", \"salary\": \"[REDACTED]\"}",
    "sha256": "01200488fa4628c0bfa9830d04748bdca682787072cbf1a44d73600872847e2e",
    "truncated": false,
    "error": null
  },
  "rollback_verified": true,
  "recovery_sent": true,
  "tested_fields": [
    "role"
  ],
  "untested_fields": [],
  "readback_consistency": "strong"
}