666ghj/MiroFish · error · StarHistoryError
generated SVG contains a forbidden attribute
Error message
generated SVG contains a forbidden attribute
What it means
Raised by `_validate_svg`'s attribute loop (scripts/star_history.py:1222) when an attribute name is namespaced (starts with `{`, e.g. `{http://www.w3.org/1999/xlink}href`) or is not in the per-element allowlist in `allowed_attributes`. The published SVG permits only reviewed, plain-named attributes on each element type — xlink-prefixed or novel attributes are rejected.
Source
Thrown at scripts/star_history.py:1222
"href": OWNER_AVATAR_DATA_URI,
"clip-path": "url(#clip-circle-title)",
}
watermark_attributes = {
"x": "635",
"y": "508.333",
"width": "20",
"height": "20",
"href": WATERMARK_LOGO_DATA_URI,
}
if element.attrib == avatar_attributes:
avatar_count += 1
elif element.attrib == watermark_attributes:
watermark_count += 1
else:
raise StarHistoryError("generated SVG contains an unreviewed image")
for raw_name, value in element.attrib.items():
if raw_name.startswith("{") or raw_name not in allowed_for_element:
raise StarHistoryError("generated SVG contains a forbidden attribute")
if (
not value.isascii()
or "\\" in value
or "/*" in value
or "*/" in value
or any(ord(character) < 0x20 for character in value)
):
raise StarHistoryError("generated SVG contains an unsafe attribute value")
exact_values = exact_attribute_values.get(raw_name)
if exact_values is not None and value not in exact_values:
raise StarHistoryError("generated SVG contains an unsafe attribute value")
if raw_name == "href":
if local_name != "image" or value not in {
OWNER_AVATAR_DATA_URI,
WATERMARK_LOGO_DATA_URI,
}:
raise StarHistoryError("generated SVG contains an external resource")
lowered = value.lower().replace(" ", "")View on GitHub (pinned to b5b53acc57)
Solutions
- Use the SVG2 plain attribute names the template already uses — `href`, not `{xlink}href`.
- In forks, add any new attribute to the target element's set in `allowed_attributes` (and to `exact_attribute_values` if it must be pinned), after review.
- Avoid editor round-trips: Inkscape adds `id`/`data-*` everywhere and this check will fail.
- Print `element.attrib` for the failing element (catch StarHistoryError around `_validate_svg` in a debug harness) to see exactly which name was rejected.
Example fix
# before: namespaced attribute serializes as {ns}href
link.set("{http://www.w3.org/1999/xlink}href", uri)
# after: plain SVG2 attribute, already allowlisted
link.set("href", uri) Defensive patterns
Strategy: try-catch
Validate before calling
def plain_attribute_names(payload: bytes) -> bool:
root = ET.fromstring(payload)
return not any(name.startswith("{") for el in root.iter() for name in el.attrib) Try / catch
try:
_validate_svg(payload)
except StarHistoryError as exc:
if "forbidden attribute" in str(exc):
raise ValueError("attribute is namespaced or not allowlisted for this element") from exc
raise Prevention
- Use plain SVG2 attribute names (href, not xlink:href) in all fork code.
- Extend the per-element allowlist (and exact-value pinning) whenever you add an attribute in a fork.
- Skip editor round-trips — tools that inject id/class/data-* attributes will fail this check.
- Debug by printing element.attrib for the failing element to identify the rejected name.
When it happens
Trigger: Serializing with ElementTree while elements carry namespaced attributes (classic `{xlink}href` when code sets `"{http://www.w3.org/1999/xlink}href"`), fork code adding unlisted attributes like `opacity`, `class`, `id`, or `filter`, or attributes valid on one element used on another (e.g. `font-size` on `<rect>`).
Common situations: Forks porting markup that uses SVG 1.1 `xlink:href`; adding CSS hooks (`class`) for downstream styling; editors that attach `id`/`data-name` attributes to every node; using `href` on an element whose allowlist set lacks it.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- generated SVG contains a forbidden element
- generated SVG contains forbidden XML directives
- generated SVG contains a foreign namespace
- generated SVG contains an unreviewed image
- generated SVG must be strict UTF-8
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/6e65556f59657648.
Report an issue: GitHub.