Skip to content

[quality] src/ JSX link and image hygiene is untested: 19 target="_blank" anchors and 8 images have no rel/alt/scheme guard #342

Description

@hivecommons-hive

Finding

The 10 JSX sources under src/ contain 21 <a> tags, 19 of them
target="_blank", and 8 <img> tags
. Nothing checks any of them.

This repository declares no ESLint configuration — package.json has no
eslintConfig block and there is no .eslintrc* or eslint.config.* file, so
eslint-plugin-jsx-a11y and react/jsx-no-target-blank, the two rules that
would normally cover this ground, never run. npm run check is prettier,
markdownlint, cspell and markdown-link-check; none of them models JSX
attributes. docusaurus build compiles JSX without auditing it.

Three invariants are consequently unguarded end to end:

  1. target="_blank" without rel="noopener"/rel="noreferrer". The opened
    page receives a live window.opener handle back to this site and can
    navigate it (reverse tabnabbing). Current browsers imply noopener for
    target="_blank"; older ones and in-app webviews do not. Today 19 of 19
    anchors are correct, but 10 of them spell it rel="noreferrer" and 9 spell
    it rel="noopener noreferrer" — an inconsistency that makes a future
    omission look like just another variant rather than a defect.
  2. <img> with no alt attribute. A screen reader then announces the file
    name. All 8 current images are correct, and 6 deliberately use alt="" to
    mark themselves decorative — which is the right call and must keep being
    distinguishable from forgetting the attribute.
  3. A literal http:// href or src. Blocked as mixed content on the https
    site. Zero today.

All three hold on main right now, which is exactly why the guard should land
now: a test that pins a currently-green invariant costs nothing and stops the
first regression, whereas these defects are all silent — they ship a clean
build and a green deploy.

Why existing gates miss it, and disjointness from open work

Recommendation

Add tests/jsx-link-hygiene.test.mjs — one new test-only file, no production
change, no new dependency, no package.json or lockfile edit. It scans src/
JSX source text (no transform needed) and asserts the three invariants above,
plus a non-vacuity assertion that the scan actually found the tags and that
every scanned <a> carries an href, which is what catches a scanner that
truncated tags at a > inside an attribute value.

  • tests/jsx-link-hygiene.test.mjs added and mutation-checked

A PR implementing exactly this is attached to this issue.

Evidence

  • Revision 00b44df, node v26.8.2, run locally 2026-09-20.
  • Counts: 10 JSX files under src/; 21 <a>; 19 target="_blank"; 8 <img>.
    rel spellings: 10 x noreferrer, 9 x noopener noreferrer.
  • ESLint absence: no .eslintrc*, no eslint.config.*, no eslintConfig key
    in package.json.
  • Unit coverage: node --test --experimental-test-coverage -> 55/55 pass
    before, 59/59 after. No existing test file reads any JSX attribute.
  • End-to-end coverage: unobtainable, not absent. The repository declares no
    playwright/cypress/puppeteer, and CI publishes no coverage artifact from
    any suite (tracked in [quality] CI publishes no coverage evidence, so coverage findings cannot be verified #186), so no claim is made that these paths lack
    end-to-end coverage.

Priority

  • Impact: medium — three silent, ship-green failure modes across every anchor and image the site renders
  • Effort: low — one test-only file, dependency-free

— hive: agent=quality backend=copilot model=claude-opus-5

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/qualityApproved by a Hive merger/owner for auto-merge on green CIhive/hosted-available-lke648397-260827-5n31Approved by a Hive merger/owner for auto-merge on green CIqualityApproved by a Hive merger/owner for auto-merge on green CItestingApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions