T09 · Insecure Skill Coding Practices
- Location
scripts/validate_clause_completeness.py:53- Finding
Ambiguous Article Matching Can Falsely Validate Incorrect Legal Quotations
- Content
View full analysis
Vulnerability Details
File Location:
scripts/validate_clause_completeness.py, lines 53–68 and 103
Vulnerability Type: Unanchored and prefix-ambiguous legal article matching
Risk Level: MediumVulnerable Code
python def locate_clause(source: str, article: str): """在源全文中截取 [目标条号, 下一条同级条号) 之间的完整条文。""" esc = re.escape(article) m = re.search(esc, source) if not m: return None, False start = m.start() level = same_level_pattern(article) next_found = False end = len(source) for nm in level.finditer(source, m.end()): if nm.group(0) == article: continue end = nm.start() next_found = True break return source[start:end].strip(), next_foundpython result["starts_with_article_number"] = norm(args.article) in naTechnical Analysis
The validator searches for article identifiers as unanchored substrings rather than structurally validating an article heading.
For dotted identifiers, a requested article such as
6.2.1can match the beginning of6.2.11. For Chinese identifiers,第六条can match the prefix of第六条之一. The search for the next same-level article is also not restricted to paragraph or line boundaries, so an article identifier appearing inside the clause as a cross-reference may be incorrectly treated as the start of the next clause.The
starts_with_article_numberfield does not verify that the quoted block begins with the requested heading. It only checks whether the normalized article identifier occurs anywhere in the complete answer. Moreover, this field does not participate in the exit-code decision:python return 0 if (result["complete_match"] and not result["ellipsis_detected"]) else 1Consequently, the script can return a successful exit code after selecting the wrong clause or an incorrectly truncated clause.
Attack Path
- An attacker ...[truncated 1694 chars]
- Remediation
View remediation
Remediation Suggestions
- Require article identifiers to occur at normalized paragraph or line starts rather than anywhere in the source text.
- Add exact trailing boundaries:
- For dotted identifiers, require a delimiter after the identifier so
6.2.1cannot match6.2.11. - For Chinese identifiers, prevent
第六条from matching第六条之一.
- For dotted identifiers, require a delimiter after the identifier so
- Match longer and more specific identifier forms before shorter prefix-compatible forms.
- Detect the next article only when the identifier is a genuine heading at the expected structural boundary.
- Require the relevant quotation block in the answer—not merely the entire answer—to begin with the exact requested article heading.
- Include
starts_with_article_numberandnext_article_foundin the success condition, except where the source has been independently confirmed to end with the target article. - Reject multiple ambiguous matches unless the caller selects a uniquely identified occurrence.
- Add regression tests for:
6.2.1versus6.2.11;第六条versus第六条之一;- Article identifiers in cross-references within clause text;
- Repeated article identifiers;
- Last-article handling;
- Answers that contain the article number outside the quoted block.
- Where source formats preserve structure, parse paragraph styles or document nodes instead of relying exclusively on regular expressions.
