-
Notifications
You must be signed in to change notification settings - Fork 241
Add blocked pattern matching for add-labels and remove-labels #16690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
8d81b5a
591f2aa
a87e368
e2ea9cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -84,9 +84,10 @@ function validateBody(body, fieldName = "body", required = false) { | |||||
| * @param {any} labels - The labels to validate | ||||||
| * @param {string[]|undefined} allowedLabels - Optional list of allowed labels | ||||||
| * @param {number} maxCount - Maximum number of labels allowed | ||||||
| * @param {string[]|undefined} blockedPatterns - Optional list of blocked label patterns (supports glob patterns like "~*", "*[bot]") | ||||||
| * @returns {{valid: boolean, value?: string[], error?: string}} Validation result | ||||||
| */ | ||||||
| function validateLabels(labels, allowedLabels = undefined, maxCount = 3) { | ||||||
| function validateLabels(labels, allowedLabels = undefined, maxCount = 3, blockedPatterns = undefined) { | ||||||
| if (!labels || !Array.isArray(labels)) { | ||||||
| return { valid: false, error: "labels must be an array" }; | ||||||
| } | ||||||
|
|
@@ -98,10 +99,27 @@ function validateLabels(labels, allowedLabels = undefined, maxCount = 3) { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| // Filter labels based on allowed list if provided | ||||||
| // Filter out blocked labels first (security boundary) | ||||||
| let validLabels = labels; | ||||||
| if (blockedPatterns && blockedPatterns.length > 0) { | ||||||
| const { matchesSimpleGlob } = require("./glob_pattern_helpers.cjs"); | ||||||
| const blockedLabels = []; | ||||||
| validLabels = labels.filter(label => { | ||||||
| const labelStr = String(label).trim(); | ||||||
| const isBlocked = blockedPatterns.some(pattern => matchesSimpleGlob(labelStr, pattern)); | ||||||
| if (isBlocked) { | ||||||
| blockedLabels.push(labelStr); | ||||||
| } | ||||||
| return !isBlocked; | ||||||
| }); | ||||||
| if (blockedLabels.length > 0) { | ||||||
| core.info(`Filtered out ${blockedLabels.length} blocked labels: ${blockedLabels.join(", ")}`); | ||||||
|
||||||
| core.info(`Filtered out ${blockedLabels.length} blocked labels: ${blockedLabels.join(", ")}`); | |
| core.info(`Filtered out ${blockedLabels.length} blocked labels: ${JSON.stringify(blockedLabels)}`); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5232,6 +5232,15 @@ | |
| "minItems": 1, | ||
| "maxItems": 50 | ||
| }, | ||
| "blocked": { | ||
| "type": "array", | ||
| "description": "Optional list of blocked label patterns (supports glob patterns like '~*', '*[bot]'). Labels matching these patterns will be rejected. Applied before allowed list filtering for security.", | ||
| "items": { | ||
| "type": "string" | ||
| }, | ||
| "minItems": 1, | ||
| "maxItems": 50 | ||
| }, | ||
| "max": { | ||
| "type": "integer", | ||
| "description": "Optional maximum number of labels to add (default: 3)", | ||
|
|
@@ -5281,6 +5290,15 @@ | |
| "minItems": 1, | ||
| "maxItems": 50 | ||
| }, | ||
| "blocked": { | ||
| "type": "array", | ||
| "description": "Optional list of blocked label patterns (supports glob patterns like '~*', '*[bot]'). Labels matching these patterns will be rejected. Applied before allowed list filtering for security.", | ||
| "items": { | ||
| "type": "string" | ||
| }, | ||
| "minItems": 1, | ||
| "maxItems": 50 | ||
|
Comment on lines
+5293
to
+5300
|
||
| }, | ||
| "max": { | ||
| "type": "integer", | ||
| "description": "Optional maximum number of labels to remove (default: 3)", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocked-pattern matching is currently performed on
labelStr = String(label).trim()beforesanitizeLabelContent/Unicode hardening. SincesanitizeLabelContentremoves zero-width chars and normalizes text, a label like~\u200bstalecould evade the~*blocked pattern check and then be normalized to~stalelater, defeating the security boundary. Consider normalizing/sanitizing the label string (at leasthardenUnicodeText, or reusesanitizeLabelContent) before evaluating blocked patterns (and ideally use the same normalized value for subsequent allowlist checks).