CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/visual-baseline-gate

Consumes pre-classified visual-diff JSON and a reviewer-signed acceptance log to produce a single go/no-go CI verdict for visual regression. Blocks when intentional baseline changes lack a non-author reviewer sign-off or when regressions are present, and emits the binding gate artifacts - visual-gate.json + visual-gate.md - with fail-closed handling of a missing classifier run and author-cannot-self-approve enforcement, so the pipeline can exit non-zero on BLOCK. Use when the gate's input is pre-classified diff data and the enforcement concern is reviewer approval and a binding CI verdict.

75

Quality

94%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

Low

Low-risk findings.

1 low severity finding. Worth noting, but not necessarily harmful.

Low

W011: Third-party content exposure detected (indirect prompt injection risk).

What this means

The skill exposes the agent to untrusted, user-generated content from public third-party sources, creating a risk of indirect prompt injection. This includes browsing arbitrary URLs, reading social media posts or forum comments, and analyzing content from unknown websites.

Why it was flagged

In `references/artifact-and-ci-wiring.md`, the CI entrypoint `scripts/run_visual_gate.py` ingests free-text-y YAML from the PR branch at `.visual-acceptance.yml` and JSON from `visual-classifications.json` via `yaml.safe_load(...read_text())` and `json.loads(...read_text())`, meaning an outsider who can author/publish PR content can supply that text for the workflow to read.

Where we found it

.visual-acceptance.yml

content-type · 2 sites

The CI entrypoint ingests free-text YAML from `.visual-acceptance.yml` on the PR branch via yaml.safe_load(); an outsider who can author PR content controls this file's contents, creating an indirect prompt-injection surface.

references/artifact-and-ci-wiring.md

65

acceptance = yaml.safe_load(ACCEPT_PATH.read_text()) if ACCEPT_PATH.exists() else {"snapshots": []}

references/artifact-and-ci-wiring.md

58

ACCEPT_PATH = Path(".visual-acceptance.yml")

visual-classifications.json

content-type · 2 sites

The CI entrypoint ingests JSON from `visual-classifications.json` on the PR branch via json.loads(); an outsider who can author PR content controls this file, and its field values (engine, snapshot) are interpolated into printed output, creating an indirect prompt-injection surface.

references/artifact-and-ci-wiring.md

64

classifications = json.loads(CLASS_PATH.read_text())

references/artifact-and-ci-wiring.md

57

CLASS_PATH = Path("visual-classifications.json") # output of the visual-diff classification step

Report incorrect finding
Audited
Security analysis
Snyk