Skip to content

Security vulnerabilities: Insecure dependencies, potential XSS, and missing integrity attributes #581

Description

@vitaly-andr

Summary

Ran an adversarial security review against master and verified each finding empirically. Three real supply-chain items independent of the trust model. Two PMP-XSS items relevant under any role-separated future.

A note on the threat model upfront: many XSS vectors require attacker control over PMP, which is currently centrally administered via zerocracy.com (effectively single-admin). Under that model, exploitation requires compromising the central server first — and at that point the server admin has many bigger problems than dashboard XSS. However, if Zerocracy ever adds multi-tenant PMP, role-separated admins, or any other path where a less-privileged actor can write PMP fields, the XSS findings below activate immediately. Treating them as future-proofing rather than skip — listed for awareness even though the current model limits exploitability.

Supply-chain (independent of trust model)

1. action.yml:9 — Docker image pinned to :latest

image: 'docker://yegor256/pages-action:latest'

uses: zerocracy/pages-action@<tag> still pulls whatever is at :latest on Docker Hub. A compromised Docker Hub credential pushes a new :latest, every consumer's next run executes it with ${{ github.token }}.

Note that even an exact tag like :0.7.0 is mutable on Docker Hub — anyone with push access can re-tag the same name to a different image, and consumers won't notice. The robust pin is by content digest:

image: 'docker://yegor256/pages-action@sha256:abc123...'

The SHA-256 digest is the hash of the image manifest, immutable by construction. This mirrors the GitHub Actions convention of pinning uses: to a commit SHA rather than a branch or tag.

2. Gemfile:6 — RubyGems source over plain HTTP

source 'http://rubygems.org'

One-character fix to https. bundle install runs during Docker image build; rubygems.org redirects HTTP→HTTPS in practice, but the declared URL is the initial connection.

3. xsl/vitals.xsl:172-183 — four CDN scripts without SRI

jQuery, jquery.tablesorter, chart.js, chroma-js. The CSS files in the same template already use build-time-computed integrity="sha384-..." hashes (entry.sh handles the hashing); the JS includes don't. Additionally, cdn.jsdelivr.net/npm/chart.js has no version pin — auto-floats to whatever latest resolves to. CDN compromise hits every visitor of every published dashboard.

XSS vectors (relevant under any role-separated PMP future)

4. xsl/bylaws.xsl:21bylaws/html rendered with disable-output-escaping="yes"

Pipeline: PMP (award ...) text → Fbe::Award.bylaw.markdownRedcarpet::Render::HTML (default settings pass inline HTML through) → fact bylaws/html → XSL inserts raw.

Today: only triggered by malicious PMP content (centrally controlled).
Future-proofing: if any non-trusted actor can ever write (award) policy, <script> in markdown text becomes stored XSS on every dashboard. Fix candidates: Redcarpet::Render::HTML.new(escape_html: true, filter_html: true), or run output through Sanitize, or use a markdown renderer that already escapes.

5. xsl/awards.xsl:404-409<a href> accepts any URL scheme

Award href field is copied verbatim into the anchor.

Today: only triggered by malicious PMP content.
Future-proofing: if href ever becomes settable from less-privileged sources (e.g. user-submitted links, federated PMP, etc), javascript:alert(1) executes on click. Fix: allowlist https://github.com/... plus any other intended schemes, reject otherwise.

Cosmetic

  • xsl/badge.xsl $avg declared without as="xs:double". RTF coerced to string then number for comparisons; if $sum / $count ever produces NaN or Infinity, badge color/width silently wrong. No data integrity issue, just visual drift.

What I'd offer

Ready to send small PRs for any of #1#5. Happy to start with the supply-chain three (Docker digest pin, Gemfile https, JS SRI), they are unconditional wins. The XSS hardening pair (#4 #5) is also straightforward if you want preemptive coverage. Let me know which direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions