forked from claude-did-this/claude-hub
* fix: merge entrypoint scripts and fix auto-tagging tool permissions - Merged duplicate claudecode-entrypoint.sh and claudecode-tagging-entrypoint.sh scripts - Added dynamic tool selection based on OPERATION_TYPE environment variable - Fixed auto-tagging permissions to include required Bash(gh:*) commands - Removed 95% code duplication between entrypoint scripts - Simplified claudeService.ts to use unified entrypoint - Auto-tagging now uses: Read,GitHub,Bash(gh issue edit:*),Bash(gh issue view:*),Bash(gh label list:*) - General operations continue to use full tool set 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: update Dockerfile to use unified entrypoint script - Remove references to deleted claudecode-tagging-entrypoint.sh - Update build process to use single unified entrypoint script * fix: remove unnecessary async from promisify mock to fix lint error * feat: add Husky pre-commit hooks with Prettier as primary formatter - Added Husky for Git pre-commit hooks - Configured eslint-config-prettier to avoid ESLint/Prettier conflicts - Prettier handles all formatting, ESLint handles code quality only - Pre-commit hooks: Prettier format, ESLint check, TypeScript check - Updated documentation with pre-commit hook setup - All code quality issues resolved * feat: consolidate workflows and fix permission issues with clean Docker runners - Replace 3 complex workflows with 2 lean ones (pull-request.yml, main.yml) - Add Docker runner configuration for clean, isolated builds - Remove file permission hacks - use ephemeral containers instead - Split workload: GitHub-hosted for tests/security, self-hosted for Docker builds - Add comprehensive pre-commit configuration for security - Update documentation to be more pragmatic - Fix credential file permissions and security audit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: allow Husky prepare script to fail in production builds 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: update CI badge to reference new main.yml workflow 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
104 lines
3.0 KiB
TypeScript
104 lines
3.0 KiB
TypeScript
import { createLogger } from './logger';
|
|
|
|
const logger = createLogger('sanitize');
|
|
|
|
/**
|
|
* Sanitizes text to prevent infinite loops by removing bot username mentions
|
|
*/
|
|
export function sanitizeBotMentions(text: string): string {
|
|
if (!text) return text;
|
|
|
|
// Get bot username from environment variables - required
|
|
const BOT_USERNAME = process.env['BOT_USERNAME'];
|
|
|
|
if (!BOT_USERNAME) {
|
|
logger.warn('BOT_USERNAME environment variable is not set. Cannot sanitize properly.');
|
|
return text;
|
|
}
|
|
|
|
// Create a regex to find all bot username mentions
|
|
// First escape any special regex characters
|
|
const escapedUsername = BOT_USERNAME.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
|
|
// Look for the username with @ symbol anywhere in the text
|
|
const botMentionRegex = new RegExp(escapedUsername, 'gi');
|
|
|
|
// Replace mentions with a sanitized version (remove @ symbol if present)
|
|
const sanitizedName = BOT_USERNAME.startsWith('@') ? BOT_USERNAME.substring(1) : BOT_USERNAME;
|
|
const sanitized = text.replace(botMentionRegex, sanitizedName);
|
|
|
|
// If sanitization occurred, log it
|
|
if (sanitized !== text) {
|
|
logger.warn('Sanitized bot mentions from text to prevent infinite loops');
|
|
}
|
|
|
|
return sanitized;
|
|
}
|
|
|
|
/**
|
|
* Sanitizes an array of labels to remove potentially sensitive or invalid characters
|
|
*/
|
|
export function sanitizeLabels(labels: string[]): string[] {
|
|
return labels.map(label => label.replace(/[^a-zA-Z0-9:_-]/g, ''));
|
|
}
|
|
|
|
/**
|
|
* Sanitizes input for safe usage in commands and prevents injection attacks
|
|
*/
|
|
export function sanitizeCommandInput(input: string): string {
|
|
if (!input) return input;
|
|
|
|
// Remove or escape potentially dangerous characters
|
|
return input
|
|
.replace(/[`$\\]/g, '') // Remove backticks, dollar signs, and backslashes
|
|
.replace(/[;&|><]/g, '') // Remove command injection characters
|
|
.trim();
|
|
}
|
|
|
|
/**
|
|
* Validates that a string contains only safe repository name characters
|
|
*/
|
|
export function validateRepositoryName(name: string): boolean {
|
|
const repoPattern = /^[a-zA-Z0-9._-]+$/;
|
|
return repoPattern.test(name);
|
|
}
|
|
|
|
/**
|
|
* Validates that a string contains only safe GitHub reference characters
|
|
*/
|
|
export function validateGitHubRef(ref: string): boolean {
|
|
// GitHub refs cannot:
|
|
// - be empty
|
|
// - contain consecutive dots (..)
|
|
// - contain spaces or special characters like @ or #
|
|
if (!ref || ref.includes('..') || ref.includes(' ') || ref.includes('@') || ref.includes('#')) {
|
|
return false;
|
|
}
|
|
|
|
// Must contain only allowed characters
|
|
const refPattern = /^[a-zA-Z0-9._/-]+$/;
|
|
return refPattern.test(ref);
|
|
}
|
|
|
|
/**
|
|
* Sanitizes environment variable values for logging
|
|
*/
|
|
export function sanitizeEnvironmentValue(key: string, value: string): string {
|
|
const sensitiveKeys = [
|
|
'TOKEN',
|
|
'SECRET',
|
|
'KEY',
|
|
'PASSWORD',
|
|
'CREDENTIAL',
|
|
'GITHUB_TOKEN',
|
|
'ANTHROPIC_API_KEY',
|
|
'AWS_ACCESS_KEY_ID',
|
|
'AWS_SECRET_ACCESS_KEY',
|
|
'WEBHOOK_SECRET'
|
|
];
|
|
|
|
const isSensitive = sensitiveKeys.some(sensitiveKey => key.toUpperCase().includes(sensitiveKey));
|
|
|
|
return isSensitive ? '[REDACTED]' : value;
|
|
}
|