Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 500
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
8d81b5a591f2aaa87e368e2ea9cbFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
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(", ")}`); | ||||||
CopilotAI | ||||||
| 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
CopilotAI | ||
| }, | ||
| "max": { | ||
| "type": "integer", | ||
| "description": "Optional maximum number of labels to remove (default: 3)", | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
CopilotAIFeb 19, 2026
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).