cfsa-antigravity 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: desktop-security-sandboxing
|
|
3
|
+
description: Security patterns for desktop applications covering file system sandboxing, IPC security, credential storage, context isolation, and framework-specific hardening for Electron and Tauri. Use when building desktop apps that handle sensitive data or need defense-in-depth.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Desktop Security & Sandboxing
|
|
8
|
+
|
|
9
|
+
Secure desktop applications against local attacks, privilege escalation, and data theft with defense-in-depth.
|
|
10
|
+
|
|
11
|
+
## File System Permissions and Sandboxing
|
|
12
|
+
|
|
13
|
+
Desktop apps often request unrestricted file system access. Minimize the attack surface.
|
|
14
|
+
|
|
15
|
+
| Approach | Scope | Use Case |
|
|
16
|
+
|----------|-------|----------|
|
|
17
|
+
| App sandbox (macOS) | App can only access its container + user-granted files | Mac App Store apps, Tauri |
|
|
18
|
+
| Flatpak sandbox | App isolated with portal-based file access | Linux distribution via Flathub |
|
|
19
|
+
| Custom restricted paths | App only reads/writes within `userData` directory | Self-contained apps |
|
|
20
|
+
| User-granted access | App requests specific files via native dialog | Document-based apps |
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
// Electron - Restrict file access to specific directories
|
|
24
|
+
import { app } from 'electron';
|
|
25
|
+
import path from 'path';
|
|
26
|
+
|
|
27
|
+
const ALLOWED_DIRS = [
|
|
28
|
+
app.getPath('userData'), // App data directory
|
|
29
|
+
app.getPath('temp'), // Temporary files
|
|
30
|
+
app.getPath('downloads'), // Only if user explicitly grants via dialog
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
function isPathAllowed(filePath: string): boolean {
|
|
34
|
+
const resolved = path.resolve(filePath);
|
|
35
|
+
return ALLOWED_DIRS.some((dir) => resolved.startsWith(dir));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Always validate paths before file operations
|
|
39
|
+
function safeReadFile(filePath: string): Buffer {
|
|
40
|
+
if (!isPathAllowed(filePath)) {
|
|
41
|
+
throw new Error(`Access denied: ${filePath} is outside allowed directories`);
|
|
42
|
+
}
|
|
43
|
+
return fs.readFileSync(filePath);
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**Anti-pattern**: Accepting arbitrary file paths from the renderer process without validation. A compromised renderer could read `/etc/passwd` or `~/.ssh/id_rsa`.
|
|
48
|
+
|
|
49
|
+
## IPC Security (Main/Renderer in Electron)
|
|
50
|
+
|
|
51
|
+
The main process has full Node.js access. The renderer process should be treated as untrusted.
|
|
52
|
+
|
|
53
|
+
### The Security Architecture
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
┌─────────────────────────────────────┐
|
|
57
|
+
│ Renderer (Untrusted) │
|
|
58
|
+
│ - No Node.js access │
|
|
59
|
+
│ - No direct fs/net/child_process │
|
|
60
|
+
│ - Communicates only via preload │
|
|
61
|
+
│ │
|
|
62
|
+
│ window.api.saveFile(data) │
|
|
63
|
+
│ │ │
|
|
64
|
+
└───────────┼─────────────────────────┘
|
|
65
|
+
│ contextBridge
|
|
66
|
+
┌───────────┼─────────────────────────┐
|
|
67
|
+
│ Preload Script (Bridge) │
|
|
68
|
+
│ - Exposes specific, typed APIs │
|
|
69
|
+
│ - Validates arguments │
|
|
70
|
+
│ - No raw IPC exposure │
|
|
71
|
+
│ │
|
|
72
|
+
│ ipcRenderer.invoke('save-file', │
|
|
73
|
+
│ validated(data)) │
|
|
74
|
+
│ │ │
|
|
75
|
+
└───────────┼─────────────────────────┘
|
|
76
|
+
│ IPC
|
|
77
|
+
┌───────────┼─────────────────────────┐
|
|
78
|
+
│ Main Process (Trusted) │
|
|
79
|
+
│ - Full Node.js access │
|
|
80
|
+
│ - Validates all IPC inputs again │
|
|
81
|
+
│ - Executes file system operations │
|
|
82
|
+
│ │
|
|
83
|
+
│ ipcMain.handle('save-file', │
|
|
84
|
+
│ handler) │
|
|
85
|
+
└─────────────────────────────────────┘
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```typescript
|
|
89
|
+
// preload.ts - Expose ONLY specific, validated APIs
|
|
90
|
+
import { contextBridge, ipcRenderer } from 'electron';
|
|
91
|
+
|
|
92
|
+
// Never expose ipcRenderer.send or ipcRenderer.on directly
|
|
93
|
+
contextBridge.exposeInMainWorld('api', {
|
|
94
|
+
// Each method is a specific, typed operation
|
|
95
|
+
saveFile: (content: string, name: string): Promise<boolean> => {
|
|
96
|
+
if (typeof content !== 'string' || typeof name !== 'string') {
|
|
97
|
+
throw new Error('Invalid arguments');
|
|
98
|
+
}
|
|
99
|
+
if (name.includes('..') || name.includes('/')) {
|
|
100
|
+
throw new Error('Invalid filename');
|
|
101
|
+
}
|
|
102
|
+
return ipcRenderer.invoke('save-file', { content, name });
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
getAppVersion: (): Promise<string> => {
|
|
106
|
+
return ipcRenderer.invoke('get-app-version');
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
onUpdateAvailable: (callback: (version: string) => void) => {
|
|
110
|
+
const handler = (_event: unknown, version: string) => callback(version);
|
|
111
|
+
ipcRenderer.on('update-available', handler);
|
|
112
|
+
return () => ipcRenderer.removeListener('update-available', handler);
|
|
113
|
+
},
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// main.ts - Validate all inputs from renderer
|
|
119
|
+
import { ipcMain } from 'electron';
|
|
120
|
+
import { z } from 'zod';
|
|
121
|
+
|
|
122
|
+
const SaveFileSchema = z.object({
|
|
123
|
+
content: z.string().max(10_000_000), // 10MB limit
|
|
124
|
+
name: z.string().regex(/^[a-zA-Z0-9._-]+$/), // Alphanumeric only
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
ipcMain.handle('save-file', async (_event, args: unknown) => {
|
|
128
|
+
const parsed = SaveFileSchema.safeParse(args);
|
|
129
|
+
if (!parsed.success) {
|
|
130
|
+
throw new Error(`Invalid input: ${parsed.error.message}`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const filePath = path.join(app.getPath('userData'), parsed.data.name);
|
|
134
|
+
await fs.promises.writeFile(filePath, parsed.data.content, 'utf-8');
|
|
135
|
+
return true;
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Anti-pattern**: `contextBridge.exposeInMainWorld('electron', { ipcRenderer })` -- this gives the renderer full IPC access, defeating the purpose of context isolation.
|
|
140
|
+
|
|
141
|
+
## Context Isolation
|
|
142
|
+
|
|
143
|
+
Context isolation prevents the renderer's JavaScript from accessing Electron internals or the preload script's scope.
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
// BrowserWindow configuration - security defaults
|
|
147
|
+
const mainWindow = new BrowserWindow({
|
|
148
|
+
webPreferences: {
|
|
149
|
+
// MANDATORY security settings
|
|
150
|
+
contextIsolation: true, // Isolate preload from renderer
|
|
151
|
+
nodeIntegration: false, // No Node.js in renderer
|
|
152
|
+
nodeIntegrationInWorker: false,
|
|
153
|
+
sandbox: true, // OS-level process sandbox
|
|
154
|
+
|
|
155
|
+
// Additional hardening
|
|
156
|
+
webSecurity: true, // Enforce same-origin policy
|
|
157
|
+
allowRunningInsecureContent: false,
|
|
158
|
+
experimentalFeatures: false,
|
|
159
|
+
|
|
160
|
+
preload: path.join(__dirname, 'preload.js'),
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Block navigation to untrusted URLs
|
|
165
|
+
mainWindow.webContents.on('will-navigate', (event, url) => {
|
|
166
|
+
const allowed = ['https://myapp.example.com'];
|
|
167
|
+
if (!allowed.some((origin) => url.startsWith(origin))) {
|
|
168
|
+
event.preventDefault();
|
|
169
|
+
console.warn(`Blocked navigation to: ${url}`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// Block new window creation
|
|
174
|
+
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
|
175
|
+
// Open external links in the default browser
|
|
176
|
+
if (url.startsWith('https://')) {
|
|
177
|
+
shell.openExternal(url);
|
|
178
|
+
}
|
|
179
|
+
return { action: 'deny' }; // Never allow new Electron windows from renderer
|
|
180
|
+
});
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## CSP for Desktop Apps
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
// Electron - Set Content Security Policy via headers
|
|
187
|
+
import { session } from 'electron';
|
|
188
|
+
|
|
189
|
+
session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
|
|
190
|
+
callback({
|
|
191
|
+
responseHeaders: {
|
|
192
|
+
...details.responseHeaders,
|
|
193
|
+
'Content-Security-Policy': [
|
|
194
|
+
[
|
|
195
|
+
"default-src 'self'",
|
|
196
|
+
"script-src 'self'", // No inline scripts, no eval
|
|
197
|
+
"style-src 'self' 'unsafe-inline'", // Allow inline styles (React)
|
|
198
|
+
"img-src 'self' data: https:",
|
|
199
|
+
"font-src 'self'",
|
|
200
|
+
"connect-src 'self' https://api.example.com wss://ws.example.com",
|
|
201
|
+
"frame-src 'none'", // No iframes
|
|
202
|
+
"object-src 'none'", // No plugins
|
|
203
|
+
"base-uri 'self'",
|
|
204
|
+
].join('; '),
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Rule**: Desktop CSP should be as strict as web CSP. Electron apps are web apps with elevated privileges, making CSP even more important.
|
|
212
|
+
|
|
213
|
+
## Credential Storage
|
|
214
|
+
|
|
215
|
+
Never store passwords, tokens, or API keys in plain text files. Use the OS keychain.
|
|
216
|
+
|
|
217
|
+
| Platform | System | API |
|
|
218
|
+
|----------|--------|-----|
|
|
219
|
+
| macOS | Keychain | `SecItemAdd` / `SecItemCopyMatching` |
|
|
220
|
+
| Windows | Credential Manager | `CredWrite` / `CredRead` |
|
|
221
|
+
| Linux | libsecret (GNOME Keyring / KWallet) | `secret_password_store` / `secret_password_lookup` |
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// Cross-platform credential storage via keytar
|
|
225
|
+
import keytar from 'keytar';
|
|
226
|
+
|
|
227
|
+
const SERVICE_NAME = 'com.example.myapp';
|
|
228
|
+
|
|
229
|
+
async function storeCredential(account: string, password: string): Promise<void> {
|
|
230
|
+
await keytar.setPassword(SERVICE_NAME, account, password);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function getCredential(account: string): Promise<string | null> {
|
|
234
|
+
return keytar.getPassword(SERVICE_NAME, account);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
async function deleteCredential(account: string): Promise<boolean> {
|
|
238
|
+
return keytar.deletePassword(SERVICE_NAME, account);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Store OAuth tokens securely
|
|
242
|
+
async function storeAuthTokens(tokens: AuthTokens): Promise<void> {
|
|
243
|
+
await keytar.setPassword(
|
|
244
|
+
SERVICE_NAME,
|
|
245
|
+
'auth-tokens',
|
|
246
|
+
JSON.stringify({
|
|
247
|
+
accessToken: tokens.accessToken,
|
|
248
|
+
refreshToken: tokens.refreshToken,
|
|
249
|
+
expiresAt: tokens.expiresAt,
|
|
250
|
+
})
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async function getAuthTokens(): Promise<AuthTokens | null> {
|
|
255
|
+
const stored = await keytar.getPassword(SERVICE_NAME, 'auth-tokens');
|
|
256
|
+
if (!stored) return null;
|
|
257
|
+
|
|
258
|
+
try {
|
|
259
|
+
return JSON.parse(stored) as AuthTokens;
|
|
260
|
+
} catch {
|
|
261
|
+
await keytar.deletePassword(SERVICE_NAME, 'auth-tokens');
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Anti-pattern**: Storing tokens in `localStorage`, `electron-store`, or JSON files in `userData`. These are readable by any process with file system access.
|
|
268
|
+
**Anti-pattern**: Storing encryption keys alongside encrypted data. The key must be in the OS keychain, the data in the app directory.
|
|
269
|
+
|
|
270
|
+
## Preventing Local Privilege Escalation
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
// Never run shell commands with user-controlled input
|
|
274
|
+
import { exec } from 'child_process'; // AVOID
|
|
275
|
+
import { execFile } from 'child_process'; // PREFER
|
|
276
|
+
|
|
277
|
+
// BAD: shell injection via user input
|
|
278
|
+
exec(`convert ${userInput} output.png`); // userInput: "file.png; rm -rf /"
|
|
279
|
+
|
|
280
|
+
// GOOD: execFile does not spawn a shell
|
|
281
|
+
execFile('convert', [userInput, 'output.png']); // Arguments are passed directly
|
|
282
|
+
|
|
283
|
+
// GOOD: validate all arguments
|
|
284
|
+
const ALLOWED_FORMATS = ['png', 'jpg', 'webp'] as const;
|
|
285
|
+
|
|
286
|
+
function convertImage(inputPath: string, format: string): Promise<void> {
|
|
287
|
+
// Validate format against allowlist
|
|
288
|
+
if (!ALLOWED_FORMATS.includes(format as any)) {
|
|
289
|
+
throw new Error(`Invalid format: ${format}`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Validate path is within allowed directory
|
|
293
|
+
const resolved = path.resolve(inputPath);
|
|
294
|
+
if (!resolved.startsWith(app.getPath('userData'))) {
|
|
295
|
+
throw new Error('Path outside allowed directory');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return new Promise((resolve, reject) => {
|
|
299
|
+
execFile('convert', [resolved, `output.${format}`], (error) => {
|
|
300
|
+
if (error) reject(error);
|
|
301
|
+
else resolve();
|
|
302
|
+
});
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
## Update Verification
|
|
308
|
+
|
|
309
|
+
```typescript
|
|
310
|
+
// Verify update signatures before installing
|
|
311
|
+
import { autoUpdater } from 'electron-updater';
|
|
312
|
+
|
|
313
|
+
// electron-updater verifies signatures automatically when configured
|
|
314
|
+
// For custom update servers, verify manually:
|
|
315
|
+
|
|
316
|
+
import crypto from 'crypto';
|
|
317
|
+
|
|
318
|
+
function verifyUpdateSignature(
|
|
319
|
+
updatePath: string,
|
|
320
|
+
signature: string,
|
|
321
|
+
publicKey: string
|
|
322
|
+
): boolean {
|
|
323
|
+
const fileBuffer = fs.readFileSync(updatePath);
|
|
324
|
+
const verifier = crypto.createVerify('RSA-SHA256');
|
|
325
|
+
verifier.update(fileBuffer);
|
|
326
|
+
return verifier.verify(publicKey, signature, 'base64');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Reject updates from non-HTTPS sources
|
|
330
|
+
autoUpdater.on('error', (error) => {
|
|
331
|
+
if (error.message.includes('net::ERR_SSL')) {
|
|
332
|
+
console.error('Update download failed SSL verification - aborting');
|
|
333
|
+
// Do NOT fall back to HTTP
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
## Electron-Specific Security Checklist
|
|
339
|
+
|
|
340
|
+
| Setting | Required Value | Why |
|
|
341
|
+
|---------|---------------|-----|
|
|
342
|
+
| `contextIsolation` | `true` | Prevents renderer from accessing Node.js via preload |
|
|
343
|
+
| `nodeIntegration` | `false` | No Node.js in renderer process |
|
|
344
|
+
| `sandbox` | `true` | OS-level process sandboxing |
|
|
345
|
+
| `webSecurity` | `true` | Enforces same-origin policy |
|
|
346
|
+
| `allowRunningInsecureContent` | `false` | No HTTP resources on HTTPS pages |
|
|
347
|
+
| `enableRemoteModule` | `false` (removed in v14+) | Remote module bypasses IPC security |
|
|
348
|
+
| `webviewTag` | `false` (unless needed) | Webviews are hard to secure |
|
|
349
|
+
|
|
350
|
+
## Tauri Security Model Comparison
|
|
351
|
+
|
|
352
|
+
Tauri provides stronger security defaults than Electron:
|
|
353
|
+
|
|
354
|
+
| Feature | Electron | Tauri |
|
|
355
|
+
|---------|----------|-------|
|
|
356
|
+
| Renderer access | Full web API, optional Node.js | Web API only, no Node.js |
|
|
357
|
+
| Backend communication | IPC (main process is Node.js) | Commands (backend is Rust) |
|
|
358
|
+
| File system access | Unrestricted (main process) | Scoped to allowlisted paths |
|
|
359
|
+
| Shell commands | `child_process` (unrestricted) | `shell.execute` with allowlist |
|
|
360
|
+
| HTTP requests | Unrestricted | Scoped to allowlisted URLs |
|
|
361
|
+
| Auto-update | Signature optional | Signature mandatory |
|
|
362
|
+
| Binary size | ~150MB+ | ~5-10MB |
|
|
363
|
+
|
|
364
|
+
```rust
|
|
365
|
+
// Tauri - Scoped file system access (tauri.conf.json)
|
|
366
|
+
{
|
|
367
|
+
"tauri": {
|
|
368
|
+
"allowlist": {
|
|
369
|
+
"fs": {
|
|
370
|
+
"scope": ["$APPDATA/*", "$DOWNLOAD/*"],
|
|
371
|
+
"readFile": true,
|
|
372
|
+
"writeFile": true,
|
|
373
|
+
"readDir": false,
|
|
374
|
+
"createDir": false,
|
|
375
|
+
"removeFile": false
|
|
376
|
+
},
|
|
377
|
+
"shell": {
|
|
378
|
+
"scope": [
|
|
379
|
+
{
|
|
380
|
+
"name": "open-url",
|
|
381
|
+
"cmd": "open",
|
|
382
|
+
"args": [{ "validator": "\\S+" }]
|
|
383
|
+
}
|
|
384
|
+
]
|
|
385
|
+
},
|
|
386
|
+
"http": {
|
|
387
|
+
"scope": ["https://api.example.com/*"]
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Output Checklist
|
|
395
|
+
|
|
396
|
+
- [ ] Context isolation enabled, nodeIntegration disabled, sandbox enabled
|
|
397
|
+
- [ ] IPC APIs are specific, typed, and validate all inputs on both sides
|
|
398
|
+
- [ ] No raw `ipcRenderer` exposed to renderer process
|
|
399
|
+
- [ ] CSP headers set (no unsafe-eval, no unsafe-inline for scripts)
|
|
400
|
+
- [ ] Credentials stored in OS keychain (not files or localStorage)
|
|
401
|
+
- [ ] File paths validated against allowlisted directories
|
|
402
|
+
- [ ] No shell command execution with user-controlled input
|
|
403
|
+
- [ ] Navigation restricted to trusted origins
|
|
404
|
+
- [ ] New window creation blocked (external links open in default browser)
|
|
405
|
+
- [ ] Update signatures verified before installation
|
|
406
|
+
- [ ] Updates served over HTTPS only
|
|
407
|
+
- [ ] Renderer cannot access arbitrary file system paths
|