Skip to content

Comments

diff#567

Closed
dengyh wants to merge 15 commits intofeat/credential_improve_v2from
master
Closed

diff#567
dengyh wants to merge 15 commits intofeat/credential_improve_v2from
master

Conversation

@dengyh
Copy link
Collaborator

@dengyh dengyh commented Jan 7, 2026

No description provided.

guohelu and others added 10 commits December 19, 2025 10:37
* feat: 网关增加流程版本管理sdk接口 --story=129266074
# Reviewed, transaction id: 68622

* fix: 修改删除接口逻辑 --story=129266074
# Reviewed, transaction id: 68626
* feat: 补充第三方插件网关接口 --story=129266074

* feat: 补充接口文档 --story=129266074

* feat: 补充流程版本关联接口文档 --story=129266074
# Reviewed, transaction id: 68892
* fix: 修复网关接口请求方法错误 --story=129266074

* fix: 修复接口文档错误 --story=129266074
* fix: 版本快照列表协议修改 --story=128050351
# Reviewed, transaction id: 69031

* fix: 添加异常捕获 --story=128050351
# Reviewed, transaction id: 69036
* feat: 补充模板发布免认证接口 --story=129543443
# Reviewed, transaction id: 69289

* fix: 修复接口逻辑 --story=129543443
# Reviewed, transaction id: 69317
* fix: 修复网关接口发布流程重复问题 --story=129266074

* feat: 调试功能增加作用域校验 --story=129266074
# Reviewed, transaction id: 69579

* fix: 修复权限校验问题 --story=129266074
# Reviewed, transaction id: 69580
assert DomainValidator.validate("http://sub.example.com")[0] is True
is_valid, err = DomainValidator.validate("http://other.com")
assert is_valid is False
assert "example.com" in err

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High test

The string
example.com
may be at an arbitrary position in the sanitized URL.

Copilot Autofix

AI about 2 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

["system", "bk_plugins"], environment="prod"
)

assert "http://paas.example.com" in url

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High test

The string
http://paas.example.com
may be at an arbitrary position in the sanitized URL.

Copilot Autofix

AI about 2 months ago

In general, instead of checking whether a trusted base URL is a substring of another URL string, parse the URL and assert on its structured components (scheme, hostname, path, query). This avoids issues where the expected host appears in an unexpected place or is combined with other content.

For this specific test, we can keep the existing behavior expectations while making the check precise by parsing url with urllib.parse.urlparse and asserting that scheme == "http" and netloc == "paas.example.com". This removes the substring check and aligns with the recommendation to operate on parsed URLs. We only need to modify the test method test_prepare_paas_api_request_with_token in tests/plugin_service/test_plugin_client.py (line 702 onward) and add a standard-library import of urlparse at the top of that file. No application logic needs to change, only the way the test validates the URL.

Concretely:

  • Add from urllib.parse import urlparse near the other imports at the top of tests/plugin_service/test_plugin_client.py.
  • Replace assert "http://paas.example.com" in url with:
    • parsed_url = urlparse(url)
    • assert parsed_url.scheme == "http"
    • assert parsed_url.netloc == "paas.example.com"
      This maintains the same intention (ensuring the base host is used) while avoiding substring sanitization.
Suggested changeset 1
tests/plugin_service/test_plugin_client.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/tests/plugin_service/test_plugin_client.py b/tests/plugin_service/test_plugin_client.py
--- a/tests/plugin_service/test_plugin_client.py
+++ b/tests/plugin_service/test_plugin_client.py
@@ -23,6 +23,7 @@
 import pytest
 from django.core.files.uploadedfile import UploadedFile
 from requests import HTTPError
+from urllib.parse import urlparse
 
 from plugin_service import env
 from plugin_service.exceptions import PluginServiceException, PluginServiceNotUse
@@ -708,7 +709,9 @@
                         ["system", "bk_plugins"], environment="prod"
                     )
 
-                    assert "http://paas.example.com" in url
+                    parsed_url = urlparse(url)
+                    assert parsed_url.scheme == "http"
+                    assert parsed_url.netloc == "paas.example.com"
                     assert params["private_token"] == "test_token"
 
     def test_prepare_paas_api_request_without_token(self):
EOF
@@ -23,6 +23,7 @@
import pytest
from django.core.files.uploadedfile import UploadedFile
from requests import HTTPError
from urllib.parse import urlparse

from plugin_service import env
from plugin_service.exceptions import PluginServiceException, PluginServiceNotUse
@@ -708,7 +709,9 @@
["system", "bk_plugins"], environment="prod"
)

assert "http://paas.example.com" in url
parsed_url = urlparse(url)
assert parsed_url.scheme == "http"
assert parsed_url.netloc == "paas.example.com"
assert params["private_token"] == "test_token"

def test_prepare_paas_api_request_without_token(self):
Copilot is powered by AI and may make mistakes. Always verify output.
["system", "bk_plugins"]
)

assert "example.com" in url

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization High test

The string
example.com
may be at an arbitrary position in the sanitized URL.

Copilot Autofix

AI about 2 months ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

bump_custom(new_version, instance.version)
except ValueError as e:
logger.error(str(e))
return JsonResponse({"result": False, "message": f"版本号不符合规范: {str(e)}", "code": err_code.VALIDATION_ERROR.code})

Check warning

Code scanning / CodeQL

Information exposure through an exception Medium

Stack trace information
flows to this location and may be exposed to an external user.

Copilot Autofix

AI about 2 months ago

In general, the fix is to avoid returning raw exception details to the client. Instead, log the exception (optionally with a stack trace) on the server and send a generic, user-friendly error message that does not expose internal implementation details.

For this specific case in bkflow/apigw/views/release_template.py, we should change the except ValueError as e: block so that it no longer interpolates str(e) into the message field of the JSON response. Instead:

  • Keep logging the error, ideally with stack information.
  • Return a generic validation message like “版本号不符合规范” without including str(e).

Concretely:

  • At lines 66–68:
    • Replace logger.error(str(e)) with a form that logs the exception more fully without affecting the client response (e.g. logger.exception("Invalid version format")), though we can also keep the original message if desired.
    • Replace return JsonResponse({"result": False, "message": f"版本号不符合规范: {str(e)}", ...}) with a generic message that omits str(e), e.g. {"result": False, "message": "版本号不符合规范", ...}.

No new imports or additional methods are required; the file already imports logging and configures logger.


Suggested changeset 1
bkflow/apigw/views/release_template.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/bkflow/apigw/views/release_template.py b/bkflow/apigw/views/release_template.py
--- a/bkflow/apigw/views/release_template.py
+++ b/bkflow/apigw/views/release_template.py
@@ -64,8 +64,8 @@
     try:
         bump_custom(new_version, instance.version)
     except ValueError as e:
-        logger.error(str(e))
-        return JsonResponse({"result": False, "message": f"版本号不符合规范: {str(e)}", "code": err_code.VALIDATION_ERROR.code})
+        logger.error("Invalid version format: %s", str(e))
+        return JsonResponse({"result": False, "message": "版本号不符合规范", "code": err_code.VALIDATION_ERROR.code})
 
     with transaction.atomic():
         data = {"username": request.user.username, **ser.validated_data}
EOF
@@ -64,8 +64,8 @@
try:
bump_custom(new_version, instance.version)
except ValueError as e:
logger.error(str(e))
return JsonResponse({"result": False, "message": f"版本号不符合规范: {str(e)}", "code": err_code.VALIDATION_ERROR.code})
logger.error("Invalid version format: %s", str(e))
return JsonResponse({"result": False, "message": "版本号不符合规范", "code": err_code.VALIDATION_ERROR.code})

with transaction.atomic():
data = {"username": request.user.username, **ser.validated_data}
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查总结

本次审查重点关注新增的并发请求、线程池、API客户端以及权限验证逻辑。发现以下关键问题需要处理:

🚨 严重问题

  1. 并发请求缺少超时控制 - batch_request 中线程池执行可能无限期等待
  2. 错误处理逻辑不一致 - 第一次请求和后续批量请求的错误检查存在差异

🔒 安全问题

  1. 敏感信息泄露风险 - Cookie 中的 bk_ticket 未经验证直接传递到 API
  2. 线程本地存储清理不完整 - 异常时可能导致数据泄露

⚡ 性能问题

  1. 线程数未限制 - ThreadPool() 可能创建大量线程导致资源耗尽

⚠️ 逻辑问题

  1. 数据库连接处理 - 仅在 finally 块关闭,异常场景可能遗留连接
  2. 响应数据校验缺失 - release_template API 未验证空间版本管理配置时机不当

建议优先修复严重和安全问题,性能问题在高并发场景下需要关注。

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查总结

本次审查重点关注新增的免登录发布流程、删除模板逻辑变更、权限控制以及前端错误处理。发现以下需要关注的问题:

🔒 安全问题

  1. 免登录接口缺少关键权限验证 - release_template 使用 @login_exempt 但权限检查可能不足
  2. 软删除未清理关联数据 - delete_template 改为软删除但未处理快照等关联数据

⚠️ 逻辑问题

  1. 版本管理开关检查不一致 - 部分接口缺少版本管理功能开关验证
  2. 前端错误处理不完整 - try-catch 块捕获异常后仅 console.log,未向用户展示错误

✨ 改进建议

  1. 权限验证逻辑可优化 - has_object_permission 中存在重复的权限检查调用

建议优先修复安全问题,逻辑问题会影响功能一致性。

guohelu and others added 4 commits January 7, 2026 16:20
* fix: 更换接口修复权限问题
# Reviewed, transaction id: 70128

* fix: 更换接口修复权限问题
# Reviewed, transaction id: 70130
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查总结

本次审查发现以下关键问题需要处理:

🚨 严重问题

  1. 软删除缺少关联数据清理 - delete_template 改为软删除但未处理快照等关联数据,可能导致数据泄露
  2. 权限控制逻辑存在漏洞 - 新增免登录接口 release_template 使用 @login_exempt,需要额外验证权限检查是否充分

🔒 安全问题

  1. 敏感信息可能泄露 - AJAX 请求新增 withCredentials: true 可能导致跨域传递敏感凭证
  2. 版本管理权限检查不一致 - 部分接口缺少版本管理开关验证

⚠️ 逻辑问题

  1. 错误处理不完整 - 多处前端 try-catch 仅输出 console.log,用户无法感知错误
  2. API 响应结构不一致 - getTemplateVersionSnapshotList 返回值从 res 改为 res.data,需确保后端一致性

建议优先修复严重和安全问题。

* refactor: 使用AI补充存量功能的测试用例 --story=129211203

* refactor: 删除冗余的无意义的测试用例 --story=129211203

* refactor: 测试用例排除非代码文件 --story=129211203

* refactor: 测试覆盖率提升到80%以上 --story=129211203
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

代码审查总结

已审查此 PR 的主要变更,发现以下关键问题需要处理:

🚨 严重问题

  1. release_template.py:48 - JSON 解析缺少异常处理,可能导致 500 错误
  2. release_template.py:52 - 返回错误响应时未设置正确的 HTTP 状态码
  3. models.py:309-320 - force 参数存在安全隐患,可绕过草稿验证直接发布任意版本

⚠️ 需改进

  1. delete_template.py:38 - 删除操作记录被移除,影响审计追踪
  2. models.py:311 - 控制流不清晰,return 语句位置会让人困惑

✨ 积极改进

  • 软删除替代硬删除(delete_template.py)
  • 权限系统增强支持 MOCK 权限
  • 新增版本管理和发布功能

建议优先修复前 3 个严重问题后再合并。

try:
instance = Template.objects.get(id=template_id, space_id=space_id)
except Template.DoesNotExist:
return JsonResponse({"result": False, "message": "Template not found"})
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 应设置正确的 HTTP 状态码(如 404),当前返回 200 会误导客户端

except TemplateSnapshot.DoesNotExist:
logger.warning(f"未找到模板(ID: {self.id})的草稿快照(draft=True)")
raise ValidationError(f"该模板{self.id}没有草稿版本")
if data.get("force", False):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 force 参数可绕过草稿验证直接发布任意 pipeline_tree,建议加权限检查或审核流程

@check_jwt_and_space
@return_json_response
def release_template(request, space_id, template_id):
data = json.loads(request.body)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 缺少异常处理:json.loads 可能抛出 JSONDecodeError,建议添加 try-except 或使用 serializer 统一验证

TemplateOperationSource.api.name,
extra_info={"tag": "apigw"},
)
def delete_template(request, space_id, template_id):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 删除操作记录被移除,影响合规审计。建议保留 record_operation 装饰器

instance.snapshot_id = snapshot.id
instance.save()

TemplateOperationRecord.objects.create(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚡ TemplateOperationRecord 创建在事务外,若此步骤失败会导致数据不一致。建议移入事务内

except Exception as e:
logger.error(f"发布模板草稿时发生错误(template_id={self.id}): {e}", exc_info=True)
raise ValidationError("发布模板失败,请稍后重试")
return template_snapshot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ return 语句移到 try-except 外部,代码流不清晰。建议在每个分支明确 return

count, _ = Template.objects.filter(space_id=space_id, id=template_id).delete()
return {"result": True, "data": {"count": count}, "code": err_code.SUCCESS.code}
Template.objects.filter(space_id=space_id, id=template_id).update(is_deleted=True)
return {"result": True, "data": {}, "code": err_code.SUCCESS.code}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 软删除缺少状态验证:应检查 is_deleted 避免重复删除;考虑检查是否有关联任务运行中

if TemplateSnapshot.objects.filter(template_id=instance.id, version=new_version).exists():
return JsonResponse({"result": False, "message": "版本已存在", "code": err_code.VALIDATION_ERROR.code})

try:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ 版本验证在快照存在性检查之后,顺序不佳。建议先验证版本格式,再检查重复,减少不必要的数据库查询

@dengyh dengyh closed this Jan 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants