supabase
Handles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
linux-at-spi2
Expert in AT-SPI2 (Assistive Technology Service Provider Interface) for Linux desktop automation. Specializes in accessible automation of GTK/Qt applications via D-Bus accessibility interface. HIGH-RISK skill requiring security controls for system-wide access.
Full skill instructions
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:
When performing AT-SPI2 automation:
Every automation operation MUST:
Application -> ATK/QAccessible -> AT-SPI2 Registry -> D-Bus -> Client
Key Components:
| Library | Purpose | Security Notes |
|---|---|---|
pyatspi2 | Python AT-SPI2 bindings | Validate accessible objects |
gi.repository.Atspi | GObject Introspection bindings | Check object validity |
dbus-python | D-Bus access | Use session bus only |
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
}
)
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 results
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)
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))
# 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')
Implement the security checks and validations to pass tests.
Apply caching, async patterns, and connection pooling.
# Run all tests with coverage
pytest tests/ -v --cov=automation --cov-report=term-missing
# Run security-specific tests
pytest tests/ -k "security or blocked" -v
# Verify no password field access
pytest tests/ -k "password" -v
# BAD: Register for all events
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)
# BAD: 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
# 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 app
# BAD: Blocking synchronous calls in main thread
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))
# BAD: Atspi.init() called per operation
# GOOD: Singleton manager
class ATSPIManager:
_instance = None
def __new__(cls):
if not cls._instance:
cls._instance = super().__new__(cls)
Atspi.init()
return cls._instance
# BAD: Search entire desktop tree
result = search_recursive(Atspi.get_desktop(0), name)
# GOOD: Limit to specific app
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)
| 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 |
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,
}
}
# BAD: No role check
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)
# BAD: Direct access
app = desktop.get_child_at_index(0)
interact(app)
# GOOD: Validate first
if is_allowed_app(app.get_name()):
interact(app)
Your goal is to create AT-SPI2 automation that is:
Security Reminders:
references/security-examples.mdreferences/threat-model.mdreferences/advanced-patterns.mdHandles the full Supabase workflow from schema changes to deployment, with built-in security guardrails that catch common traps like RLS...
Comprehensive guides and best practices for Neon Serverless Postgres, covering setup, connection methods, authentication, and platform APIs.
Guide for setting up and using Firebase Authentication. Use this skill when the user's app requires user sign-in, user management, or secure data access using auth rules.
A skill to evaluate how secure Firestore security rules are. Use this when Firestore security rules are updated to ensure that the generated rules are extremely secure and robust.
Official skill for integrating Firebase AI Logic (Gemini API) into web applications. Covers setup, multimodal inference, structured output, and security.
Complete Better Auth server and client setup with database adapters, session management, plugins, and security configuration.
Deploy and manage projects on Vercel using token-based authentication. Use when working with Vercel CLI using access tokens rather than interactive login — e.g. "deploy to vercel", "set up vercel", "add environment variables to vercel".
Complete Cloudflare platform integration with decision trees for compute, storage, AI, networking, security, and infrastructure-as-code.
Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.
Send, read, and manage Gmail messages, drafts, labels, and account settings.
Comprehensive website auditing across 230+ rules in 21 categories including SEO, performance, security, and accessibility.
Shared authentication, CLI syntax, and output formatting patterns for gws Google Workspace commands.
Discover your celebrity doppelgänger with StarByFace!
GeoSpy: Pricing, Features, FAQs, and Alternatives for AI Teams
Detect AI-generated voices to protect against audio fraud.
Ensure Your Content's Originality with AI Plagiarism Checker
Upscale images by 400% without quality loss
Protect your social media from copyright disputes
Accurately Detect AI-Generated Content with TheChecker.AI
Chrome extension that detects and flags AI-generated content