{"record":{"id":"362fe230ffd154bf","repo":"shadow1ng/fscan","slug":"webscan-xray-no-rules","errorCode":"webscan_xray_no_rules","errorMessage":"webscan_xray_no_rules","messagePattern":"webscan_xray_no_rules","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"webscan/lib/poc_adapter.go","lineNumber":493,"sourceCode":"\t\t\tFollowRedirects: rule.Request.FollowRedirects,\n\t\t\tExpression:      rule.Expression,\n\t\t}\n\n\t\t// 转换 output 字段为 Search — 多步POC中从响应提取变量供后续步骤使用\n\t\tif searchVal, ok := rule.Output[\"search\"]; ok {\n\t\t\tfscanRule.Search = fmt.Sprintf(\"%v\", searchVal)\n\t\t}\n\n\t\t// 如果expression为空，默认检查200状态码\n\t\tif fscanRule.Expression == \"\" {\n\t\t\tfscanRule.Expression = \"response.status == 200\"\n\t\t}\n\n\t\tpoc.Rules = append(poc.Rules, fscanRule)\n\t}\n\n\tif len(poc.Rules) == 0 {\n\t\treturn nil, fmt.Errorf(\"%s\", i18n.GetText(\"webscan_xray_no_rules\"))\n\t}\n\n\treturn poc, nil\n}\n\n// ============= afrog格式适配器 =============\n\n// AfrogPoc afrog POC结构（混合 Nuclei + xray 风格）\ntype AfrogPoc struct {\n\tID   string `yaml:\"id\"`\n\tInfo struct {\n\t\tName        string         `yaml:\"name\"`\n\t\tAuthor      yamlStringList `yaml:\"author\"`\n\t\tSeverity    string         `yaml:\"severity\"`\n\t\tVerified    bool           `yaml:\"verified\"`\n\t\tDescription string         `yaml:\"description\"`\n\t\tReference   yamlStringList `yaml:\"reference\"`\n\t\tTags        string         `yaml:\"tags\"`","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/shadow1ng/fscan/blob/95cc12e753bf43de7004e5aef42a9ffba3934303/webscan/lib/poc_adapter.go#L475-L511","documentation":"ToFscanPoc converts an XrayPoc into fscan-style rules; if zero rules were produced after conversion, it refuses to return an empty POC and throws webscan_xray_no_rules. This guards callers from executing a POC with no detectable logic.","triggerScenarios":"Calling ToFscanPoc on an XrayPoc whose Rules/Expression fields are empty or whose expression syntax is not convertible, so the conversion loop appends nothing to poc.Rules.","commonSituations":"An Xray POC YAML missing the 'expression' or rules section; a POC using xray CEL expression features the converter does not support, resulting in all rules being skipped silently; programmatically constructing an XrayPoc struct with only metadata (name/id) and no rules.","solutions":["Check that the source Xray POC has non-empty rules/expression fields before calling ToFscanPoc","Verify the xray expression uses constructs the converter supports; simplify unsupported CEL operators","Log/warn if poc.Rules is empty after conversion and skip or fix that POC","Regenerate or obtain the POC from a current xray POC repository"],"exampleFix":"// before\npoc, err := adapter.ToFscanPoc() // errors: no rules\n// after\nif len(adapter.Poc.Rules) == 0 || adapter.Poc.Expression == \"\" {\n    return // skip non-convertible POC\n}\npoc, err := adapter.ToFscanPoc()","handlingStrategy":"validation","validationCode":"if len(xrayPoc.Rules) == 0 || xrayPoc.Expression == \"\" {\n    return errors.New(\"xray POC has no convertible rules\")\n}","typeGuard":"func hasConvertibleRules(p *lib.XrayPoc) bool {\n    return p != nil && (len(p.Rules) > 0 || strings.TrimSpace(p.Expression) != \"\")\n}","tryCatchPattern":"poc, err := adapter.ToFscanPoc()\nif err != nil && strings.Contains(err.Error(), \"webscan_xray_no_rules\") {\n    log.Warnf(\"skipping non-convertible POC %s\", adapter.GetName())\n    return nil\n}","preventionTips":["Pre-download POCs that the converter is known to handle","Dry-run conversion over your POC corpus and drop empty-rule cases","Keep xray POC expressions within supported CEL constructs","Check rule count after conversion before executing"],"tags":["poc","conversion","xray"],"backgroundTag":"empty-result-set","analyzedSha":"95cc12e753bf43de7004e5aef42a9ffba3934303","analyzedAt":"2026-09-06T17:07:30.094Z","contentChangedAt":"2026-09-06T17:07:30.094Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}