OtterMind/Chat2DB · error · ConfigurationError
Prepared QQ notification contains a OneBot CQ code
Error message
Prepared QQ notification contains a OneBot CQ code
What it means
Raised by _read_prepared_message (notify_qq.py:265) when message contains the OneBot 11 CQ-code marker "[CQ:" (case-insensitive). CQ codes are markup that OneBot interprets as commands (images, mentions, etc.), so injecting one is an injection vector; the relay and prepared path both forbid it.
Source
Thrown at script/github/notify_qq.py:265
raise ConfigurationError("Prepared QQ notification is missing or too large")
try:
envelope = json.loads(path.read_text(encoding="utf-8"))
except (OSError, UnicodeError, json.JSONDecodeError) as error:
raise ConfigurationError("Prepared QQ notification is not valid JSON") from error
if not isinstance(envelope, Mapping) or envelope.get("version") != 1:
raise ConfigurationError("Prepared QQ notification has an invalid format")
if envelope.get("repository") != repository:
raise ConfigurationError("Prepared QQ notification repository does not match")
event_name = str(envelope.get("event_name") or "")
if event_name not in COLLECTED_EVENT_NAMES:
raise ConfigurationError("Prepared QQ notification event is not allowed")
message = envelope.get("message")
if not isinstance(message, str) or not message or len(message) > 900:
raise ConfigurationError("Prepared QQ notification message is invalid")
if re.search(r"[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]", message):
raise ConfigurationError("Prepared QQ notification contains control characters")
if re.search(r"(?i)\[CQ:", message):
raise ConfigurationError("Prepared QQ notification contains a OneBot CQ code")
return event_name, message
def _event_detail(event_name: str, action: str, payload: Mapping[str, Any]) -> str:
if action in {"labeled", "unlabeled"}:
label = payload.get("label") or {}
return f"标签:{_clean_text(label.get('name'), 80)}"
if action in {"assigned", "unassigned"}:
return f"处理人:{_login(payload.get('assignee'))}"
if action in {"milestoned", "demilestoned"}:
milestone = payload.get("milestone") or {}
return f"里程碑:{_clean_text(milestone.get('title'), 100)}"
if action in {"review_requested", "review_request_removed"}:
reviewer = _login(payload.get("requested_reviewer"))
team = payload.get("requested_team") or {}
target = reviewer or _clean_text(team.get("name"), 80)
return f"评审人:{target}"
if event_name == "pull_request_target" and action == "synchronize":View on GitHub (pinned to 5ee1e990e7)
Solutions
- Regenerate the envelope through the collect step, which defangs CQ markers in _clean_text.
- Remove or escape the literal "[CQ:" sequence in the message field.
- Treat this as a security signal: investigate how untrusted text entered the envelope.
Example fix
import re safe = re.sub(r'(?i)\[CQ:', '[CQ :', message)
Defensive patterns
Strategy: validation
Validate before calling
import re
if re.search(r'(?i)\[CQ:', message):
message = re.sub(r'(?i)\[CQ:', '[CQ :', message) Type guard
import re
CQ = re.compile(r'(?i)\[CQ:')
def is_safe_from_cq(message: str) -> bool:
return not CQ.search(message) Prevention
- Defang CQ markers with _clean_text before storing in an envelope.
- Treat an injected CQ code as a security incident and trace its source.
When it happens
Trigger: A crafted message containing "[CQ:..." reaches the prepared envelope. The live build path defangs it via _clean_text (replacing with "[CQ :"), so this only fires through the QQ_PREPARED_MESSAGE_PATH read path with a tampered envelope.
Common situations: Hand-editing the JSON to inject a mention/at-all/image CQ code; testing the relay with a payload meant to trigger OneBot features; an envelope from tooling that did not sanitize.
Related errors
- Prepared QQ notification repository does not match
- Prepared QQ notification event is not allowed
- Prepared QQ notification message is invalid
- Prepared QQ notification contains control characters
- QQ_RELAY_URL must be an HTTPS URL without credentials or a f
AI-assisted analysis of OtterMind/Chat2DB@5ee1e990e7 (2026-08-14).
Data as JSON: /api/errors/962d5b328dd37c7a.
Report an issue: GitHub.