/** * GUARDiA Messenger — 보안 유틸 (현장서비스 모듈 공용) * * 보안 원칙 (불변): * - 서버 IP(ip_addr), SSH 계정(ssh_user), 비밀번호(os_pw_enc)는 화면에 절대 노출 금지 * - 배치 SSH / 터미널 출력의 IP 패턴은 자동 마스킹 * - 파일 경로 traversal(`../`) 입력 차단 */ /** IPv4 패턴 — 출력 텍스트에서 자동 마스킹 처리 */ const IPV4_RE = /\b(?:\d{1,3})\.(?:\d{1,3})\.(?:\d{1,3})\.(?:\d{1,3})\b/g /** 텍스트 내 IPv4 주소를 ***.***.***.*** 로 마스킹 */ export function maskIPs(text: string): string { if (!text) return text return text.replace(IPV4_RE, '***.***.***.***') } /** 위험 명령어 블랙리스트 — 클라이언트단 1차 차단 */ export const BLOCKED_COMMANDS = [ 'rm -rf /', 'mkfs', 'dd if=/dev/zero', 'shutdown -h', 'shutdown -r', 'reboot', ':(){:|:&};:', '> /dev/sda', 'chmod -R 000 /', 'mv /home', ] /** 명령어 안전성 검사 — 위험 패턴 포함 시 false */ export function validateCommand(cmd: string): boolean { if (!cmd || !cmd.trim()) return false const normalized = cmd.replace(/\s+/g, ' ').trim() return !BLOCKED_COMMANDS.some((b) => normalized.includes(b)) } /** 차단된 위험 패턴을 반환(있으면), 없으면 null */ export function blockedReason(cmd: string): string | null { const normalized = cmd.replace(/\s+/g, ' ').trim() const hit = BLOCKED_COMMANDS.find((b) => normalized.includes(b)) return hit ?? null } /** 경로 traversal 차단 — `../`, `..\`, 또는 null byte 포함 시 false */ export function isSafePath(path: string): boolean { if (!path) return true if (path.includes('..')) return false if (path.includes('\0')) return false return true } /** * 자산/서버 객체에서 민감 필드를 제거한 안전 복사본 반환. * API 응답에 혹시라도 ip_addr/ssh_user/os_pw_enc가 포함되어도 화면에 닿지 않게 한다. */ export function sanitizeAsset>(obj: T): Partial { if (!obj || typeof obj !== 'object') return obj const SENSITIVE = ['ip_addr', 'ip_address', 'ssh_user', 'ssh_pass', 'os_pw', 'os_pw_enc', 'password', 'private_key'] const out: Record = {} for (const [k, v] of Object.entries(obj)) { if (SENSITIVE.includes(k)) continue out[k] = v } return out as Partial }