보안 계층
TinyElf Agent 엔진은 도구 호출이 실행되기 전에 충분한 보안 검증을 거치도록 3계층 보안 파이프라인을 구현합니다. 세 계층은 순서대로 실행되며, 어느 계층에서든 거부되면 프로세스가 종료됩니다.
3계층 보안 파이프라인
graph TB
TC["Tool call request<br/>(toolName, args)"] --> L1
subgraph Layer1["Layer 1: ExecutionFirewall"]
L1["checkToolCall(name, args)"] --> L1a{"Path in deny list?"}
L1a -->|Yes| Block1["Block<br/>[firewall] Blocked"]
L1a -->|No| L1b{"Bash command contains deny path?"}
L1b -->|Yes| Block1
L1b -->|No| Pass1["Pass"]
end
Pass1 --> L2
subgraph Layer2["Layer 2: GuardianAgent"]
L2["review(name, args)"] --> L2a{"Mode = off?"}
L2a -->|Yes| Pass2a["Skip"]
L2a -->|No| L2b{"In review scope?"}
L2b -->|No| Pass2b["Skip"]
L2b -->|Yes| L2c["LLM risk assessment<br/>(15s timeout)"]
L2c --> L2d{"Risk level decision"}
L2d -->|"guard: high/critical"| Block2["Block<br/>[guardian] Blocked"]
L2d -->|"strict: medium+"| Block2
L2d -->|Allow| Pass2["Pass"]
end
Pass2 --> L3
Pass2a --> L3
Pass2b --> L3
subgraph Layer3["Layer 3: PermissionCallback"]
L3["isSensitiveTool(name)"] --> L3a{"Requires confirmation?"}
L3a -->|No| Pass3a["Auto-pass"]
L3a -->|Yes| L3b["Send confirmation request<br/>(5min timeout)"]
L3b --> L3c{"User reply"}
L3c -->|Allow| Pass3["Pass"]
L3c -->|AllowSession| Pass3s["Pass + cache"]
L3c -->|Deny/Timeout| Block3["Deny"]
end
Pass3 --> Exec["Execute tool"]
Pass3a --> Exec
Pass3s --> Exec
계층 1: ExecutionFirewall
ExecutionFirewall는 경로 패턴 규칙을 기반으로 민감한 시스템 리소스 접근을 차단하는 결정론적 보안 게이트웨이입니다.
인터페이스
class ExecutionFirewall {
constructor(workspacePath: string);
checkPath(filePath: string, operation?: 'read' | 'write'): FirewallCheckResult;
checkCommand(command: string): FirewallCheckResult;
checkToolCall(toolName: string, params: Record<string, unknown>): FirewallCheckResult;
setWorkspacePath(newPath: string): void;
}
interface FirewallCheckResult {
allowed: boolean;
deniedBy?: string;
reason?: string;
}
거부 경로 규칙
읽기와 쓰기 모두 거부
| 경로 패턴 | 이유 |
|---|---|
C:\Windows\ | Windows 시스템 디렉터리 |
C:\Program Files\ | 프로그램 설치 디렉터리 |
C:\ProgramData\ | 프로그램 데이터 디렉터리 |
C:\Recovery\ | 복구 파티션 |
/etc/ | 시스템 구성 디렉터리 |
/usr/ | 시스템 디렉터리 |
/sbin/ | 시스템 바이너리 |
/boot/ | 부트 디렉터리 |
/proc/ | 프로세스 의사 파일 시스템 |
/sys/ | 시스템 의사 파일 시스템 |
/dev/ | 디바이스 파일 |
.ssh/ | SSH 키 디렉터리 |
.gnupg/ | GPG 키 디렉터리 |
.aws/ | AWS 자격 증명 |
.azure/ | Azure 자격 증명 |
.gcloud/ | GCloud 자격 증명 |
.kube/config | Kubernetes 구성 |
.docker/config.json | Docker 구성 |
id_rsa, id_ed25519, id_ecdsa | SSH 개인 키 파일 |
.env, .env.* | 환경 변수 파일 |
credentials.json | 자격 증명 파일 |
service_account*.json | 서비스 계정 키 |
| Firefox/Chrome/Edge user data | 브라우저 구성 파일 |
System32\config\SAM/SYSTEM/... | Windows 레지스트리 |
쓰기만 거부(읽기 가능)
| 경로 패턴 | 이유 |
|---|---|
.gitconfig | Git 구성 |
.npmrc | npm 구성 |
.bashrc | Bash 구성 |
.zshrc | Zsh 구성 |
.profile | Shell 구성 |
.bash_profile | Bash 구성 |
도구 경로 매개변수 매핑
| 도구 | 추출된 경로 매개변수 | 작업 유형 |
|---|---|---|
Read | path, file_path | read |
Write | path, file_path | write |
Edit | path, file_path | write |
ListDir | path, dir_path | read |
명령 경로 추출
checkCommand()는 Shell 명령에서 경로를 추출하고 각각을 검사합니다.
- Windows 절대 경로:
C:\path\to\file - POSIX 절대 경로:
/path/to/file
계층 2: GuardianAgent
GuardianAgent는 LLM을 사용해 도구 호출의 보안 위험 평가를 수행합니다.
인터페이스
class GuardianAgent {
constructor(
config: GuardianAgentConfig,
llmAdapter: TinyElfLLMAdapter,
auditLogger?: AuditLogger,
sessionId?: string,
workspacePath?: string,
);
review(toolName: string, args: Record<string, unknown>): Promise<GuardianReviewResult>;
clearCache(): void;
}
interface GuardianReviewResult {
allowed: boolean;
riskLevel: RiskLevel; // 'none' | 'low' | 'medium' | 'high' | 'critical'
reason: string;
cached: boolean;
}
작업 모드
| 모드 | 검토 범위 | 차단 조건 | 제한 시간/오류 동작 |
|---|---|---|---|
off | 없음 | 차단 없음 | N/A |
monitor | 민감한 도구 | 차단 없음(로깅만) | N/A |
guard | 민감한 도구 | high, critical | Fail open(허용) |
strict | 모든 도구 | medium, high, critical | Fail closed(거부) |
민감한 도구 목록
const SENSITIVE_TOOLS = new Set(['Bash', 'Write', 'Edit', 'Agent']);
monitor와 guard 모드는 이 도구들만 검토합니다. strict 모드는 모든 도구를 검토합니다.
위험 수준
| 수준 | 의미 | 예시 |
|---|---|---|
none | 완전히 안전 | 워크스페이스 내부 파일 읽기 |
low | 낮은 위험 | 프로젝트 파일 쓰기 |
medium | 중간 위험 | 패키지 설치, 상태 수정 |
high | 높은 위험 | 워크스페이스 외부 작업, 네트워크 요청, 자격 증명 접근 |
critical | 치명적 위험 | 재귀 삭제, 권한 상승, 데이터 탈취 |
핵심 규칙(항상 high/critical로 표시)
- 워크스페이스 외부 파일 삭제
- 재귀 삭제 명령(
rm -rf,del /s /q,Remove-Item -Recurse) - 시스템 디렉터리 작업(
/etc,C:\Windows) - 사용자 개인 디렉터리 작업(Desktop, Documents)
- 권한 상승(
sudo,runas) - 파이프 실행(
curl | sh) - 보안 우회(
--no-verify,--force) - 자격 증명 접근
캐싱 전략
- 승인 결과를 캐시합니다(
sha256(toolName:args)의 처음 16비트를 키로 사용). - 허용 결과만 캐시합니다(거부 결과는 매번 다시 평가).
- 세션 종료 시 캐시를 지웁니다.
상수
| 상수 | 값 | 설명 |
|---|---|---|
GUARDIAN_TIMEOUT_MS | 15,000 | LLM 평가 제한 시간 |
계층 3: PermissionCallback
TinyElfPermissionManager
class TinyElfPermissionManager {
resolvePermission(requestId: string, result: PermissionResult): void;
cleanupSession(dbSessionId: string): void;
requestPermission(dbSessionId, sender, toolName, toolInput): Promise<PermissionResult>;
buildPermissionCallback(dbSessionId, sender, permissionMode, channelCtx, channelPermissionGate):
((toolName, toolInput) => Promise<PermissionResult>) | undefined;
}
interface PermissionResult {
behavior: 'allow' | 'deny' | 'allowSession';
message?: string;
}
권한 모드 동작
| 모드 | buildPermissionCallback 반환값 |
|---|---|
bypassPermissions | undefined(콜백을 주입하지 않으며 모든 도구가 자동 통과) |
default | Desktop 콜백 / Channel 콜백 |
acceptEdits | 기본값과 동일하지만 Write/Edit는 isSensitiveTool에서 false를 반환 |
세션 수준 화이트리스트
사용자가 allowSession을 선택하면 다음이 적용됩니다.
sessionAllowedTools: Map<string, Set<string>> // dbSessionId → Set<toolName>
이후 같은 도구 이름의 호출은 자동 통과합니다. 화이트리스트는 cleanupSession()에서 지워집니다.
제한 시간
- Desktop 모드: 5분 제한 시간 → 자동 거부
- Channel 모드: 5분 제한 시간 → 자동 거부
ChannelPermissionGate
Channel 시나리오의 권한 확인은 메시지 라우팅을 통해 구현됩니다.
확인 흐름
sequenceDiagram
participant A as TinyElfAgentLoop
participant G as ChannelPermissionGate
participant C as Channel (Discord/Telegram)
participant U as Channel User
A->>G: requestConfirmation(channelId, chatId, senderId, toolName, desc)
G->>G: Check always-allow list
alt Already in always-allow
G-->>A: true
else Not in list
G->>C: sendMessage("Confirmation needed: Bash: npm test")
C->>U: Display confirmation message
U->>C: Reply "y" / "n" / "always"
C->>G: processReply(channelId, chatId, senderId, "y")
G-->>A: true / false
end
지문 범위
always 응답의 범위는 buildToolFingerprint()로 결정됩니다.
fingerprint = `${toolName}:${description.slice(0, 120)}`
예를 들어 Bash:npm test와 Bash:rm -rf /는 서로 다른 지문이므로 별도 승인이 필요합니다.
상수
| 상수 | 값 | 설명 |
|---|---|---|
MAX_PENDING | 5 | Channel당 최대 대기 중 확인 수 |
TIMEOUT_MS | 300,000 | 확인 제한 시간(5분) |
응답 파싱
지원되는 확인 응답은 다음과 같습니다(대소문자 구분 없음, Discord 멘션 등 자동 제거).
| 응답 | 동작 |
|---|---|
| y, yes, approve, ok, 确认, はい | 허용 |
| n, no, deny, cancel, 拒绝, いいえ | 거부 |
| always, always allow, 始终允许, 常に許可 | 허용 + 항상 허용 목록에 추가 |
AuditLogger
모든 보안 이벤트는 audit_log 데이터베이스 테이블에 기록됩니다.
이벤트 유형
type AuditEventType =
| 'firewall_block'
| 'permission_denied'
| 'permission_granted'
| 'permission_timeout'
| 'rate_limited'
| 'role_changed'
| 'user_created'
| 'user_deleted'
| 'injection_detected'
| 'command_blocked'
| 'guardian_review'
| 'prompt_review';
type AuditSeverity = 'info' | 'warn' | 'critical';
쓰기 전략
- Fire-and-forget: 비동기 쓰기이며 기본 흐름을 차단하지 않습니다.
- 쓰기 실패는 조용히 처리되며(
console.warn) 도구 실행에 영향을 주지 않습니다.
주요 파일
| 파일 | 경로 | 설명 |
|---|---|---|
| ExecutionFirewall | platform/security/ExecutionFirewall.ts | 경로 방화벽 |
| GuardianAgent | platform/security/GuardianAgent.ts | AI 보안 평가 |
| AuditLogger | platform/security/AuditLogger.ts | 감사 로깅 |
| ChannelPermissionGate | platform/security/ChannelPermissionGate.ts | Channel 권한 게이트 |
| InputSanitizer | platform/security/InputSanitizer.ts | 입력 정리 |
| PromptGuardian | platform/security/PromptGuardian.ts | 프롬프트 인젝션 감지 |
| RateLimiter | platform/security/RateLimiter.ts | 속도 제한 |
| UserPermissionService | platform/security/UserPermissionService.ts | 사용자 역할 권한 |
| TinyElfPermissions | agent-core/engine/tinyelf/TinyElfPermissions.ts | 권한 관리자 |
모든 경로는 packages/desktop/app/main/services/ 기준 상대 경로입니다.
확장 지점
- 사용자 지정 거부 경로:
SYSTEM_DENIED_PATHS배열에 규칙 추가 - 사용자 지정 Guardian 시스템 프롬프트:
SYSTEM_PROMPT상수 수정 - 사용자 지정 감사 이벤트:
AuditEventType에 새 유형 추가 - 사용자 지정 Channel 응답:
processReply의 정규식 매칭 확장
관련 모듈
| 모듈 | 경로 | 관계 |
|---|---|---|
| TinyElfAgentLoop | agent-core/engine/tinyelf/TinyElfAgentLoop.ts | 보안 파이프라인 호출자 |
| TinyElfSessionRunner | agent-core/engine/tinyelf/TinyElfSessionRunner.ts | Firewall/Guardian 인스턴스화 |
| ShellTool | agent-core/engine/tinyelf/tools/ShellTool.ts | 내장 명령 블랙리스트 |
| TinyElfLLMAdapter | agent-core/engine/tinyelf/TinyElfLLMAdapter.ts | Guardian이 사용하는 LLM |