feat(gateway): 输入护栏拦提示词注入/超大体(弃用空桩)+ 单测
Guardrail 中间件此前是空桩(直接 c.Next)。落地输入护栏: - 新增纯逻辑包 internal/guardrail:Inspect(body) 检测提示词注入(忽略既定指令/ 角色越权/诱导泄露提示词,中英文模式)+ 超大体(>256KB),与 HTTP 解耦便于单测; 敏感词黑名单留空可扩展。 - 中间件:仅对带 JSON 体的 POST/PUT 检查(文件上传 multipart 与 GET/SSE 跳过); 限读 + 命中拦截返回 422;未命中则还原请求体(io.NopCloser)供 handler 读取。 - 输出护栏不在网关做:Token 流是 SSE 实时流,网关缓冲会破坏流式 —— 标到路线图, 应在 dispatcher token 发射层做。 验证: - 单测:正常输入不误拦、中英文注入均拦、超大体拦、边界恰好放行。 - 实跑(nats+gateway):注入(中/英) → 422 带原因;干净输入 → 202 且 body 正确还原、 handler 正常发布到 NATS。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,20 +2,37 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/sundynix/sundynix-gateway/internal/guardrail"
|
||||
"github.com/sundynix/sundynix-gateway/internal/store"
|
||||
)
|
||||
|
||||
// Guardrail 实现 Harness 的输入/输出护栏(敏感词、注入、配额校验等)。
|
||||
// Guardrail 实现 Harness 输入护栏:拦截提示词注入 / 超大请求体。
|
||||
// 只检查带 JSON 体的写请求(POST/PUT);文件上传(multipart)与 GET/SSE 不经此。
|
||||
// 输出护栏不在此做 —— Token 流为 SSE 实时流,网关缓冲会破坏流式,输出过滤应在
|
||||
// dispatcher 的 token 发射层(见 PROGRESS 路线图)。
|
||||
func Guardrail() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
// TODO: 输入护栏校验
|
||||
if m := c.Request.Method; (m == http.MethodPost || m == http.MethodPut) &&
|
||||
strings.HasPrefix(c.GetHeader("Content-Type"), "application/json") {
|
||||
// 限读上限 + 1 字节以判定"过大";命中拦截则后续 handler 不执行。
|
||||
body, _ := io.ReadAll(io.LimitReader(c.Request.Body, guardrail.MaxJSONBytes+1))
|
||||
if reason, blocked := guardrail.Inspect(body); blocked {
|
||||
log.Printf("[guardrail] 拦截 %s %s:%s", c.Request.Method, c.Request.URL.Path, reason)
|
||||
c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{"error": "输入护栏拦截:" + reason})
|
||||
return
|
||||
}
|
||||
c.Request.Body = io.NopCloser(bytes.NewReader(body)) // 还原请求体供后续 handler 读取
|
||||
}
|
||||
c.Next()
|
||||
// TODO: 输出护栏校验
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user