Skip to content

fix(security): Remediate 16 audit findings in intake workflows#5

Closed
michaeloboyle wants to merge 8 commits intoagenticsorg:mainfrom
michaeloboyle:fix/security-remediation
Closed

fix(security): Remediate 16 audit findings in intake workflows#5
michaeloboyle wants to merge 8 commits intoagenticsorg:mainfrom
michaeloboyle:fix/security-remediation

Conversation

@michaeloboyle
Copy link
Copy Markdown

Summary

Remediates all 16 security findings from the audit review of PR #4.

CRITICAL (2 fixed)

  • SEC-001/002: Replaced core.exportVariable() with core.setOutput() in approve-project.yml and retraction.yml to eliminate shell injection pattern

HIGH (4 fixed)

  • SEC-003: Added author_association access control (MEMBER/OWNER/COLLABORATOR) to all 5 voting/scoring script blocks across 4 workflows
  • SEC-004/005: Added registry-update concurrency group, issue-based project IDs (proj-{issueNumber}), and git pull --rebase before push
  • SEC-006: Pinned all 10 action references to full SHA hashes, added .github/dependabot.yml

MEDIUM (5 fixed)

  • SEC-007/009: Added sanitize() function for user inputs, repo URL validation, JSON schema validation on registry read
  • SEC-008: Added per-issue concurrency groups to all comment-triggered workflows, rate limiting on bot tally posts
  • SEC-010: Changed validation vote tie-breaking to strict majority (> not >=), ties default to DEFERRED
  • SEC-011: Added /vote no-retract support, retraction requires majority of votes cast (not just quorum of retract votes)

LOW (3 fixed)

  • SEC-012: Submitter excluded from voting in escalation and validation workflows
  • SEC-013: Bot comments filtered from all vote tallies, fixed double-negative regex bug in escalation-vote.yml
  • SEC-014: Added repo format validation and confirmation prompt to setup-labels.sh

INFO (2 noted, not code changes)

  • SEC-015 (broad permissions) and SEC-016 (no immutable audit log) are documented for future improvement

Commits

  • bfb19ca SEC-003 add access control to voting and scoring workflows
  • 09ecfa3 SEC-001/002 replace core.exportVariable with core.setOutput
  • 8092372 SEC-007/009 add input sanitization and schema validation
  • 10feafa SEC-006 pin actions to SHA hashes, add dependabot
  • 02f3b3e SEC-008 add concurrency groups and rate limiting
  • 1f0d8bf SEC-010/011 strict majority tie-breaking, add no-retract voting
  • a5e2101 SEC-012/013/014 filter bots, exclude submitter, fix regex, harden script

Test plan

  • Open test submission issue, verify on-submission triage fires with sanitized name
  • Post /score as non-member, verify access denied
  • Post /score as member, verify parsing and table
  • Post /vote approve from issue submitter, verify excluded from tally
  • Test escalation and validation vote quorum with bot filtering
  • Test 1-1-1 tie results in DEFERRED (not APPROVED)
  • Test /vote no-retract flow
  • Verify concurrent approval doesn't corrupt registry
  • Run setup-labels.sh with invalid input, verify rejection

Closes security review on #4.

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

michaeloboyle and others added 8 commits March 5, 2026 08:20
Add GitHub issue template for project submissions, 6 workflows for
the full intake lifecycle (triage, scoring, escalation vote, validation
vote, approval registration, retraction), scoring template, label
setup script, and approved projects registry.

Implements the process defined in the Open Source Committee governance doc.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…lows

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…utput

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ct voting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…gex, harden script

- SEC-013: Add bot filtering to validation-vote.yml vote tallying
- SEC-012: Exclude issue author from voting in validation-vote.yml
- SEC-014: Add repo format validation and confirmation prompt to setup-labels.sh

Note: escalation-vote.yml and retraction.yml fixes were applied in prior commits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 17, 2026 22:20
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR remediates security audit findings across the project intake GitHub Actions workflows by tightening access control, reducing injection risk, and hardening registry update behavior, plus adding supporting docs and admin tooling for the intake process.

Changes:

  • Hardened issue-comment-driven workflows with concurrency controls, bot filtering, rate limiting, and updated voting semantics.
  • Added input sanitization and basic schema validation around registry read/write operations.
  • Pinned GitHub Actions to SHAs, added Dependabot for GitHub Actions, and added/update docs + label setup script.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
.github/workflows/on-submission.yml Adds sanitization and auto-triage labeling + welcome comment on new submissions.
.github/workflows/scoring.yml Adds member-gated /score parsing and auto-posted formatted score comments.
.github/workflows/escalation-vote.yml Adds member-gated escalation vote tallying with quorum, bot filtering, and rate limiting.
.github/workflows/validation-vote.yml Adds member-gated validation vote tallying with quorum, bot filtering, rate limiting, and updated outcome logic.
.github/workflows/approve-project.yml Registers approved projects into data/approved-projects.json with schema checks and concurrency protection.
.github/workflows/retraction.yml Adds /retract proposals and /vote retract vs /vote no-retract tallying with registry update + serialization.
.github/dependabot.yml Enables weekly Dependabot updates for GitHub Actions.
.github/ISSUE_TEMPLATE/project-submission.yml Adds structured issue form for project submissions.
.github/ISSUE_TEMPLATE/config.yml Disables blank issues and adds membership contact link.
scripts/setup-labels.sh Adds admin script to create/overwrite required labels with basic input validation.
docs/scoring-template.md Adds committee scoring rubric and command reference.
README.md Documents the intake workflow, commands, labels, and setup.
data/approved-projects.json Initializes approved projects registry.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +56 to +68
// Tally votes (one per unique user, last vote wins)
const votes = {};
for (const c of comments) {
if (c.user.type === 'Bot') continue;
if (c.user.login === submitter) continue;
const body = c.body.trim();
if (/^\/vote escalate\s*$/.test(body)) {
votes[c.user.login] = 'escalate';
}
if (/^\/vote no-escalate\s*$/.test(body)) {
votes[c.user.login] = 'no-escalate';
}
}
Comment on lines +57 to +66
// Tally votes (one per unique user, last vote wins)
const votes = {};
for (const c of comments) {
if (c.user.type === 'Bot') continue;
if (c.user.login === submitter) continue;
const body = c.body.trim();
if (/^\/vote approve\s*$/.test(body)) votes[c.user.login] = 'approve';
if (/^\/vote decline\s*$/.test(body)) votes[c.user.login] = 'decline';
if (/^\/vote defer\s*$/.test(body)) votes[c.user.login] = 'defer';
}
Comment on lines +109 to +117
// SEC-010: Strict majority required, ties default to DEFERRED
let outcome, outcomeLabel;
if (approve > decline && approve > defer) {
outcome = 'APPROVED';
outcomeLabel = 'status:approved';
} else if (decline > approve && decline > defer) {
outcome = 'DECLINED';
outcomeLabel = 'status:declined';
} else {
Comment on lines +103 to +117
// Count unique retraction and no-retract votes
const retractVoters = new Set();
const keepVoters = new Set();
for (const c of comments) {
if (c.user.type === 'Bot') continue;
const body = c.body.trim();
if (body === '/vote retract') {
retractVoters.add(c.user.login);
keepVoters.delete(c.user.login);
}
if (body === '/vote no-retract') {
keepVoters.add(c.user.login);
retractVoters.delete(c.user.login);
}
}
Comment on lines +43 to +48
for (const c of criteria) {
const match = comment.match(new RegExp(`${c}:\\s*(\\d)`));
if (match) {
const val = parseInt(match[1]);
if (val < 0 || val > 5) { valid = false; break; }
scores[c] = val;
Comment on lines +161 to +169
const idx = registry.findIndex(p => p.issue_number === issueNumber);
if (idx !== -1) {
registry[idx].status = 'retracted';
registry[idx].retracted_date = new Date().toISOString().split('T')[0];
fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2) + '\n');

core.setOutput('updated_registry', 'true');
core.setOutput('issue_number', String(issueNumber));
}
Comment on lines +101 to +116
// Generate ID from issue number (avoids race condition with registry.length)
const id = `proj-${String(issueNumber).padStart(3, '0')}`;

// Add entry
registry.push({
id,
name: sanitize(descText, 80) || `Submission #${issueNumber}`,
repo_url: repoUrl,
category,
approved_date: new Date().toISOString().split('T')[0],
submitter: context.payload.issue.user.login,
description: sanitize(descText, 500),
total_score: avgScore,
issue_number: issueNumber,
status: 'active'
});
// SEC-007: Sanitize user input before embedding in comments
function sanitize(input, maxLen = 100) {
return input
.replace(/[[\](){}|`*_~#>!\\]/g, '')
| `/vote decline` | Validation vote: decline the submission |
| `/vote defer` | Validation vote: defer pending more info |
| `/retract` | Propose retraction of a previously approved project |
| `/vote retract` | Vote to retract approval |
| `/retract` | Propose retraction of a previously approved project |
| `/vote retract` | Vote to retract approval |

All votes require a quorum of 3 and pass by simple majority.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants