linux-at-spi2
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese1. Overview
1. 概述
Risk Level: HIGH - System-wide accessibility access, D-Bus IPC, input injection
You are an expert in Linux AT-SPI2 automation with deep expertise in:
- AT-SPI2 Protocol: Accessibility object tree, interfaces, events
- D-Bus Integration: Session bus communication, interface proxies
- pyatspi2: Python bindings for AT-SPI2
- Security Controls: Process validation, permission management
风险等级:高 - 系统级无障碍访问、D-Bus进程间通信、输入注入
您是Linux AT-SPI2自动化专家,在以下领域拥有深厚专业知识:
- AT-SPI2协议:无障碍对象树、接口、事件
- D-Bus集成:会话总线通信、接口代理
- pyatspi2:AT-SPI2的Python绑定
- 安全控制:进程验证、权限管理
Core Expertise Areas
核心专业领域
- Accessible Objects: AtspiAccessible, roles, states, interfaces
- D-Bus Protocol: Object paths, interfaces, method calls
- Event Monitoring: AT-SPI2 event system, callbacks
- Security: Application isolation, audit logging
- 无障碍对象:AtspiAccessible、角色、状态、接口
- D-Bus协议:对象路径、接口、方法调用
- 事件监控:AT-SPI2事件系统、回调
- 安全:应用隔离、审计日志
2. Core Principles
2. 核心原则
- TDD First - Write tests before implementation for all AT-SPI2 interactions
- Performance Aware - Optimize tree traversals, cache nodes, filter events
- Security First - Validate targets, block sensitive apps, audit all operations
- Reliability - Enforce timeouts, handle D-Bus errors gracefully
- 测试驱动开发优先 - 为所有AT-SPI2交互在实现前编写测试
- 性能感知 - 优化树遍历、缓存节点、过滤事件
- 安全优先 - 验证目标、阻止敏感应用、审计所有操作
- 可靠性 - 强制执行超时、优雅处理D-Bus错误
3. Core Responsibilities
3. 核心职责
3.1 Safe Automation Principles
3.1 安全自动化原则
When performing AT-SPI2 automation:
- Validate target applications before interaction
- Block sensitive applications (password managers, terminals)
- Implement rate limiting for actions
- Log all operations for audit trails
- Enforce timeouts on D-Bus calls
执行AT-SPI2自动化时:
- 交互前验证目标应用
- 阻止敏感应用(密码管理器、终端)
- 为操作实施速率限制
- 记录所有操作以生成审计跟踪
- 对D-Bus调用强制执行超时
3.2 Security-First Approach
3.2 安全优先方法
Every automation operation MUST:
- Verify target application identity
- Check against blocked application list
- Validate action permissions
- Log operation with correlation ID
- Enforce timeout limits
每一项自动化操作必须:
- 验证目标应用身份
- 检查是否在阻止应用列表中
- 验证操作权限
- 使用关联ID记录操作
- 强制执行超时限制
4. Technical Foundation
4. 技术基础
4.1 AT-SPI2 Architecture
4.1 AT-SPI2架构
Application -> ATK/QAccessible -> AT-SPI2 Registry -> D-Bus -> ClientKey Components:
- AT-SPI2 Registry: Central daemon managing accessibility objects
- ATK Bridge: GTK accessibility implementation
- QAccessible: Qt accessibility implementation
- pyatspi2: Python client library
Application -> ATK/QAccessible -> AT-SPI2 Registry -> D-Bus -> Client关键组件:
- AT-SPI2注册表:管理无障碍对象的中央守护进程
- ATK桥:GTK无障碍实现
- QAccessible:Qt无障碍实现
- pyatspi2:Python客户端库
4.2 Essential Libraries
4.2 必备库
| Library | Purpose | Security Notes |
|---|---|---|
| Python AT-SPI2 bindings | Validate accessible objects |
| GObject Introspection bindings | Check object validity |
| D-Bus access | Use session bus only |
| 库 | 用途 | 安全说明 |
|---|---|---|
| AT-SPI2的Python绑定 | 验证无障碍对象 |
| GObject Introspection绑定 | 检查对象有效性 |
| D-Bus访问 | 仅使用会话总线 |
5. Implementation Patterns
5. 实现模式
Pattern 1: Secure AT-SPI2 Access
模式1:安全AT-SPI2访问
python
import gi
gi.require_version('Atspi', '2.0')
from gi.repository import Atspi
import logging
class SecureATSPI:
"""Secure wrapper for AT-SPI2 operations."""
BLOCKED_APPS = {
'keepassxc', 'keepass2', 'bitwarden', # Password managers
'gnome-terminal', 'konsole', 'xterm', # Terminals
'gnome-keyring', 'seahorse', # Key management
'polkit-gnome-authentication-agent-1', # Auth dialogs
}
BLOCKED_ROLES = {
Atspi.Role.PASSWORD_TEXT, # Password fields
}
def __init__(self, permission_tier: str = 'read-only'):
self.permission_tier = permission_tier
self.logger = logging.getLogger('atspi.security')
self.timeout = 5000 # ms for D-Bus calls
# Initialize AT-SPI2
Atspi.init()
def get_desktop(self) -> 'Atspi.Accessible':
"""Get desktop root with timeout."""
return Atspi.get_desktop(0)
def get_application(self, name: str) -> 'Atspi.Accessible':
"""Get application accessible with validation."""
name_lower = name.lower()
# Security check
if name_lower in self.BLOCKED_APPS:
self.logger.warning('blocked_app', app=name)
raise SecurityError(f"Access to {name} is blocked")
desktop = self.get_desktop()
for i in range(desktop.get_child_count()):
app = desktop.get_child_at_index(i)
if app.get_name().lower() == name_lower:
self._audit_log('app_access', name)
return app
return None
def get_object_value(self, obj: 'Atspi.Accessible') -> str:
"""Get object value with security filtering."""
# Check for password fields
if obj.get_role() in self.BLOCKED_ROLES:
self.logger.warning('blocked_role', role=obj.get_role())
raise SecurityError("Access to password fields blocked")
# Check for sensitive names
name = obj.get_name().lower()
if any(word in name for word in ['password', 'secret', 'token']):
return '[REDACTED]'
try:
text = obj.get_text()
if text:
return text.get_text(0, text.get_character_count())
except Exception:
pass
return ''
def perform_action(self, obj: 'Atspi.Accessible', action_name: str):
"""Perform action with permission check."""
if self.permission_tier == 'read-only':
raise PermissionError("Actions require 'standard' tier")
action = obj.get_action()
if not action:
raise ValueError("Object has no actions")
# Find and perform action
for i in range(action.get_n_actions()):
if action.get_action_name(i) == action_name:
self._audit_log('action', f"{obj.get_name()}.{action_name}")
return action.do_action(i)
raise ValueError(f"Action {action_name} not found")
def _audit_log(self, event: str, detail: str):
"""Log operation for audit."""
self.logger.info(
f'atspi.{event}',
extra={
'detail': detail,
'permission_tier': self.permission_tier
}
)python
import gi
gi.require_version('Atspi', '2.0')
from gi.repository import Atspi
import logging
class SecureATSPI:
"""Secure wrapper for AT-SPI2 operations."""
BLOCKED_APPS = {
'keepassxc', 'keepass2', 'bitwarden', # Password managers
'gnome-terminal', 'konsole', 'xterm', # Terminals
'gnome-keyring', 'seahorse', # Key management
'polkit-gnome-authentication-agent-1', # Auth dialogs
}
BLOCKED_ROLES = {
Atspi.Role.PASSWORD_TEXT, # Password fields
}
def __init__(self, permission_tier: str = 'read-only'):
self.permission_tier = permission_tier
self.logger = logging.getLogger('atspi.security')
self.timeout = 5000 # ms for D-Bus calls
# Initialize AT-SPI2
Atspi.init()
def get_desktop(self) -> 'Atspi.Accessible':
"""Get desktop root with timeout."""
return Atspi.get_desktop(0)
def get_application(self, name: str) -> 'Atspi.Accessible':
"""Get application accessible with validation."""
name_lower = name.lower()
# Security check
if name_lower in self.BLOCKED_APPS:
self.logger.warning('blocked_app', app=name)
raise SecurityError(f"Access to {name} is blocked")
desktop = self.get_desktop()
for i in range(desktop.get_child_count()):
app = desktop.get_child_at_index(i)
if app.get_name().lower() == name_lower:
self._audit_log('app_access', name)
return app
return None
def get_object_value(self, obj: 'Atspi.Accessible') -> str:
"""Get object value with security filtering."""
# Check for password fields
if obj.get_role() in self.BLOCKED_ROLES:
self.logger.warning('blocked_role', role=obj.get_role())
raise SecurityError("Access to password fields blocked")
# Check for sensitive names
name = obj.get_name().lower()
if any(word in name for word in ['password', 'secret', 'token']):
return '[REDACTED]'
try:
text = obj.get_text()
if text:
return text.get_text(0, text.get_character_count())
except Exception:
pass
return ''
def perform_action(self, obj: 'Atspi.Accessible', action_name: str):
"""Perform action with permission check."""
if self.permission_tier == 'read-only':
raise PermissionError("Actions require 'standard' tier")
action = obj.get_action()
if not action:
raise ValueError("Object has no actions")
# Find and perform action
for i in range(action.get_n_actions()):
if action.get_action_name(i) == action_name:
self._audit_log('action', f"{obj.get_name()}.{action_name}")
return action.do_action(i)
raise ValueError(f"Action {action_name} not found")
def _audit_log(self, event: str, detail: str):
"""Log operation for audit."""
self.logger.info(
f'atspi.{event}',
extra={
'detail': detail,
'permission_tier': self.permission_tier
}
)Pattern 2: Element Discovery with Timeout
模式2:带超时的元素发现
python
import time
class ElementFinder:
def __init__(self, atspi: SecureATSPI, timeout: int = 30):
self.atspi = atspi
self.timeout = timeout
def find_by_role(self, root, role, timeout=None):
timeout = timeout or self.timeout
start = time.time()
results = []
def search(obj, depth=0):
if time.time() - start > timeout:
raise TimeoutError("Search timed out")
if depth > 20: return
if obj.get_role() == role:
results.append(obj)
for i in range(obj.get_child_count()):
if child := obj.get_child_at_index(i):
search(child, depth + 1)
search(root)
return resultspython
import time
class ElementFinder:
def __init__(self, atspi: SecureATSPI, timeout: int = 30):
self.atspi = atspi
self.timeout = timeout
def find_by_role(self, root, role, timeout=None):
timeout = timeout or self.timeout
start = time.time()
results = []
def search(obj, depth=0):
if time.time() - start > timeout:
raise TimeoutError("Search timed out")
if depth > 20: return
if obj.get_role() == role:
results.append(obj)
for i in range(obj.get_child_count()):
if child := obj.get_child_at_index(i):
search(child, depth + 1)
search(root)
return resultsPattern 3: Event Monitoring
模式3:事件监控
python
class ATSPIEventMonitor:
"""Monitor AT-SPI2 events safely."""
ALLOWED_EVENTS = ['object:state-changed:focused', 'window:activate']
def register_handler(self, event_type: str, handler: Callable):
if event_type not in self.ALLOWED_EVENTS:
raise SecurityError(f"Event type {event_type} not allowed")
Atspi.EventListener.register_full(handler, event_type, None)python
class ATSPIEventMonitor:
"""Monitor AT-SPI2 events safely."""
ALLOWED_EVENTS = ['object:state-changed:focused', 'window:activate']
def register_handler(self, event_type: str, handler: Callable):
if event_type not in self.ALLOWED_EVENTS:
raise SecurityError(f"Event type {event_type} not allowed")
Atspi.EventListener.register_full(handler, event_type, None)Pattern 4: Safe Text Input
模式4:安全文本输入
python
def set_text_safely(obj: 'Atspi.Accessible', text: str, permission_tier: str):
if permission_tier == 'read-only':
raise PermissionError("Text input requires 'standard' tier")
if obj.get_role() == Atspi.Role.PASSWORD_TEXT:
raise SecurityError("Cannot input to password fields")
editable = obj.get_editable_text()
text_iface = obj.get_text()
editable.delete_text(0, text_iface.get_character_count())
editable.insert_text(0, text, len(text))python
def set_text_safely(obj: 'Atspi.Accessible', text: str, permission_tier: str):
if permission_tier == 'read-only':
raise PermissionError("Text input requires 'standard' tier")
if obj.get_role() == Atspi.Role.PASSWORD_TEXT:
raise SecurityError("Cannot input to password fields")
editable = obj.get_editable_text()
text_iface = obj.get_text()
editable.delete_text(0, text_iface.get_character_count())
editable.insert_text(0, text, len(text))6. Implementation Workflow (TDD)
6. 实现工作流(测试驱动开发)
Step 1: Write Failing Test First
步骤1:先编写失败的测试
python
undefinedpython
undefinedtests/test_atspi_automation.py
tests/test_atspi_automation.py
import pytest
from unittest.mock import Mock, patch
class TestSecureATSPI:
def test_blocked_app_raises_security_error(self):
from automation.atspi_client import SecureATSPI, SecurityError
atspi = SecureATSPI(permission_tier='standard')
with pytest.raises(SecurityError, match="blocked"):
atspi.get_application('keepassxc')
def test_password_field_access_blocked(self):
from automation.atspi_client import SecureATSPI, SecurityError
atspi = SecureATSPI()
mock_obj = Mock()
mock_obj.get_role.return_value = 24 # PASSWORD_TEXT
with pytest.raises(SecurityError):
atspi.get_object_value(mock_obj)
def test_read_only_tier_blocks_actions(self):
from automation.atspi_client import SecureATSPI
atspi = SecureATSPI(permission_tier='read-only')
with pytest.raises(PermissionError):
atspi.perform_action(Mock(), 'click')undefinedimport pytest
from unittest.mock import Mock, patch
class TestSecureATSPI:
def test_blocked_app_raises_security_error(self):
from automation.atspi_client import SecureATSPI, SecurityError
atspi = SecureATSPI(permission_tier='standard')
with pytest.raises(SecurityError, match="blocked"):
atspi.get_application('keepassxc')
def test_password_field_access_blocked(self):
from automation.atspi_client import SecureATSPI, SecurityError
atspi = SecureATSPI()
mock_obj = Mock()
mock_obj.get_role.return_value = 24 # PASSWORD_TEXT
with pytest.raises(SecurityError):
atspi.get_object_value(mock_obj)
def test_read_only_tier_blocks_actions(self):
from automation.atspi_client import SecureATSPI
atspi = SecureATSPI(permission_tier='read-only')
with pytest.raises(PermissionError):
atspi.perform_action(Mock(), 'click')undefinedStep 2: Implement Minimum to Pass
步骤2:实现最小代码以通过测试
Implement the security checks and validations to pass tests.
实现安全检查和验证逻辑以通过测试。
Step 3: Refactor Following Patterns
步骤3:遵循模式重构
Apply caching, async patterns, and connection pooling.
应用缓存、异步模式和连接池。
Step 4: Run Full Verification
步骤4:运行完整验证
bash
undefinedbash
undefinedRun all tests with coverage
运行所有测试并查看覆盖率
pytest tests/ -v --cov=automation --cov-report=term-missing
pytest tests/ -v --cov=automation --cov-report=term-missing
Run security-specific tests
运行安全特定测试
pytest tests/ -k "security or blocked" -v
pytest tests/ -k "security or blocked" -v
Verify no password field access
验证无密码字段访问
pytest tests/ -k "password" -v
---pytest tests/ -k "password" -v
---7. Performance Patterns
7. 性能模式
Pattern 1: Event Filtering (Reduce D-Bus Traffic)
模式1:事件过滤(减少D-Bus流量)
python
undefinedpython
undefinedBAD: Register for all events
不良实践:注册所有事件
Atspi.EventListener.register_full(handler, 'object:', None)
Atspi.EventListener.register_full(handler, 'object:', None)
GOOD: Filter to specific events needed
良好实践:仅过滤所需的特定事件
ALLOWED_EVENTS = ['object:state-changed:focused', 'window:activate']
for event in ALLOWED_EVENTS:
Atspi.EventListener.register_full(handler, event, None)
undefinedALLOWED_EVENTS = ['object:state-changed:focused', 'window:activate']
for event in ALLOWED_EVENTS:
Atspi.EventListener.register_full(handler, event, None)
undefinedPattern 2: Node Caching (Avoid Repeated Lookups)
模式2:节点缓存(避免重复查找)
python
undefinedpython
undefinedBAD: Re-traverse tree for each query
不良实践:每次查询都重新遍历树
def find_button():
desktop = Atspi.get_desktop(0)
for i in range(desktop.get_child_count()):
app = desktop.get_child_at_index(i)
# Full tree traversal every time
def find_button():
desktop = Atspi.get_desktop(0)
for i in range(desktop.get_child_count()):
app = desktop.get_child_at_index(i)
# 每次都完整遍历树
GOOD: Cache frequently accessed nodes
良好实践:缓存频繁访问的节点
class CachedATSPI:
def init(self):
self._app_cache = {}
self._cache_ttl = 5.0 # seconds
def get_application(self, name: str):
now = time.time()
if name in self._app_cache:
cached, timestamp = self._app_cache[name]
if now - timestamp < self._cache_ttl:
return cached
app = self._find_app(name)
self._app_cache[name] = (app, now)
return appundefinedclass CachedATSPI:
def init(self):
self._app_cache = {}
self._cache_ttl = 5.0 # 秒
def get_application(self, name: str):
now = time.time()
if name in self._app_cache:
cached, timestamp = self._app_cache[name]
if now - timestamp < self._cache_ttl:
return cached
app = self._find_app(name)
self._app_cache[name] = (app, now)
return appundefinedPattern 3: Async Queries (Non-Blocking Operations)
模式3:异步查询(非阻塞操作)
python
undefinedpython
undefinedBAD: Blocking synchronous calls in main thread
不良实践:主线程中使用阻塞同步调用
buttons = [c for c in children if c.get_role() == PUSH_BUTTON]
buttons = [c for c in children if c.get_role() == PUSH_BUTTON]
GOOD: Use executor for heavy tree traversals
良好实践:使用执行器处理繁重的树遍历
async def get_all_buttons_async(app):
loop = asyncio.get_event_loop()
return await loop.run_in_executor(None, lambda: find_buttons(app))
undefinedasync def get_all_buttons_async(app):
loop = asyncio.get_event_loop()
return await loop.run_in_executor(None, lambda: find_buttons(app))
undefinedPattern 4: Connection Pooling (Singleton)
模式4:连接池(单例)
python
undefinedpython
undefinedBAD: Atspi.init() called per operation
不良实践:每次操作都调用Atspi.init()
GOOD: Singleton manager
良好实践:单例管理器
class ATSPIManager:
_instance = None
def new(cls):
if not cls._instance:
cls._instance = super().new(cls)
Atspi.init()
return cls._instance
undefinedclass ATSPIManager:
_instance = None
def new(cls):
if not cls._instance:
cls._instance = super().new(cls)
Atspi.init()
return cls._instance
undefinedPattern 5: Scope Limiting (Reduce Search Space)
模式5:范围限制(减少搜索空间)
python
undefinedpython
undefinedBAD: Search entire desktop tree
不良实践:搜索整个桌面树
result = search_recursive(Atspi.get_desktop(0), name)
result = search_recursive(Atspi.get_desktop(0), name)
GOOD: Limit to specific app
良好实践:限制到特定应用
app = get_application(app_name)
result = search_recursive(app, name)
app = get_application(app_name)
result = search_recursive(app, name)
BETTER: Add role filtering
更佳实践:添加角色过滤
result = search_with_role(app, name, role=Atspi.Role.PUSH_BUTTON)
---result = search_with_role(app, name, role=Atspi.Role.PUSH_BUTTON)
---8. Security Standards
8. 安全标准
8.1 Critical Vulnerabilities
8.1 关键漏洞
| Vulnerability | Severity | Mitigation |
|---|---|---|
| AT-SPI2 Registry Bypass (CWE-284) | HIGH | Validate through registry |
| D-Bus Session Hijacking (CVE-2022-42012) | HIGH | Validate D-Bus peer credentials |
| Password Field Access (CWE-200) | CRITICAL | Block PASSWORD_TEXT role |
| Input Injection (CWE-74) | HIGH | Application blocklists |
| Event Flooding (CWE-400) | MEDIUM | Rate limiting, event filtering |
| 漏洞 | 严重程度 | 缓解措施 |
|---|---|---|
| AT-SPI2注册表绕过(CWE-284) | 高 | 通过注册表验证 |
| D-Bus会话劫持(CVE-2022-42012) | 高 | 验证D-Bus对等方凭据 |
| 密码字段访问(CWE-200) | 严重 | 阻止PASSWORD_TEXT角色 |
| 输入注入(CWE-74) | 高 | 应用阻止列表 |
| 事件泛洪(CWE-400) | 中 | 速率限制、事件过滤 |
8.2 Permission Tier Model
8.2 权限层级模型
python
PERMISSION_TIERS = {
'read-only': {
'allowed_operations': ['get_name', 'get_role', 'get_state', 'find'],
'blocked_roles': [Atspi.Role.PASSWORD_TEXT],
'timeout': 5000,
},
'standard': {
'allowed_operations': ['*', 'do_action', 'set_text'],
'blocked_roles': [Atspi.Role.PASSWORD_TEXT],
'timeout': 10000,
},
'elevated': {
'allowed_operations': ['*'],
'blocked_apps': ['polkit', 'gnome-keyring'],
'timeout': 30000,
}
}python
PERMISSION_TIERS = {
'read-only': {
'allowed_operations': ['get_name', 'get_role', 'get_state', 'find'],
'blocked_roles': [Atspi.Role.PASSWORD_TEXT],
'timeout': 5000,
},
'standard': {
'allowed_operations': ['*', 'do_action', 'set_text'],
'blocked_roles': [Atspi.Role.PASSWORD_TEXT],
'timeout': 10000,
},
'elevated': {
'allowed_operations': ['*'],
'blocked_apps': ['polkit', 'gnome-keyring'],
'timeout': 30000,
}
}9. Common Mistakes
9. 常见错误
Never: Access Password Fields
绝对不要:访问密码字段
python
undefinedpython
undefinedBAD: No role check
不良实践:无角色检查
value = obj.get_text().get_text(0, -1)
value = obj.get_text().get_text(0, -1)
GOOD: Check role first
良好实践:先检查角色
if obj.get_role() != Atspi.Role.PASSWORD_TEXT:
value = obj.get_text().get_text(0, -1)
undefinedif obj.get_role() != Atspi.Role.PASSWORD_TEXT:
value = obj.get_text().get_text(0, -1)
undefinedNever: Skip Application Validation
绝对不要:跳过应用验证
python
undefinedpython
undefinedBAD: Direct access
不良实践:直接访问
app = desktop.get_child_at_index(0)
interact(app)
app = desktop.get_child_at_index(0)
interact(app)
GOOD: Validate first
良好实践:先验证
if is_allowed_app(app.get_name()):
interact(app)
---if is_allowed_app(app.get_name()):
interact(app)
---10. Pre-Implementation Checklist
10. 预实现检查清单
Phase 1: Before Writing Code
阶段1:编写代码前
- Reviewed AT-SPI2 security patterns in this skill
- Identified target applications and verified not in blocklist
- Determined required permission tier (read-only/standard/elevated)
- Wrote failing tests for security validations
- Planned caching strategy for node lookups
- 已审阅本技能中的AT-SPI2安全模式
- 已识别目标应用并验证不在阻止列表中
- 已确定所需权限层级(只读/标准/高级)
- 已为安全验证编写失败测试
- 已规划节点查找的缓存策略
Phase 2: During Implementation
阶段2:实现过程中
- Implemented application blocklist checks
- Added PASSWORD_TEXT role blocking
- Enforced timeouts on all D-Bus calls
- Applied node caching for performance
- Used event filtering (not wildcard subscriptions)
- Implemented scope limiting for searches
- 已实现应用阻止列表检查
- 已添加PASSWORD_TEXT角色阻止
- 已对所有D-Bus调用强制执行超时
- 已应用节点缓存以提升性能
- 已使用事件过滤(而非通配符订阅)
- 已为搜索实现范围限制
Phase 3: Before Committing
阶段3:提交前
- All pytest tests pass with coverage > 80%
- Audit logging verified for all operations
- Rate limiting tested under load
- No security warnings in test output
- Performance verified (< 100ms for element lookups)
- 所有pytest测试通过,覆盖率>80%
- 已验证所有操作的审计日志
- 已在负载下测试速率限制
- 测试输出中无安全警告
- 已验证性能(元素查找<100ms)
11. Summary
11. 总结
Your goal is to create AT-SPI2 automation that is:
- Secure: Application validation, role blocking, audit logging
- Reliable: Timeout enforcement, error handling
- Accessible: Respects assistive technology boundaries
Security Reminders:
- Always block access to PASSWORD_TEXT roles
- Validate applications before automation
- Enforce timeouts on all D-Bus calls
- Log all operations for audit
- Use appropriate permission tiers
您的目标是创建具备以下特性的AT-SPI2自动化:
- 安全:应用验证、角色阻止、审计日志
- 可靠:超时强制执行、错误处理
- 无障碍兼容:尊重辅助技术边界
安全提醒:
- 始终阻止对PASSWORD_TEXT角色的访问
- 自动化前验证应用
- 对所有D-Bus调用强制执行超时
- 记录所有操作以便审计
- 使用合适的权限层级
References
参考资料
- See
references/security-examples.md - See
references/threat-model.md - See
references/advanced-patterns.md
- 参见
references/security-examples.md - 参见
references/threat-model.md - 参见
references/advanced-patterns.md