Files
rengine/reports/render/env.py
T
Yogesh OjhaandClaude Opus 5 0b853e04b6 chore: production-readiness review across the tree
A full static review of the 3.0 tree, run as two fan-out passes with every
finding verified against the running stack rather than taken on inspection.

Correctness and security
- instance settings encrypted the mask over the stored AI key: `!= MASK` never
  matched `••••••••abcd`, so saving settings destroyed the key and `test_ai`
  posted the mask as a bearer token
- the MFA token was replayable for its full five-minute life; the gate now
  checks revocation and consumes the token after a successful exchange
- logout revoked nothing for a bearer client while answering "Logged out"
- `POST /api-keys/{id}/test` returned the plaintext key inside httpx's error
  string, which embeds the whole URL
- an interest rule could be edited or deleted through another project's id
- redis ran the celery broker under `allkeys-lru`, free to evict a queued task
  or a chord counter; now `noeviction`
- nuclei's stored command carried the OAST token and every auth header
- a finalize step could poison the session and leave a scan RUNNING for ever
- `is:issue` raised TypeError on every search
- offset paging repeated and skipped rows in four dimensions
- a cancelled run kept a stale `scans.*_found` rollup
- every PDF report raised `KeyError: 'software'`
- `version_key` truncated a wide numeric run and inverted release ordering
- psycopg raises a NUL as a bare ValueError, above StatementError, so every
  savepoint guard was blind to the case it was written for

Performance
- endpoints.host had no trigram index: 35.9ms seq scan -> 0.389ms
- free text compiled to one OR, not the prescribed UNION ALL: 132ms -> 41ms
- `/http-assets/summary` and `/ips/summary` materialised whole tables
- the cross-link `ip` kind ran an estate query per page and drew nothing

Frontend
- `$effect` loaders that read the state they write, an unbounded request loop
  on a failing endpoint
- error states that rendered as empty states
- 2FA backup codes were unusable while the copy said they worked
- a "Scan history" dialog that always reported none
- ~400 duplicated lines across five filter bars, now one component

Build and tooling
- every scanner installed at @latest; all 13 pinned to the measured versions
- CI built `web/`, gone since 2.x, with tags that cannot be valid
- the prettier pre-commit hook discarded its filenames and always passed
- the test suite destroyed itself when run twice

Also: subdomains from public code, via a pinned github-subdomains source and a
GitHub API key that subfinder receives too; sublist3r and oneforall removed
after measuring one unique host in 89 across four targets.

Verified: 853 tests, ruff clean over eleven packages, svelte-check 0 errors,
the count-is-a-promise gate at 131 checks and 0 mismatches, and 143 GET routes
with no 5xx. Four migrations, each with an exercised downgrade.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DVkdx5ynZ6aof5kLFczmhX
2026-09-13 18:03:29 +05:30

144 lines
4.1 KiB
Python

"""The Jinja environment: section templates plus the filters they all use."""
from __future__ import annotations
import re
from datetime import datetime
from functools import lru_cache
from pathlib import Path
from jinja2 import ChoiceLoader, Environment, FileSystemLoader, select_autoescape
from markdown_it import MarkdownIt
from reports.charts import bars, cover_art, dial, donut, matrix, sparkline, stack_bar
from reports.charts.svg import Slice
from reports.render.media import image_data_uri
from shared.definitions.ports import SERVICE_CLASS_LABELS
from shared.definitions.vulnerabilities import SEVERITY_LABELS
TEMPLATES = Path(__file__).resolve().parent.parent / "templates"
SECTIONS = Path(__file__).resolve().parent.parent / "sections"
_MD = MarkdownIt("commonmark", {"html": False, "linkify": False, "typographer": True})
_MD.enable("table")
_MD.enable("strikethrough")
_REMOTE_IMG = re.compile(r"<img\b[^>]*?src=[\"\']((?!data:)[^\"\']*)[\"\'][^>]*>", re.I)
_MINUTE = 60
_HOUR = 3600
def markdown(value: str | None) -> str:
"""Authored text may embed an image."""
return _REMOTE_IMG.sub("", _MD.render(value or "")).strip()
def number(value: float | int | None) -> str:
if value is None:
return "—"
return f"{int(value):,}" if float(value).is_integer() else f"{value:,.1f}"
def percent(value: float | None, *, digits: int = 0) -> str:
if value is None:
return "—"
return f"{value * 100:.{digits}f}%"
def share(part: float | None, whole: float | None, *, digits: int = 0) -> str:
if not whole:
return "—"
return percent((part or 0) / whole, digits=digits)
def date(value: datetime | None, fmt: str = "%d %B %Y") -> str:
return value.strftime(fmt) if value else "—"
def datetime_at(value: datetime | None) -> str:
return value.strftime("%d %b %Y, %H:%M UTC") if value else "—"
def duration(seconds: float | None) -> str:
if seconds is None:
return "—"
total = int(seconds)
if total < _MINUTE:
return f"{total}s"
if total < _HOUR:
return f"{total // 60}m {total % 60:02d}s"
return f"{total // 3600}h {(total % 3600) // 60:02d}m"
def clip(value: str | None, length: int = 80) -> str:
"""Trim, and drop the replacement character a bad byte upstream leaves behind."""
text = (value or "").replace("\ufffd", "")
return text if len(text) <= length else text[: length - 1] + "…"
def severity_label(value: str | None) -> str:
return SEVERITY_LABELS.get((value or "").lower(), "Unknown")
def service_label(value: str | None) -> str:
return SERVICE_CLASS_LABELS.get((value or "").lower(), "Other")
def plural(count: int, word: str, suffix: str = "s") -> str:
return word if count == 1 else f"{word}{suffix}"
def counted(count: int, word: str, suffix: str = "s") -> str:
return f"{number(count)} {plural(count, word, suffix)}"
def pairs(rows) -> list[tuple[str, float]]:
return [(getattr(r, "name", ""), getattr(r, "count", 0)) for r in rows]
def severity_fill(value: str | None) -> str:
return f"var(--r-sev-{(value or 'unknown').lower()})"
@lru_cache(maxsize=1)
def environment() -> Environment:
env = Environment(
loader=ChoiceLoader([FileSystemLoader(TEMPLATES), FileSystemLoader(SECTIONS)]),
autoescape=select_autoescape(["html"]),
trim_blocks=True,
lstrip_blocks=True,
)
env.filters.update(
{
"md": markdown,
"num": number,
"pct": percent,
"share": share,
"date": date,
"at": datetime_at,
"dur": duration,
"clip": clip,
"sev": severity_label,
"svc": service_label,
"plural": plural,
"counted": counted,
"sevfill": severity_fill,
"pairs": pairs,
"shot": image_data_uri,
}
)
env.globals.update(
{
"Slice": Slice,
"donut": donut,
"bars": bars,
"stack_bar": stack_bar,
"dial": dial,
"sparkline": sparkline,
"matrix": matrix,
"cover_art": cover_art,
}
)
return env