Back to skill

Security audit

Build Transparency Dashboard

Security checks for vulnerabilities and agentic risk

Overview

The skill largely does what it claims, but it asks for an overly broad GitHub token and includes public-facing code with security weaknesses that should be reviewed before use.

Review before installing. Use a fine-grained PAT or GitHub App limited to the single public site repo, avoid publishing raw sensitive commit messages, fix the dashboard rendering to use textContent or strict sanitization, and add rate limits/moderation plus clear privacy disclosure for idea submissions and voting.

Vulnerability Patterns
  • Unauthorized Access and Privilege EscalationObtains permissions beyond the task's legitimate needs
  • Insecure Skill Coding PracticesFinds exploitable flaws such as hardcoded secrets or command injection
  • Skill Instruction HijackingAlters the agent's session goals or safety constraints when the skill loads
  • Agent Memory PoisoningWrites attacker-controlled rules into memory that affect later sessions
  • Remote Payload Retrieval and ExecutionFetches external code whose behavior can change after review
Findings (3)

T05 · Unauthorized Access and Privilege Escalation

Error
Location
assets/github-actions.yml:13
Finding

Overprivileged Classic GitHub Personal Access Token

Content
View full analysis
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Error
Location
assets/build.html:884
Finding

Stored DOM Cross-Site Scripting Through Untrusted status.json Fields

Content
View full analysis
`
${item.date || ''}
${escHtml(item.text)}
${(item.type || 'feature').toUpperCase()}
`).join(''); } // Queue if (s.queue?.length) { const list = document.getElementById('queueList'); list.innerHTML = s.queue.map(item => `
${item.num || '—'}
${escHtml(item.title)}
${escHtml(item.desc)}
`).join(''); ``` The relevant escaping helper is: ```javascript function escHtml(str) { return String(str || '').replace(//g, '>'); } ``` ### Technical Analysis The dashboard fetches `/status.json` and inserts several fields into HTML templates assigned to `innerHTML`. The following fields are not escaped: - `shipped[].date` - `shipped[].type` - `queue[].num` Consequently, markup in these values is parsed as HTML. For example, a malicious `date` value such as an image element with an error event handler can execute JavaScript when the dashboard renders it. The `type` field is additionally inserted into an HTML attribute and into element content. Even the fields passed through `escHtml()` are protected only by replacing angle brackets. That helper is not a general context-aware sanitizer and would be unsafe if reused in attribute, URL, script, or style contexts. Because `status.json` is stored in a public site repository and is updated ...[truncated 1741 chars]
Remediation
View remediation

T09 · Insecure Skill Coding Practices

Warning
Location
scripts/ideas-api.js:65
Finding

Unauthenticated Ideas API Permits Spam, Vote Manipulation, and Storage Exhaustion

Content
View full analysis
{ const { text, author } = req.body || {}; if (!text || text.trim().length < 5) { return res.status(400).json({ error: 'Idea must be at least 5 characters.' }); } const ideas = loadIdeas(); const idea = { id: crypto.randomBytes(8).toString('hex'), text: text.trim().slice(0, 160), author: (author || 'anon').trim().slice(0, 30), votes: 1, createdAt: new Date().toISOString(), }; ideas.push(idea); saveIdeas(ideas); res.status(201).json(idea); }); // POST /public/ideas/:id/vote — upvote an idea router.post('/:id/vote', (req, res) => { const ideas = loadIdeas(); const idea = ideas.find(i => i.id === req.params.id); if (!idea) { return res.status(404).json({ error: 'Idea not found.' }); } idea.votes = (idea.votes || 0) + 1; saveIdeas(ideas); res.json(idea); }); ``` The browser-side vote restriction is only local state: ```javascript const voted = new Set(JSON.parse(localStorage.getItem('build_dashboard_voted') || '[]')); function saveVoted() { localStorage.setItem('build_dashboard_voted', JSON.stringify([...voted])); } ``` ### Technical Analysis Both idea creation and voting are intentionally public, but the implementation provides no server-side controls against automated abuse. It lacks: - Authentication or proof of user identity. - Per-client or global rate limiting. - CAPTCHA or bot mitigation. - Server-side vote uniqueness. - Maximum idea count or storage quota. - Request concurrency controls. - Atomic or transactional file updates. - Moderation and spam filtering. The `localStorage` vote set only affects the provided browser interface. An attacker c ...[truncated 2169 chars]
Remediation
View remediation
Vulnerability Patterns
  • Prompt InjectionInstruction Override, Hidden Instructions, Exfiltration Commands
  • Data ExfiltrationExternal Transmission, Env Variable Harvesting, File System Enumeration
  • Privilege EscalationExcessive Permissions, Sudo/Root Execution, Credential Access
  • Excessive AgencyUnrestricted Tool Access, Autonomous Decision Making, Scope Creep
  • Supply ChainUnpinned Dependencies, External Script Fetching, Obfuscated Code
Findings (20)

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 45)May include surrounding context.

md
In `assets/build.html`, search for these TODOs:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 87)May include surrounding context.

md
In `assets/build.html`, search for these TODOs:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 98)May include surrounding context.

md
In `assets/build.html`, search for these TODOs:

Ae1

High
Category
analysis-evasion
Confidence
100% confidence
Finding

Referenced artifact was not completely inspected

Content

Scanner excerpt · SKILL.md (reported line 147)May include surrounding context.

md
In `assets/build.html`, search for these TODOs:

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/build.html (reported line 6)May include surrounding context.

html
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- TODO: Replace YOUR_PROJECT_NAME throughout this file -->
<title>The Build — YOUR_PROJECT_NAME</title>
<meta name="description" content="Watch YOUR_PROJECT_NAME being built in real time. Live progress, shipped features, community ideas.">
<link rel="preconnect" href="https://fonts.googleapis.com">

Hidden Instructions

High
Category
Prompt Injection
Confidence
70% confidence
Finding

Hidden instructions were detected in comments or invisible text. These could contain malicious directives. Manual review is recommended.

Content

Scanner excerpt · assets/build.html (reported line 670)May include surrounding context.

html
<!-- ══════════════════════════════════════════════════════════ -->
  <!-- SECTION 2: SHIPPED LOG + UP NEXT QUEUE                   -->
  <!-- ══════════════════════════════════════════════════════════ -->
  <section class="section">
    <div class="two-col">

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · SKILL.md (reported line 83)May include surrounding context.

md
#   5. (Optional) Deploys the public site to Fly.io
#
# Required secrets (Settings → Secrets and variables → Actions):
#   GH_PAT          — GitHub Personal Access Token with "repo" scope
#                     (needs write access to the public site repo)
#   FLY_API_TOKEN   — (optional) Fly.io API token, only if deploying via Fly
#

Credential Access

High
Category
Privilege Escalation
Confidence
70% confidence
Finding

Code accesses credential files (SSH keys, AWS credentials, etc.). This could indicate credential theft attempts.

Content

Scanner excerpt · assets/github-actions.yml (reported line 14)May include surrounding context.

yaml
#   5. (Optional) Deploys the public site to Fly.io
#
# Required secrets (Settings → Secrets and variables → Actions):
#   GH_PAT          — GitHub Personal Access Token with "repo" scope
#                     (needs write access to the public site repo)
#   FLY_API_TOKEN   — (optional) Fly.io API token, only if deploying via Fly
#

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The guide instructs users to create a classic personal access token with repo scope, which is a powerful credential covering private repository operations. In the context of a workflow that checks out a private repo and pushes to another repo, compromise of that secret could allow code tampering, repository access, or lateral movement across repositories accessible by the token.

Content

Scanner excerpt · references/setup-guide.md (reported line 58)May include surrounding context.

md
| Secret | Value |
|--------|-------|
| `GH_PAT` | A Personal Access Token (classic) with **`repo`** scope. Create at: github.com/settings/tokens |
| `FLY_API_TOKEN` | (optional) Fly.io API token — only if you deploy via Fly |

**Create a PAT:**

Credential Access

High
Category
Privilege Escalation
Confidence
97% confidence
Finding

The step-by-step instruction to generate a classic PAT with repo scope normalizes creation of an overprivileged credential without warning about blast radius. Because this guide is for automating cross-repository updates from a private repository, the token becomes especially sensitive: misuse could expose private code history or permit unauthorized writes to repositories the token can access.

Content

Scanner excerpt · references/setup-guide.md (reported line 62)May include surrounding context.

md
| `FLY_API_TOKEN` | (optional) Fly.io API token — only if you deploy via Fly |

**Create a PAT:**
1. github.com → Settings → Developer settings → Personal access tokens → Tokens (classic)
2. Generate new token → select `repo` scope → copy the value
3. Add as `GH_PAT` secret in your private repo

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
92% confidence
Finding

The skill explicitly promotes publishing metadata derived from a private repository to a public dashboard, but it does not warn users that commit messages, timing, cadence, and activity patterns can disclose sensitive operational or business information. Even without source exposure, commit metadata can reveal internal project names, features in progress, incident response activity, or release timing to competitors and attackers.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The skill tells users to create a Personal Access Token with broad repo scope, but gives no warning about the sensitivity of that credential or the risks if it is exfiltrated from GitHub Actions or misconfigured. A compromised PAT with repo scope can enable unauthorized reads/writes across repositories accessible to the token, leading to code tampering, data exposure, or supply-chain compromise.

Content

No source excerpt is available for this finding.

External Transmission

Medium
Category
Data Exfiltration
Confidence
50% confidence
Finding

Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.

Content

Scanner excerpt · assets/build.html (reported line 925)May include surrounding context.

html
async function fetchCoin() {
  if (!COIN_CA || COIN_CA === 'YOUR_COIN_CA') return;
  try {
    const r = await fetch(`https://api.dexscreener.com/latest/dex/tokens/${COIN_CA}`);
    const d = await r.json();
    const p = d.pairs?.[0];
    if (!p) return;

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The page sends user-provided idea text and optional handle to a configurable external API endpoint without any in-UI notice, consent flow, or explanation of where the data goes. While this is not code execution, it is a real privacy and data-transmission issue because users may submit identifying or sensitive content under the assumption it stays local to the site.

Content

No source excerpt is available for this finding.

Missing User Warnings

Medium
Category
Not specified by scanner
Confidence
95% confidence
Finding

The guide explicitly instructs users to create a classic GitHub PAT with broad repo scope and store it as a repository secret, but it does not emphasize least privilege, token rotation, or safer alternatives like the built-in GITHUB_TOKEN or a fine-grained PAT limited to a single repository. If that token is exposed through workflow misuse, logging, or a compromised action, it could grant broad access to private repositories and enable unauthorized code changes or data exposure.

Content

No source excerpt is available for this finding.

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/setup-guide.md (reported line 183)May include surrounding context.

md
Then deploy: `fly deploy --remote-only --depot=false`

To also auto-deploy via GitHub Actions, uncomment the Fly deploy step in the workflow and add `FLY_API_TOKEN` to secrets.

### Option B: Netlify

Autonomous Decision Making

Medium
Category
Excessive Agency
Confidence
85% confidence
Finding

Skill enables autonomous high-impact decisions without human-in-the-loop verification. Critical operations (destructive commands, financial transactions, data deletion) should require explicit user confirmation.

Content

Scanner excerpt · references/setup-guide.md (reported line 190)May include surrounding context.

md
Then deploy: `fly deploy --remote-only --depot=false`

To also auto-deploy via GitHub Actions, uncomment the Fly deploy step in the workflow and add `FLY_API_TOKEN` to secrets.

### Option B: Netlify

Natural-Language Policy Violations

Low
Category
Not specified by scanner
Confidence
97% confidence
Finding

The code explicitly formats dates with the 'en-US' locale, which imposes a specific language/locale choice on all users. The policy requires either user opt-in/choice or a clearly documented justification for locale constraints.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
88% confidence
Finding

Clicking the vote button causes a POST request to an external API, transmitting user interaction data without informing the user. The transmitted data is limited, but it still reveals behavior and can contribute to tracking or profiling when combined with server logs or IP data.

Content

No source excerpt is available for this finding.

Missing User Warnings

Low
Category
Not specified by scanner
Confidence
84% confidence
Finding

This code performs a DOM write by assigning a constructed HTML string to nav.innerHTML. Under the code-file warning rule, file writes or similar state-changing operations should have some visible disclosure, comment, or documented warning; while the file is commented generally, it does not explicitly warn that it injects markup into the page at runtime.

Content

No source excerpt is available for this finding.

Static analysis

Detected: suspicious.dangerous_exec

Shell command execution detected (child_process).

Critical
Code
suspicious.dangerous_exec
Location
scripts/update-status.js:37