@wazir-dev/cli 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/AGENTS.md +111 -0
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/assets/composition-engine.mmd +34 -0
- package/assets/demo-script.sh +17 -0
- package/assets/logo-dark.svg +14 -0
- package/assets/logo.svg +14 -0
- package/assets/pipeline.mmd +39 -0
- package/assets/record-demo.sh +51 -0
- package/docs/README.md +51 -0
- package/docs/adapters/context-mode.md +60 -0
- package/docs/concepts/architecture.md +87 -0
- package/docs/concepts/artifact-model.md +60 -0
- package/docs/concepts/composition-engine.md +36 -0
- package/docs/concepts/indexing-and-recall.md +160 -0
- package/docs/concepts/observability.md +41 -0
- package/docs/concepts/roles-and-workflows.md +59 -0
- package/docs/concepts/terminology-policy.md +27 -0
- package/docs/getting-started/01-installation.md +78 -0
- package/docs/getting-started/02-first-run.md +102 -0
- package/docs/getting-started/03-adding-to-project.md +15 -0
- package/docs/getting-started/04-host-setup.md +15 -0
- package/docs/guides/ci-integration.md +15 -0
- package/docs/guides/creating-skills.md +15 -0
- package/docs/guides/expertise-module-authoring.md +15 -0
- package/docs/guides/hook-development.md +15 -0
- package/docs/guides/memory-and-learnings.md +34 -0
- package/docs/guides/multi-host-export.md +15 -0
- package/docs/guides/troubleshooting.md +101 -0
- package/docs/guides/writing-custom-roles.md +15 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
- package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
- package/docs/readmes/INDEX.md +99 -0
- package/docs/readmes/features/expertise/README.md +171 -0
- package/docs/readmes/features/exports/README.md +222 -0
- package/docs/readmes/features/hooks/README.md +103 -0
- package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
- package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
- package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
- package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
- package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
- package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
- package/docs/readmes/features/hooks/session-start.md +119 -0
- package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
- package/docs/readmes/features/roles/README.md +157 -0
- package/docs/readmes/features/roles/clarifier.md +152 -0
- package/docs/readmes/features/roles/content-author.md +190 -0
- package/docs/readmes/features/roles/designer.md +193 -0
- package/docs/readmes/features/roles/executor.md +184 -0
- package/docs/readmes/features/roles/learner.md +210 -0
- package/docs/readmes/features/roles/planner.md +182 -0
- package/docs/readmes/features/roles/researcher.md +164 -0
- package/docs/readmes/features/roles/reviewer.md +184 -0
- package/docs/readmes/features/roles/specifier.md +162 -0
- package/docs/readmes/features/roles/verifier.md +215 -0
- package/docs/readmes/features/schemas/README.md +178 -0
- package/docs/readmes/features/skills/README.md +63 -0
- package/docs/readmes/features/skills/brainstorming.md +96 -0
- package/docs/readmes/features/skills/debugging.md +148 -0
- package/docs/readmes/features/skills/design.md +120 -0
- package/docs/readmes/features/skills/prepare-next.md +109 -0
- package/docs/readmes/features/skills/run-audit.md +159 -0
- package/docs/readmes/features/skills/scan-project.md +109 -0
- package/docs/readmes/features/skills/self-audit.md +176 -0
- package/docs/readmes/features/skills/tdd.md +137 -0
- package/docs/readmes/features/skills/using-skills.md +92 -0
- package/docs/readmes/features/skills/verification.md +120 -0
- package/docs/readmes/features/skills/writing-plans.md +104 -0
- package/docs/readmes/features/tooling/README.md +320 -0
- package/docs/readmes/features/workflows/README.md +186 -0
- package/docs/readmes/features/workflows/author.md +181 -0
- package/docs/readmes/features/workflows/clarify.md +154 -0
- package/docs/readmes/features/workflows/design-review.md +171 -0
- package/docs/readmes/features/workflows/design.md +169 -0
- package/docs/readmes/features/workflows/discover.md +162 -0
- package/docs/readmes/features/workflows/execute.md +173 -0
- package/docs/readmes/features/workflows/learn.md +167 -0
- package/docs/readmes/features/workflows/plan-review.md +165 -0
- package/docs/readmes/features/workflows/plan.md +170 -0
- package/docs/readmes/features/workflows/prepare-next.md +167 -0
- package/docs/readmes/features/workflows/review.md +169 -0
- package/docs/readmes/features/workflows/run-audit.md +191 -0
- package/docs/readmes/features/workflows/spec-challenge.md +159 -0
- package/docs/readmes/features/workflows/specify.md +160 -0
- package/docs/readmes/features/workflows/verify.md +177 -0
- package/docs/readmes/packages/README.md +50 -0
- package/docs/readmes/packages/ajv.md +117 -0
- package/docs/readmes/packages/context-mode.md +118 -0
- package/docs/readmes/packages/gray-matter.md +116 -0
- package/docs/readmes/packages/node-test.md +137 -0
- package/docs/readmes/packages/yaml.md +112 -0
- package/docs/reference/configuration-reference.md +159 -0
- package/docs/reference/expertise-index.md +52 -0
- package/docs/reference/git-flow.md +43 -0
- package/docs/reference/hooks.md +87 -0
- package/docs/reference/host-exports.md +50 -0
- package/docs/reference/launch-checklist.md +172 -0
- package/docs/reference/marketplace-listings.md +76 -0
- package/docs/reference/release-process.md +34 -0
- package/docs/reference/roles-reference.md +77 -0
- package/docs/reference/skills.md +33 -0
- package/docs/reference/templates.md +29 -0
- package/docs/reference/tooling-cli.md +94 -0
- package/docs/truth-claims.yaml +222 -0
- package/expertise/PROGRESS.md +63 -0
- package/expertise/README.md +18 -0
- package/expertise/antipatterns/PROGRESS.md +56 -0
- package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
- package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
- package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
- package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
- package/expertise/antipatterns/backend/index.md +24 -0
- package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
- package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
- package/expertise/antipatterns/code/async-antipatterns.md +622 -0
- package/expertise/antipatterns/code/code-smells.md +1186 -0
- package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
- package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
- package/expertise/antipatterns/code/index.md +27 -0
- package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
- package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
- package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
- package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
- package/expertise/antipatterns/design/dark-patterns.md +1121 -0
- package/expertise/antipatterns/design/index.md +22 -0
- package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
- package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
- package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
- package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
- package/expertise/antipatterns/frontend/index.md +23 -0
- package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
- package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
- package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
- package/expertise/antipatterns/index.md +31 -0
- package/expertise/antipatterns/performance/index.md +20 -0
- package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
- package/expertise/antipatterns/performance/premature-optimization.md +623 -0
- package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
- package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
- package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
- package/expertise/antipatterns/process/index.md +23 -0
- package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
- package/expertise/antipatterns/security/index.md +20 -0
- package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
- package/expertise/antipatterns/security/security-theater.md +843 -0
- package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
- package/expertise/architecture/PROGRESS.md +70 -0
- package/expertise/architecture/data/caching-architecture.md +671 -0
- package/expertise/architecture/data/data-consistency.md +574 -0
- package/expertise/architecture/data/data-modeling.md +536 -0
- package/expertise/architecture/data/event-streams-and-queues.md +634 -0
- package/expertise/architecture/data/index.md +25 -0
- package/expertise/architecture/data/search-architecture.md +663 -0
- package/expertise/architecture/data/sql-vs-nosql.md +708 -0
- package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
- package/expertise/architecture/decisions/build-vs-buy.md +616 -0
- package/expertise/architecture/decisions/index.md +23 -0
- package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
- package/expertise/architecture/decisions/technology-selection.md +616 -0
- package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
- package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
- package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
- package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
- package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
- package/expertise/architecture/distributed/index.md +25 -0
- package/expertise/architecture/distributed/saga-pattern.md +797 -0
- package/expertise/architecture/foundations/architectural-thinking.md +460 -0
- package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
- package/expertise/architecture/foundations/design-principles-solid.md +649 -0
- package/expertise/architecture/foundations/domain-driven-design.md +719 -0
- package/expertise/architecture/foundations/index.md +25 -0
- package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
- package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
- package/expertise/architecture/index.md +34 -0
- package/expertise/architecture/integration/api-design-graphql.md +638 -0
- package/expertise/architecture/integration/api-design-grpc.md +804 -0
- package/expertise/architecture/integration/api-design-rest.md +892 -0
- package/expertise/architecture/integration/index.md +25 -0
- package/expertise/architecture/integration/third-party-integration.md +795 -0
- package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
- package/expertise/architecture/integration/websockets-realtime.md +791 -0
- package/expertise/architecture/mobile-architecture/index.md +22 -0
- package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
- package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
- package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
- package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
- package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
- package/expertise/architecture/patterns/event-driven.md +797 -0
- package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
- package/expertise/architecture/patterns/index.md +27 -0
- package/expertise/architecture/patterns/layered-architecture.md +736 -0
- package/expertise/architecture/patterns/microservices.md +753 -0
- package/expertise/architecture/patterns/modular-monolith.md +692 -0
- package/expertise/architecture/patterns/monolith.md +626 -0
- package/expertise/architecture/patterns/plugin-architecture.md +735 -0
- package/expertise/architecture/patterns/serverless.md +780 -0
- package/expertise/architecture/scaling/database-scaling.md +615 -0
- package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
- package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
- package/expertise/architecture/scaling/index.md +24 -0
- package/expertise/architecture/scaling/multi-tenancy.md +800 -0
- package/expertise/architecture/scaling/stateless-design.md +787 -0
- package/expertise/backend/embedded-firmware.md +625 -0
- package/expertise/backend/go.md +853 -0
- package/expertise/backend/index.md +24 -0
- package/expertise/backend/java-spring.md +448 -0
- package/expertise/backend/node-typescript.md +625 -0
- package/expertise/backend/python-fastapi.md +724 -0
- package/expertise/backend/rust.md +458 -0
- package/expertise/backend/solidity.md +711 -0
- package/expertise/composition-map.yaml +443 -0
- package/expertise/content/foundations/content-modeling.md +395 -0
- package/expertise/content/foundations/editorial-standards.md +449 -0
- package/expertise/content/foundations/index.md +24 -0
- package/expertise/content/foundations/microcopy.md +455 -0
- package/expertise/content/foundations/terminology-governance.md +509 -0
- package/expertise/content/index.md +34 -0
- package/expertise/content/patterns/accessibility-copy.md +518 -0
- package/expertise/content/patterns/index.md +24 -0
- package/expertise/content/patterns/notification-content.md +433 -0
- package/expertise/content/patterns/sample-content.md +486 -0
- package/expertise/content/patterns/state-copy.md +439 -0
- package/expertise/design/PROGRESS.md +58 -0
- package/expertise/design/disciplines/dark-mode-theming.md +577 -0
- package/expertise/design/disciplines/design-systems.md +595 -0
- package/expertise/design/disciplines/index.md +25 -0
- package/expertise/design/disciplines/information-architecture.md +800 -0
- package/expertise/design/disciplines/interaction-design.md +788 -0
- package/expertise/design/disciplines/responsive-design.md +552 -0
- package/expertise/design/disciplines/usability-testing.md +516 -0
- package/expertise/design/disciplines/user-research.md +792 -0
- package/expertise/design/foundations/accessibility-design.md +796 -0
- package/expertise/design/foundations/color-theory.md +797 -0
- package/expertise/design/foundations/iconography.md +795 -0
- package/expertise/design/foundations/index.md +26 -0
- package/expertise/design/foundations/motion-and-animation.md +653 -0
- package/expertise/design/foundations/rtl-design.md +585 -0
- package/expertise/design/foundations/spacing-and-layout.md +607 -0
- package/expertise/design/foundations/typography.md +800 -0
- package/expertise/design/foundations/visual-hierarchy.md +761 -0
- package/expertise/design/index.md +32 -0
- package/expertise/design/patterns/authentication-flows.md +474 -0
- package/expertise/design/patterns/content-consumption.md +789 -0
- package/expertise/design/patterns/data-display.md +618 -0
- package/expertise/design/patterns/e-commerce.md +1494 -0
- package/expertise/design/patterns/feedback-and-states.md +642 -0
- package/expertise/design/patterns/forms-and-input.md +819 -0
- package/expertise/design/patterns/gamification.md +801 -0
- package/expertise/design/patterns/index.md +31 -0
- package/expertise/design/patterns/microinteractions.md +449 -0
- package/expertise/design/patterns/navigation.md +800 -0
- package/expertise/design/patterns/notifications.md +705 -0
- package/expertise/design/patterns/onboarding.md +700 -0
- package/expertise/design/patterns/search-and-filter.md +601 -0
- package/expertise/design/patterns/settings-and-preferences.md +768 -0
- package/expertise/design/patterns/social-and-community.md +748 -0
- package/expertise/design/platforms/desktop-native.md +612 -0
- package/expertise/design/platforms/index.md +25 -0
- package/expertise/design/platforms/mobile-android.md +825 -0
- package/expertise/design/platforms/mobile-cross-platform.md +983 -0
- package/expertise/design/platforms/mobile-ios.md +699 -0
- package/expertise/design/platforms/tablet.md +794 -0
- package/expertise/design/platforms/web-dashboard.md +790 -0
- package/expertise/design/platforms/web-responsive.md +550 -0
- package/expertise/design/psychology/behavioral-nudges.md +449 -0
- package/expertise/design/psychology/cognitive-load.md +1191 -0
- package/expertise/design/psychology/error-psychology.md +778 -0
- package/expertise/design/psychology/index.md +22 -0
- package/expertise/design/psychology/persuasive-design.md +736 -0
- package/expertise/design/psychology/user-mental-models.md +623 -0
- package/expertise/design/tooling/open-pencil.md +266 -0
- package/expertise/frontend/angular.md +1073 -0
- package/expertise/frontend/desktop-electron.md +546 -0
- package/expertise/frontend/flutter.md +782 -0
- package/expertise/frontend/index.md +27 -0
- package/expertise/frontend/native-android.md +409 -0
- package/expertise/frontend/native-ios.md +490 -0
- package/expertise/frontend/react-native.md +1160 -0
- package/expertise/frontend/react.md +808 -0
- package/expertise/frontend/vue.md +1089 -0
- package/expertise/humanize/domain-rules-code.md +79 -0
- package/expertise/humanize/domain-rules-content.md +67 -0
- package/expertise/humanize/domain-rules-technical-docs.md +56 -0
- package/expertise/humanize/index.md +35 -0
- package/expertise/humanize/self-audit-checklist.md +87 -0
- package/expertise/humanize/sentence-patterns.md +218 -0
- package/expertise/humanize/vocabulary-blacklist.md +105 -0
- package/expertise/i18n/PROGRESS.md +65 -0
- package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
- package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
- package/expertise/i18n/advanced/complex-scripts.md +30 -0
- package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
- package/expertise/i18n/advanced/testing-i18n.md +28 -0
- package/expertise/i18n/content/content-adaptation.md +23 -0
- package/expertise/i18n/content/locale-specific-formatting.md +23 -0
- package/expertise/i18n/content/machine-translation-integration.md +28 -0
- package/expertise/i18n/content/translation-management.md +29 -0
- package/expertise/i18n/foundations/date-time-calendars.md +67 -0
- package/expertise/i18n/foundations/i18n-architecture.md +272 -0
- package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
- package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
- package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
- package/expertise/i18n/foundations/string-externalization.md +236 -0
- package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
- package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
- package/expertise/i18n/index.md +38 -0
- package/expertise/i18n/platform/backend-i18n.md +31 -0
- package/expertise/i18n/platform/flutter-i18n.md +148 -0
- package/expertise/i18n/platform/native-android-i18n.md +36 -0
- package/expertise/i18n/platform/native-ios-i18n.md +36 -0
- package/expertise/i18n/platform/react-i18n.md +103 -0
- package/expertise/i18n/platform/web-css-i18n.md +81 -0
- package/expertise/i18n/rtl/arabic-specific.md +175 -0
- package/expertise/i18n/rtl/hebrew-specific.md +149 -0
- package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
- package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
- package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
- package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
- package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
- package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
- package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
- package/expertise/i18n/rtl/rtl-typography.md +160 -0
- package/expertise/index.md +113 -0
- package/expertise/index.yaml +216 -0
- package/expertise/infrastructure/cloud-aws.md +597 -0
- package/expertise/infrastructure/cloud-gcp.md +599 -0
- package/expertise/infrastructure/cybersecurity.md +816 -0
- package/expertise/infrastructure/database-mongodb.md +447 -0
- package/expertise/infrastructure/database-postgres.md +400 -0
- package/expertise/infrastructure/devops-cicd.md +787 -0
- package/expertise/infrastructure/index.md +27 -0
- package/expertise/performance/PROGRESS.md +50 -0
- package/expertise/performance/backend/api-latency.md +1204 -0
- package/expertise/performance/backend/background-jobs.md +506 -0
- package/expertise/performance/backend/connection-pooling.md +1209 -0
- package/expertise/performance/backend/database-query-optimization.md +515 -0
- package/expertise/performance/backend/index.md +23 -0
- package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
- package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
- package/expertise/performance/foundations/caching-strategies.md +489 -0
- package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
- package/expertise/performance/foundations/index.md +24 -0
- package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
- package/expertise/performance/foundations/memory-management.md +964 -0
- package/expertise/performance/foundations/performance-budgets.md +1314 -0
- package/expertise/performance/index.md +31 -0
- package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
- package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
- package/expertise/performance/infrastructure/index.md +22 -0
- package/expertise/performance/infrastructure/load-balancing.md +1081 -0
- package/expertise/performance/infrastructure/observability.md +1079 -0
- package/expertise/performance/mobile/index.md +23 -0
- package/expertise/performance/mobile/mobile-animations.md +544 -0
- package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
- package/expertise/performance/mobile/mobile-network.md +452 -0
- package/expertise/performance/mobile/mobile-rendering.md +599 -0
- package/expertise/performance/mobile/mobile-startup-time.md +505 -0
- package/expertise/performance/platform-specific/flutter-performance.md +647 -0
- package/expertise/performance/platform-specific/index.md +22 -0
- package/expertise/performance/platform-specific/node-performance.md +1307 -0
- package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
- package/expertise/performance/platform-specific/react-performance.md +1403 -0
- package/expertise/performance/web/bundle-optimization.md +1239 -0
- package/expertise/performance/web/image-and-media.md +636 -0
- package/expertise/performance/web/index.md +24 -0
- package/expertise/performance/web/network-optimization.md +1133 -0
- package/expertise/performance/web/rendering-performance.md +1098 -0
- package/expertise/performance/web/ssr-and-hydration.md +918 -0
- package/expertise/performance/web/web-vitals.md +1374 -0
- package/expertise/quality/accessibility.md +985 -0
- package/expertise/quality/evidence-based-verification.md +499 -0
- package/expertise/quality/index.md +24 -0
- package/expertise/quality/ml-model-audit.md +614 -0
- package/expertise/quality/performance.md +600 -0
- package/expertise/quality/testing-api.md +891 -0
- package/expertise/quality/testing-mobile.md +496 -0
- package/expertise/quality/testing-web.md +849 -0
- package/expertise/security/PROGRESS.md +54 -0
- package/expertise/security/agentic-identity.md +540 -0
- package/expertise/security/compliance-frameworks.md +601 -0
- package/expertise/security/data/data-encryption.md +364 -0
- package/expertise/security/data/data-privacy-gdpr.md +692 -0
- package/expertise/security/data/database-security.md +1171 -0
- package/expertise/security/data/index.md +22 -0
- package/expertise/security/data/pii-handling.md +531 -0
- package/expertise/security/foundations/authentication.md +1041 -0
- package/expertise/security/foundations/authorization.md +603 -0
- package/expertise/security/foundations/cryptography.md +1001 -0
- package/expertise/security/foundations/index.md +25 -0
- package/expertise/security/foundations/owasp-top-10.md +1354 -0
- package/expertise/security/foundations/secrets-management.md +1217 -0
- package/expertise/security/foundations/secure-sdlc.md +700 -0
- package/expertise/security/foundations/supply-chain-security.md +698 -0
- package/expertise/security/index.md +31 -0
- package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
- package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
- package/expertise/security/infrastructure/container-security.md +721 -0
- package/expertise/security/infrastructure/incident-response.md +1295 -0
- package/expertise/security/infrastructure/index.md +24 -0
- package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
- package/expertise/security/infrastructure/network-security.md +1337 -0
- package/expertise/security/mobile/index.md +23 -0
- package/expertise/security/mobile/mobile-android-security.md +1218 -0
- package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
- package/expertise/security/mobile/mobile-data-storage.md +1265 -0
- package/expertise/security/mobile/mobile-ios-security.md +1401 -0
- package/expertise/security/mobile/mobile-network-security.md +1520 -0
- package/expertise/security/smart-contract-security.md +594 -0
- package/expertise/security/testing/index.md +22 -0
- package/expertise/security/testing/penetration-testing.md +1258 -0
- package/expertise/security/testing/security-code-review.md +1765 -0
- package/expertise/security/testing/threat-modeling.md +1074 -0
- package/expertise/security/testing/vulnerability-scanning.md +1062 -0
- package/expertise/security/web/api-security.md +586 -0
- package/expertise/security/web/cors-and-headers.md +433 -0
- package/expertise/security/web/csrf.md +562 -0
- package/expertise/security/web/file-upload.md +1477 -0
- package/expertise/security/web/index.md +25 -0
- package/expertise/security/web/injection.md +1375 -0
- package/expertise/security/web/session-management.md +1101 -0
- package/expertise/security/web/xss.md +1158 -0
- package/exports/README.md +17 -0
- package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
- package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
- package/exports/hosts/claude/.claude/agents/designer.md +55 -0
- package/exports/hosts/claude/.claude/agents/executor.md +55 -0
- package/exports/hosts/claude/.claude/agents/learner.md +51 -0
- package/exports/hosts/claude/.claude/agents/planner.md +53 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
- package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
- package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
- package/exports/hosts/claude/.claude/commands/author.md +42 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
- package/exports/hosts/claude/.claude/commands/design.md +44 -0
- package/exports/hosts/claude/.claude/commands/discover.md +37 -0
- package/exports/hosts/claude/.claude/commands/execute.md +48 -0
- package/exports/hosts/claude/.claude/commands/learn.md +38 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
- package/exports/hosts/claude/.claude/commands/plan.md +39 -0
- package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
- package/exports/hosts/claude/.claude/commands/review.md +40 -0
- package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
- package/exports/hosts/claude/.claude/commands/specify.md +38 -0
- package/exports/hosts/claude/.claude/commands/verify.md +37 -0
- package/exports/hosts/claude/.claude/settings.json +34 -0
- package/exports/hosts/claude/CLAUDE.md +19 -0
- package/exports/hosts/claude/export.manifest.json +38 -0
- package/exports/hosts/claude/host-package.json +67 -0
- package/exports/hosts/codex/AGENTS.md +19 -0
- package/exports/hosts/codex/export.manifest.json +38 -0
- package/exports/hosts/codex/host-package.json +41 -0
- package/exports/hosts/cursor/.cursor/hooks.json +16 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
- package/exports/hosts/cursor/export.manifest.json +38 -0
- package/exports/hosts/cursor/host-package.json +42 -0
- package/exports/hosts/gemini/GEMINI.md +19 -0
- package/exports/hosts/gemini/export.manifest.json +38 -0
- package/exports/hosts/gemini/host-package.json +41 -0
- package/hooks/README.md +18 -0
- package/hooks/definitions/loop_cap_guard.yaml +21 -0
- package/hooks/definitions/post_tool_capture.yaml +24 -0
- package/hooks/definitions/pre_compact_summary.yaml +19 -0
- package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
- package/hooks/definitions/protected_path_write_guard.yaml +19 -0
- package/hooks/definitions/session_start.yaml +19 -0
- package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
- package/hooks/loop-cap-guard +17 -0
- package/hooks/post-tool-lint +36 -0
- package/hooks/protected-path-write-guard +17 -0
- package/hooks/session-start +41 -0
- package/llms-full.txt +2355 -0
- package/llms.txt +43 -0
- package/package.json +79 -0
- package/roles/README.md +20 -0
- package/roles/clarifier.md +42 -0
- package/roles/content-author.md +63 -0
- package/roles/designer.md +55 -0
- package/roles/executor.md +55 -0
- package/roles/learner.md +51 -0
- package/roles/planner.md +53 -0
- package/roles/researcher.md +43 -0
- package/roles/reviewer.md +54 -0
- package/roles/specifier.md +47 -0
- package/roles/verifier.md +71 -0
- package/schemas/README.md +24 -0
- package/schemas/accepted-learning.schema.json +20 -0
- package/schemas/author-artifact.schema.json +156 -0
- package/schemas/clarification.schema.json +19 -0
- package/schemas/design-artifact.schema.json +80 -0
- package/schemas/docs-claim.schema.json +18 -0
- package/schemas/export-manifest.schema.json +20 -0
- package/schemas/hook.schema.json +67 -0
- package/schemas/host-export-package.schema.json +18 -0
- package/schemas/implementation-plan.schema.json +19 -0
- package/schemas/proposed-learning.schema.json +19 -0
- package/schemas/research.schema.json +18 -0
- package/schemas/review.schema.json +29 -0
- package/schemas/run-manifest.schema.json +18 -0
- package/schemas/spec-challenge.schema.json +18 -0
- package/schemas/spec.schema.json +20 -0
- package/schemas/usage.schema.json +102 -0
- package/schemas/verification-proof.schema.json +29 -0
- package/schemas/wazir-manifest.schema.json +173 -0
- package/skills/README.md +40 -0
- package/skills/brainstorming/SKILL.md +77 -0
- package/skills/debugging/SKILL.md +50 -0
- package/skills/design/SKILL.md +61 -0
- package/skills/dispatching-parallel-agents/SKILL.md +128 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +169 -0
- package/skills/humanize/SKILL.md +123 -0
- package/skills/init-pipeline/SKILL.md +124 -0
- package/skills/prepare-next/SKILL.md +20 -0
- package/skills/receiving-code-review/SKILL.md +123 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +108 -0
- package/skills/run-audit/SKILL.md +197 -0
- package/skills/scan-project/SKILL.md +41 -0
- package/skills/self-audit/SKILL.md +153 -0
- package/skills/subagent-driven-development/SKILL.md +154 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +102 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tdd/SKILL.md +23 -0
- package/skills/using-git-worktrees/SKILL.md +163 -0
- package/skills/using-skills/SKILL.md +95 -0
- package/skills/verification/SKILL.md +22 -0
- package/skills/wazir/SKILL.md +463 -0
- package/skills/writing-plans/SKILL.md +30 -0
- package/skills/writing-skills/SKILL.md +157 -0
- package/skills/writing-skills/anthropic-best-practices.md +122 -0
- package/skills/writing-skills/persuasion-principles.md +50 -0
- package/templates/README.md +20 -0
- package/templates/artifacts/README.md +10 -0
- package/templates/artifacts/accepted-learning.md +19 -0
- package/templates/artifacts/accepted-learning.template.json +12 -0
- package/templates/artifacts/author.md +74 -0
- package/templates/artifacts/author.template.json +19 -0
- package/templates/artifacts/clarification.md +21 -0
- package/templates/artifacts/clarification.template.json +12 -0
- package/templates/artifacts/execute-notes.md +19 -0
- package/templates/artifacts/implementation-plan.md +21 -0
- package/templates/artifacts/implementation-plan.template.json +11 -0
- package/templates/artifacts/learning-proposal.md +19 -0
- package/templates/artifacts/next-run-handoff.md +21 -0
- package/templates/artifacts/plan-review.md +19 -0
- package/templates/artifacts/proposed-learning.template.json +12 -0
- package/templates/artifacts/research.md +21 -0
- package/templates/artifacts/research.template.json +12 -0
- package/templates/artifacts/review-findings.md +19 -0
- package/templates/artifacts/review.template.json +11 -0
- package/templates/artifacts/run-manifest.template.json +8 -0
- package/templates/artifacts/spec-challenge.md +19 -0
- package/templates/artifacts/spec-challenge.template.json +11 -0
- package/templates/artifacts/spec.md +21 -0
- package/templates/artifacts/spec.template.json +12 -0
- package/templates/artifacts/verification-proof.md +19 -0
- package/templates/artifacts/verification-proof.template.json +11 -0
- package/templates/examples/accepted-learning.example.json +14 -0
- package/templates/examples/author.example.json +152 -0
- package/templates/examples/clarification.example.json +15 -0
- package/templates/examples/docs-claim.example.json +8 -0
- package/templates/examples/export-manifest.example.json +7 -0
- package/templates/examples/host-export-package.example.json +11 -0
- package/templates/examples/implementation-plan.example.json +17 -0
- package/templates/examples/proposed-learning.example.json +13 -0
- package/templates/examples/research.example.json +15 -0
- package/templates/examples/research.example.md +6 -0
- package/templates/examples/review.example.json +17 -0
- package/templates/examples/run-manifest.example.json +9 -0
- package/templates/examples/spec-challenge.example.json +14 -0
- package/templates/examples/spec.example.json +21 -0
- package/templates/examples/verification-proof.example.json +21 -0
- package/templates/examples/wazir-manifest.example.yaml +65 -0
- package/templates/task-definition-schema.md +99 -0
- package/tooling/README.md +20 -0
- package/tooling/src/adapters/context-mode.js +50 -0
- package/tooling/src/capture/command.js +376 -0
- package/tooling/src/capture/store.js +99 -0
- package/tooling/src/capture/usage.js +270 -0
- package/tooling/src/checks/branches.js +50 -0
- package/tooling/src/checks/brand-truth.js +110 -0
- package/tooling/src/checks/changelog.js +231 -0
- package/tooling/src/checks/command-registry.js +36 -0
- package/tooling/src/checks/commits.js +102 -0
- package/tooling/src/checks/docs-drift.js +103 -0
- package/tooling/src/checks/docs-truth.js +201 -0
- package/tooling/src/checks/runtime-surface.js +156 -0
- package/tooling/src/cli.js +116 -0
- package/tooling/src/command-options.js +56 -0
- package/tooling/src/commands/validate.js +320 -0
- package/tooling/src/doctor/command.js +91 -0
- package/tooling/src/export/command.js +77 -0
- package/tooling/src/export/compiler.js +498 -0
- package/tooling/src/guards/loop-cap-guard.js +52 -0
- package/tooling/src/guards/protected-path-write-guard.js +67 -0
- package/tooling/src/index/command.js +152 -0
- package/tooling/src/index/storage.js +1061 -0
- package/tooling/src/index/summarizers.js +261 -0
- package/tooling/src/loaders.js +18 -0
- package/tooling/src/project-root.js +22 -0
- package/tooling/src/recall/command.js +225 -0
- package/tooling/src/schema-validator.js +30 -0
- package/tooling/src/state-root.js +40 -0
- package/tooling/src/status/command.js +71 -0
- package/wazir.manifest.yaml +135 -0
- package/workflows/README.md +19 -0
- package/workflows/author.md +42 -0
- package/workflows/clarify.md +38 -0
- package/workflows/design-review.md +46 -0
- package/workflows/design.md +44 -0
- package/workflows/discover.md +37 -0
- package/workflows/execute.md +48 -0
- package/workflows/learn.md +38 -0
- package/workflows/plan-review.md +42 -0
- package/workflows/plan.md +39 -0
- package/workflows/prepare-next.md +37 -0
- package/workflows/review.md +40 -0
- package/workflows/run-audit.md +41 -0
- package/workflows/spec-challenge.md +41 -0
- package/workflows/specify.md +38 -0
- package/workflows/verify.md +37 -0
|
@@ -0,0 +1,1217 @@
|
|
|
1
|
+
# Secrets Management — Security Expertise Module
|
|
2
|
+
|
|
3
|
+
> **Purpose:** Comprehensive reference for AI agents to ensure secrets are never hardcoded,
|
|
4
|
+
> leaked, or mismanaged in any codebase, pipeline, or deployment artifact.
|
|
5
|
+
>
|
|
6
|
+
> **Last updated:** 2026-03-08
|
|
7
|
+
> **Sources:** GitGuardian State of Secrets Sprawl 2025, GitHub Security Blog, OWASP Secrets
|
|
8
|
+
> Management Cheat Sheet, NIST SP 800-57, PCI-DSS v4.0.1, CWE/MITRE, vendor documentation.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Threat Landscape
|
|
13
|
+
|
|
14
|
+
### 1.1 Scale of the Problem
|
|
15
|
+
|
|
16
|
+
Secret sprawl is one of the most pervasive and underestimated security risks in modern
|
|
17
|
+
software development. The numbers are staggering:
|
|
18
|
+
|
|
19
|
+
- **39 million secrets** were leaked across GitHub repositories in 2024 alone (GitHub Security).
|
|
20
|
+
- GitGuardian independently detected **23.8 million new hardcoded secrets** in public GitHub
|
|
21
|
+
repos in 2024 — a **25% year-over-year increase**.
|
|
22
|
+
- **70% of secrets leaked in 2022 remain valid today**, giving attackers prolonged access.
|
|
23
|
+
- **22% of all breaches** in 2025 are driven by stolen or leaked credentials (Verizon DBIR).
|
|
24
|
+
- **65% of top private AI companies** had exposed API keys or tokens in public GitHub repos.
|
|
25
|
+
- GitHub Copilot users showed a **6.4% secret leakage rate** in public repositories.
|
|
26
|
+
|
|
27
|
+
### 1.2 Where Secrets Leak
|
|
28
|
+
|
|
29
|
+
| Attack Surface | Detail |
|
|
30
|
+
|-----------------------------|---------------------------------------------------------------|
|
|
31
|
+
| Source code repositories | Hardcoded API keys, passwords, tokens committed to Git |
|
|
32
|
+
| `.env` files | Exposed via misconfigured web servers, committed to repos |
|
|
33
|
+
| Docker images | 98% of detected secrets found in Docker image layers |
|
|
34
|
+
| CI/CD logs | Secrets printed to build output, stored in plain text |
|
|
35
|
+
| Collaboration tools | 6.1% of Jira tickets and 2.4% of Slack channels contain secrets |
|
|
36
|
+
| Client-side code | API keys embedded in JavaScript bundles, mobile app binaries |
|
|
37
|
+
| URL parameters | Tokens passed in query strings, logged by proxies and servers |
|
|
38
|
+
| Infrastructure-as-Code | Cloud credentials in Terraform state files, Ansible playbooks |
|
|
39
|
+
| Git history | Secrets removed from HEAD but still in commit history |
|
|
40
|
+
|
|
41
|
+
### 1.3 Real-World Breaches
|
|
42
|
+
|
|
43
|
+
**Uber (2016) — AWS Keys in GitHub Repository**
|
|
44
|
+
Attackers discovered AWS administrator credentials hardcoded in a private GitHub repository.
|
|
45
|
+
Using these credentials, they accessed an S3 bucket containing data on 57 million users and
|
|
46
|
+
600,000 driver license numbers. Uber paid the attackers $100,000 to delete the data and
|
|
47
|
+
concealed the breach for over a year. The eventual disclosure led to a $148 million settlement
|
|
48
|
+
with all 50 U.S. states.
|
|
49
|
+
|
|
50
|
+
**Toyota (2022) — Access Key Public on GitHub for 5 Years**
|
|
51
|
+
In December 2017, a subcontractor uploaded T-Connect source code to a public GitHub repo
|
|
52
|
+
containing a hardcoded access key to the customer data server. The exposure went undetected
|
|
53
|
+
until September 2022, potentially compromising 296,019 customer records (IDs and emails)
|
|
54
|
+
across nearly five years.
|
|
55
|
+
|
|
56
|
+
**Samsung (2022) — Lapsus$ Source Code Leak**
|
|
57
|
+
The Lapsus$ group exfiltrated 190GB of Samsung source code, which contained thousands of
|
|
58
|
+
hardcoded credentials and secrets. The leaked data included TrustZone source code, biometric
|
|
59
|
+
unlock algorithms, bootloader code, and confidential Qualcomm data.
|
|
60
|
+
|
|
61
|
+
**CircleCI (2023) — Mass Secrets Rotation Incident**
|
|
62
|
+
Unauthorized access on December 19, 2022 led to exfiltration of customer environment
|
|
63
|
+
variables, keys, and tokens on December 22. CircleCI advised all customers to rotate every
|
|
64
|
+
secret stored in the platform — OAuth tokens, API keys, SSH keys, and cloud credentials.
|
|
65
|
+
The incident forced organization-wide secrets rotation across thousands of companies.
|
|
66
|
+
|
|
67
|
+
**U.S. Treasury (2024) — Single Leaked API Key**
|
|
68
|
+
A compromise of the U.S. Treasury Department was traced to a single leaked API key for an
|
|
69
|
+
authentication platform, demonstrating that one exposed secret can compromise an entire
|
|
70
|
+
government agency.
|
|
71
|
+
|
|
72
|
+
**Large-Scale .env Extortion Campaign (2024)**
|
|
73
|
+
Attackers scanned 26.8 million IP addresses, harvesting credentials from publicly exposed
|
|
74
|
+
`.env` files. They extracted 1,185 AWS access keys, 333 PayPal OAuth tokens, 235 GitHub
|
|
75
|
+
tokens, and used compromised AWS infrastructure to encrypt S3 buckets for ransom.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 2. Core Security Principles
|
|
80
|
+
|
|
81
|
+
### 2.1 The Seven Commandments of Secrets Management
|
|
82
|
+
|
|
83
|
+
1. **Never hardcode secrets.** No credentials in source code, config files committed to VCS,
|
|
84
|
+
or compiled binaries — no exceptions, not even for "local development only."
|
|
85
|
+
|
|
86
|
+
2. **Rotate regularly.** Every secret has a shelf life. Automate rotation on a schedule
|
|
87
|
+
(90 days maximum for most credentials, shorter for high-privilege keys).
|
|
88
|
+
|
|
89
|
+
3. **Least privilege.** Each secret grants the minimum permissions required. A database
|
|
90
|
+
credential for a read-only service should not have write access.
|
|
91
|
+
|
|
92
|
+
4. **Encrypt at rest and in transit.** Secrets stored in vaults must be encrypted with
|
|
93
|
+
AES-256 or equivalent. Transmission must use TLS 1.2+.
|
|
94
|
+
|
|
95
|
+
5. **Audit all access.** Every read, write, and rotation of a secret must be logged with
|
|
96
|
+
identity, timestamp, and purpose. Alert on anomalous access patterns.
|
|
97
|
+
|
|
98
|
+
6. **Separate by environment.** Development, staging, and production must use different
|
|
99
|
+
secrets. A compromised dev key must never grant production access.
|
|
100
|
+
|
|
101
|
+
7. **Assume breach.** Design systems so that any single compromised secret has a limited
|
|
102
|
+
blast radius. Use short-lived tokens, scoped permissions, and defense in depth.
|
|
103
|
+
|
|
104
|
+
### 2.2 Defense in Depth for Secrets
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
Layer 1: Prevention — Pre-commit hooks block secrets before they enter Git
|
|
108
|
+
Layer 2: Detection — CI scanners catch secrets that bypass pre-commit
|
|
109
|
+
Layer 3: Remediation — Automated rotation on detection, alert pipelines
|
|
110
|
+
Layer 4: Monitoring — Runtime detection of secret misuse, anomaly alerts
|
|
111
|
+
Layer 5: Response — Incident playbooks for leaked credential scenarios
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 3. Implementation Patterns
|
|
117
|
+
|
|
118
|
+
### 3.1 Environment Variables — Proper Usage
|
|
119
|
+
|
|
120
|
+
Environment variables are the baseline mechanism for injecting secrets at runtime.
|
|
121
|
+
|
|
122
|
+
**Correct pattern:**
|
|
123
|
+
```bash
|
|
124
|
+
# Secrets loaded from a secure source into the process environment
|
|
125
|
+
export DATABASE_URL="postgres://user:${DB_PASS}@host:5432/db"
|
|
126
|
+
|
|
127
|
+
# Application reads at startup
|
|
128
|
+
const dbUrl = process.env.DATABASE_URL;
|
|
129
|
+
if (!dbUrl) throw new Error("DATABASE_URL is required");
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**Common mistakes to avoid:**
|
|
133
|
+
- Never commit `.env` files to version control
|
|
134
|
+
- Never log environment variables (especially in error handlers or debug output)
|
|
135
|
+
- Never pass secrets via command-line arguments (visible in `ps` output)
|
|
136
|
+
- Never embed secrets in Dockerfiles (`ENV SECRET=...` persists in image layers)
|
|
137
|
+
|
|
138
|
+
### 3.2 Secret Managers — Enterprise Solutions
|
|
139
|
+
|
|
140
|
+
**AWS Secrets Manager**
|
|
141
|
+
- Automatic rotation with Lambda functions
|
|
142
|
+
- Fine-grained IAM policies for access control
|
|
143
|
+
- Cross-account secret sharing
|
|
144
|
+
- Native integration with RDS, Redshift, DocumentDB
|
|
145
|
+
- Versioning with staging labels (AWSCURRENT, AWSPENDING, AWSPREVIOUS)
|
|
146
|
+
|
|
147
|
+
**GCP Secret Manager**
|
|
148
|
+
- IAM-based access control per secret version
|
|
149
|
+
- Automatic replication across regions
|
|
150
|
+
- Customer-managed encryption keys (CMEK)
|
|
151
|
+
- Integration with Cloud Run, GKE, Cloud Functions
|
|
152
|
+
- Audit logging via Cloud Audit Logs
|
|
153
|
+
|
|
154
|
+
**HashiCorp Vault**
|
|
155
|
+
- Dynamic secrets: generates credentials on demand with automatic TTL expiry
|
|
156
|
+
- Multiple auth methods: AppRole, Kubernetes, AWS IAM, OIDC, LDAP
|
|
157
|
+
- Encryption as a service (Transit secrets engine)
|
|
158
|
+
- Namespaces for multi-tenant isolation
|
|
159
|
+
- Policy-as-code with HCL
|
|
160
|
+
- High availability with Raft or Consul backend
|
|
161
|
+
|
|
162
|
+
**Azure Key Vault**
|
|
163
|
+
- HSM-backed key storage (FIPS 140-2 Level 2/3)
|
|
164
|
+
- Managed identity integration (no credentials needed)
|
|
165
|
+
- Certificate lifecycle management
|
|
166
|
+
- Soft-delete and purge protection
|
|
167
|
+
|
|
168
|
+
### 3.3 .gitignore Patterns for Secrets
|
|
169
|
+
|
|
170
|
+
```gitignore
|
|
171
|
+
# ---- Environment & Secrets ----
|
|
172
|
+
.env
|
|
173
|
+
.env.*
|
|
174
|
+
!.env.example
|
|
175
|
+
!.env.template
|
|
176
|
+
|
|
177
|
+
# ---- Private Keys & Certificates ----
|
|
178
|
+
*.pem
|
|
179
|
+
*.key
|
|
180
|
+
*.p12
|
|
181
|
+
*.pfx
|
|
182
|
+
*.jks
|
|
183
|
+
*.keystore
|
|
184
|
+
id_rsa
|
|
185
|
+
id_ed25519
|
|
186
|
+
|
|
187
|
+
# ---- Cloud Credentials ----
|
|
188
|
+
credentials.json
|
|
189
|
+
service-account*.json
|
|
190
|
+
*-credentials.json
|
|
191
|
+
.aws/credentials
|
|
192
|
+
.gcloud/
|
|
193
|
+
.azure/
|
|
194
|
+
|
|
195
|
+
# ---- IDE & Editor Secrets ----
|
|
196
|
+
.idea/**/dataSources/
|
|
197
|
+
.vscode/settings.json
|
|
198
|
+
|
|
199
|
+
# ---- Terraform State (may contain secrets) ----
|
|
200
|
+
*.tfstate
|
|
201
|
+
*.tfstate.backup
|
|
202
|
+
.terraform/
|
|
203
|
+
|
|
204
|
+
# ---- Docker Secrets ----
|
|
205
|
+
docker-compose.override.yml
|
|
206
|
+
.docker/config.json
|
|
207
|
+
|
|
208
|
+
# ---- Miscellaneous ----
|
|
209
|
+
*.secret
|
|
210
|
+
*.secrets
|
|
211
|
+
secret.*
|
|
212
|
+
secrets.*
|
|
213
|
+
token.txt
|
|
214
|
+
api_key.txt
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 3.4 Secret Rotation Automation
|
|
218
|
+
|
|
219
|
+
```python
|
|
220
|
+
#!/usr/bin/env python3
|
|
221
|
+
"""Automated secret rotation for AWS Secrets Manager."""
|
|
222
|
+
|
|
223
|
+
import boto3
|
|
224
|
+
import json
|
|
225
|
+
import string
|
|
226
|
+
import secrets as stdlib_secrets
|
|
227
|
+
from datetime import datetime
|
|
228
|
+
|
|
229
|
+
def generate_password(length: int = 32) -> str:
|
|
230
|
+
"""Generate a cryptographically secure password."""
|
|
231
|
+
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
|
|
232
|
+
return ''.join(stdlib_secrets.choice(alphabet) for _ in range(length))
|
|
233
|
+
|
|
234
|
+
def rotate_secret(secret_id: str, region: str = "us-east-1") -> dict:
|
|
235
|
+
"""Rotate a secret in AWS Secrets Manager."""
|
|
236
|
+
client = boto3.client("secretsmanager", region_name=region)
|
|
237
|
+
|
|
238
|
+
# Step 1: Retrieve current secret
|
|
239
|
+
current = client.get_secret_value(SecretId=secret_id)
|
|
240
|
+
secret_data = json.loads(current["SecretString"])
|
|
241
|
+
|
|
242
|
+
# Step 2: Generate new credential
|
|
243
|
+
new_password = generate_password()
|
|
244
|
+
secret_data["password"] = new_password
|
|
245
|
+
secret_data["rotated_at"] = datetime.utcnow().isoformat()
|
|
246
|
+
|
|
247
|
+
# Step 3: Update the secret (creates a new version)
|
|
248
|
+
client.put_secret_value(
|
|
249
|
+
SecretId=secret_id,
|
|
250
|
+
SecretString=json.dumps(secret_data),
|
|
251
|
+
VersionStages=["AWSCURRENT"],
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
# Step 4: Update the downstream service (e.g., database password)
|
|
255
|
+
# update_database_password(secret_data["username"], new_password)
|
|
256
|
+
|
|
257
|
+
return {"secret_id": secret_id, "rotated_at": secret_data["rotated_at"]}
|
|
258
|
+
|
|
259
|
+
if __name__ == "__main__":
|
|
260
|
+
result = rotate_secret("prod/database/main")
|
|
261
|
+
print(f"Rotated: {result['secret_id']} at {result['rotated_at']}")
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 3.5 Kubernetes Secrets
|
|
265
|
+
|
|
266
|
+
Native Kubernetes Secrets are base64-encoded (not encrypted) by default. This is
|
|
267
|
+
insufficient for production.
|
|
268
|
+
|
|
269
|
+
**Best practices:**
|
|
270
|
+
- Enable encryption at rest in etcd (`EncryptionConfiguration` with `aescbc` or `aesgcm`)
|
|
271
|
+
- Use the External Secrets Operator (ESO) to sync from Vault/AWS/GCP/Azure
|
|
272
|
+
- Apply RBAC to restrict `get`, `list`, `watch` on Secret resources
|
|
273
|
+
- Use `projected` volumes instead of environment variables to avoid secrets in `kubectl describe`
|
|
274
|
+
- Never store secrets in ConfigMaps
|
|
275
|
+
- Set NetworkPolicies to restrict ESO pod communication
|
|
276
|
+
|
|
277
|
+
**External Secrets Operator example:**
|
|
278
|
+
```yaml
|
|
279
|
+
apiVersion: external-secrets.io/v1beta1
|
|
280
|
+
kind: ExternalSecret
|
|
281
|
+
metadata:
|
|
282
|
+
name: database-credentials
|
|
283
|
+
namespace: production
|
|
284
|
+
spec:
|
|
285
|
+
refreshInterval: 1h
|
|
286
|
+
secretStoreRef:
|
|
287
|
+
name: aws-secrets-manager
|
|
288
|
+
kind: ClusterSecretStore
|
|
289
|
+
target:
|
|
290
|
+
name: db-credentials
|
|
291
|
+
creationPolicy: Owner
|
|
292
|
+
data:
|
|
293
|
+
- secretKey: username
|
|
294
|
+
remoteRef:
|
|
295
|
+
key: prod/database/main
|
|
296
|
+
property: username
|
|
297
|
+
- secretKey: password
|
|
298
|
+
remoteRef:
|
|
299
|
+
key: prod/database/main
|
|
300
|
+
property: password
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 3.6 CI/CD Secret Injection
|
|
304
|
+
|
|
305
|
+
**GitHub Actions:**
|
|
306
|
+
```yaml
|
|
307
|
+
jobs:
|
|
308
|
+
deploy:
|
|
309
|
+
runs-on: ubuntu-latest
|
|
310
|
+
steps:
|
|
311
|
+
- name: Deploy
|
|
312
|
+
env:
|
|
313
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
|
314
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
|
315
|
+
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
|
316
|
+
run: |
|
|
317
|
+
# Secrets are masked in logs automatically
|
|
318
|
+
./deploy.sh
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**GitLab CI:**
|
|
322
|
+
```yaml
|
|
323
|
+
deploy:
|
|
324
|
+
stage: deploy
|
|
325
|
+
variables:
|
|
326
|
+
# References CI/CD variable set in GitLab UI (Settings > CI/CD > Variables)
|
|
327
|
+
DATABASE_URL: $DATABASE_URL
|
|
328
|
+
script:
|
|
329
|
+
- ./deploy.sh
|
|
330
|
+
environment:
|
|
331
|
+
name: production
|
|
332
|
+
rules:
|
|
333
|
+
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Key rules for CI/CD secrets:**
|
|
337
|
+
- Never echo or print secret values in build scripts
|
|
338
|
+
- Use masked variables (GitHub masks by default; GitLab requires "Mask variable" checkbox)
|
|
339
|
+
- Scope secrets to specific environments (production, staging)
|
|
340
|
+
- Use OIDC federation instead of long-lived access keys where possible
|
|
341
|
+
- Audit CI/CD variable access regularly
|
|
342
|
+
- Rotate CI/CD secrets after any team member departure
|
|
343
|
+
|
|
344
|
+
### 3.7 Runtime Secret Loading — Secure Config Pattern
|
|
345
|
+
|
|
346
|
+
**TypeScript (Node.js):**
|
|
347
|
+
```typescript
|
|
348
|
+
import {
|
|
349
|
+
SecretsManagerClient,
|
|
350
|
+
GetSecretValueCommand,
|
|
351
|
+
} from "@aws-sdk/client-secrets-manager";
|
|
352
|
+
|
|
353
|
+
interface AppSecrets {
|
|
354
|
+
databaseUrl: string;
|
|
355
|
+
apiKey: string;
|
|
356
|
+
jwtSecret: string;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
async function loadSecrets(): Promise<AppSecrets> {
|
|
360
|
+
// In production, load from a secret manager
|
|
361
|
+
if (process.env.NODE_ENV === "production") {
|
|
362
|
+
const client = new SecretsManagerClient({ region: "us-east-1" });
|
|
363
|
+
const command = new GetSecretValueCommand({ SecretId: "prod/app/config" });
|
|
364
|
+
const response = await client.send(command);
|
|
365
|
+
const parsed = JSON.parse(response.SecretString!);
|
|
366
|
+
return {
|
|
367
|
+
databaseUrl: parsed.database_url,
|
|
368
|
+
apiKey: parsed.api_key,
|
|
369
|
+
jwtSecret: parsed.jwt_secret,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// In development, load from environment variables (sourced from .env locally)
|
|
374
|
+
const required = ["DATABASE_URL", "API_KEY", "JWT_SECRET"];
|
|
375
|
+
for (const key of required) {
|
|
376
|
+
if (!process.env[key]) {
|
|
377
|
+
throw new Error(`Missing required environment variable: ${key}`);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
databaseUrl: process.env.DATABASE_URL!,
|
|
382
|
+
apiKey: process.env.API_KEY!,
|
|
383
|
+
jwtSecret: process.env.JWT_SECRET!,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Load once at startup, pass via dependency injection — never as globals
|
|
388
|
+
const secrets = await loadSecrets();
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Python:**
|
|
392
|
+
```python
|
|
393
|
+
import os
|
|
394
|
+
import json
|
|
395
|
+
from dataclasses import dataclass
|
|
396
|
+
from functools import lru_cache
|
|
397
|
+
|
|
398
|
+
import boto3
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
@dataclass(frozen=True)
|
|
402
|
+
class AppSecrets:
|
|
403
|
+
database_url: str
|
|
404
|
+
api_key: str
|
|
405
|
+
jwt_secret: str
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
@lru_cache(maxsize=1)
|
|
409
|
+
def load_secrets() -> AppSecrets:
|
|
410
|
+
"""Load secrets from AWS Secrets Manager in production, env vars in dev."""
|
|
411
|
+
if os.getenv("ENV") == "production":
|
|
412
|
+
client = boto3.client("secretsmanager", region_name="us-east-1")
|
|
413
|
+
response = client.get_secret_value(SecretId="prod/app/config")
|
|
414
|
+
data = json.loads(response["SecretString"])
|
|
415
|
+
return AppSecrets(
|
|
416
|
+
database_url=data["database_url"],
|
|
417
|
+
api_key=data["api_key"],
|
|
418
|
+
jwt_secret=data["jwt_secret"],
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
# Development: require explicit env vars
|
|
422
|
+
required = ["DATABASE_URL", "API_KEY", "JWT_SECRET"]
|
|
423
|
+
missing = [k for k in required if k not in os.environ]
|
|
424
|
+
if missing:
|
|
425
|
+
raise EnvironmentError(f"Missing required env vars: {', '.join(missing)}")
|
|
426
|
+
|
|
427
|
+
return AppSecrets(
|
|
428
|
+
database_url=os.environ["DATABASE_URL"],
|
|
429
|
+
api_key=os.environ["API_KEY"],
|
|
430
|
+
jwt_secret=os.environ["JWT_SECRET"],
|
|
431
|
+
)
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## 4. Vulnerability Catalog
|
|
437
|
+
|
|
438
|
+
### 4.1 CWE-798: Use of Hard-coded Credentials
|
|
439
|
+
|
|
440
|
+
**Severity:** Critical | **CVSS:** 9.8 | **OWASP:** A07:2021 (Identification & Auth Failures)
|
|
441
|
+
|
|
442
|
+
Embedding passwords, API keys, or cryptographic keys directly in source code.
|
|
443
|
+
|
|
444
|
+
```typescript
|
|
445
|
+
// VULNERABLE: Hardcoded API key
|
|
446
|
+
const stripe = new Stripe("REDACTED_STRIPE_KEY");
|
|
447
|
+
|
|
448
|
+
// SECURE: Loaded from environment
|
|
449
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### 4.2 CWE-312: Cleartext Storage of Sensitive Information
|
|
453
|
+
|
|
454
|
+
**Severity:** High | **CVSS:** 7.5
|
|
455
|
+
|
|
456
|
+
Storing secrets in plaintext config files, databases, or shared storage.
|
|
457
|
+
|
|
458
|
+
```yaml
|
|
459
|
+
# VULNERABLE: Plaintext in docker-compose.yml committed to git
|
|
460
|
+
services:
|
|
461
|
+
db:
|
|
462
|
+
environment:
|
|
463
|
+
POSTGRES_PASSWORD: "SuperSecret123!"
|
|
464
|
+
|
|
465
|
+
# SECURE: Reference external secret or env file not in VCS
|
|
466
|
+
services:
|
|
467
|
+
db:
|
|
468
|
+
environment:
|
|
469
|
+
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
470
|
+
env_file:
|
|
471
|
+
- .env # .env is in .gitignore
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### 4.3 CWE-532: Insertion of Sensitive Information into Log File
|
|
475
|
+
|
|
476
|
+
**Severity:** High | **CVSS:** 7.5
|
|
477
|
+
|
|
478
|
+
Logging secrets in application logs, error messages, or debug output.
|
|
479
|
+
|
|
480
|
+
```python
|
|
481
|
+
# VULNERABLE: Logging the full connection string including password
|
|
482
|
+
logger.info(f"Connecting to database: {database_url}")
|
|
483
|
+
logger.error(f"Auth failed with token: {api_token}")
|
|
484
|
+
|
|
485
|
+
# SECURE: Redact sensitive values before logging
|
|
486
|
+
def redact_url(url: str) -> str:
|
|
487
|
+
"""Replace password in connection string with ***."""
|
|
488
|
+
from urllib.parse import urlparse, urlunparse
|
|
489
|
+
parsed = urlparse(url)
|
|
490
|
+
if parsed.password:
|
|
491
|
+
replaced = parsed._replace(
|
|
492
|
+
netloc=f"{parsed.username}:***@{parsed.hostname}:{parsed.port}"
|
|
493
|
+
)
|
|
494
|
+
return urlunparse(replaced)
|
|
495
|
+
return url
|
|
496
|
+
|
|
497
|
+
logger.info(f"Connecting to database: {redact_url(database_url)}")
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### 4.4 CWE-311: Missing Encryption of Sensitive Data
|
|
501
|
+
|
|
502
|
+
**Severity:** High | **CVSS:** 7.5
|
|
503
|
+
|
|
504
|
+
Secrets transmitted or stored without encryption.
|
|
505
|
+
|
|
506
|
+
### 4.5 CWE-522: Insufficiently Protected Credentials
|
|
507
|
+
|
|
508
|
+
**Severity:** High | **CVSS:** 7.5
|
|
509
|
+
|
|
510
|
+
Using weak encryption, reversible encoding (base64), or insufficient access controls
|
|
511
|
+
for credential storage.
|
|
512
|
+
|
|
513
|
+
```yaml
|
|
514
|
+
# VULNERABLE: Kubernetes Secret — base64 is NOT encryption
|
|
515
|
+
apiVersion: v1
|
|
516
|
+
kind: Secret
|
|
517
|
+
metadata:
|
|
518
|
+
name: db-creds
|
|
519
|
+
type: Opaque
|
|
520
|
+
data:
|
|
521
|
+
# echo -n "admin" | base64 → easily reversible
|
|
522
|
+
password: YWRtaW4=
|
|
523
|
+
|
|
524
|
+
# SECURE: Use External Secrets Operator with encrypted backend
|
|
525
|
+
# (see Section 3.5 for ESO example)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### 4.6 CWE-209: Generation of Error Message Containing Sensitive Information
|
|
529
|
+
|
|
530
|
+
**Severity:** Medium | **CVSS:** 5.3
|
|
531
|
+
|
|
532
|
+
Stack traces or error responses that expose secrets, connection strings, or internal paths.
|
|
533
|
+
|
|
534
|
+
### 4.7 Secrets in Docker Image Layers
|
|
535
|
+
|
|
536
|
+
```dockerfile
|
|
537
|
+
# VULNERABLE: Secret persists in image layer history even if deleted later
|
|
538
|
+
COPY .env /app/.env
|
|
539
|
+
RUN source /app/.env && ./setup.sh
|
|
540
|
+
RUN rm /app/.env # Still recoverable via `docker history`
|
|
541
|
+
|
|
542
|
+
# ALSO VULNERABLE: Build arg persists in image metadata
|
|
543
|
+
ARG DATABASE_PASSWORD
|
|
544
|
+
ENV DB_PASS=$DATABASE_PASSWORD
|
|
545
|
+
|
|
546
|
+
# SECURE: Use Docker BuildKit secrets (never persisted in layers)
|
|
547
|
+
RUN --mount=type=secret,id=db_pass \
|
|
548
|
+
DB_PASS=$(cat /run/secrets/db_pass) ./setup.sh
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### 4.8 Secrets in URL Parameters
|
|
552
|
+
|
|
553
|
+
```
|
|
554
|
+
# VULNERABLE: Token in URL — logged by proxies, browsers, CDNs, analytics
|
|
555
|
+
https://api.example.com/data?api_key=sk_live_abc123&user=admin
|
|
556
|
+
|
|
557
|
+
# SECURE: Token in Authorization header
|
|
558
|
+
GET /data HTTP/1.1
|
|
559
|
+
Host: api.example.com
|
|
560
|
+
Authorization: Bearer sk_live_abc123
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### 4.9 JWT Secret Weakness
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
// VULNERABLE: Weak, guessable JWT secret
|
|
567
|
+
const token = jwt.sign(payload, "secret");
|
|
568
|
+
const token2 = jwt.sign(payload, "password123");
|
|
569
|
+
|
|
570
|
+
// SECURE: Strong random secret, minimum 256 bits
|
|
571
|
+
import { randomBytes } from "crypto";
|
|
572
|
+
const JWT_SECRET = process.env.JWT_SECRET; // 64+ char random string
|
|
573
|
+
// Generated via: node -e "console.log(require('crypto').randomBytes(64).toString('hex'))"
|
|
574
|
+
const token = jwt.sign(payload, JWT_SECRET, { algorithm: "HS256", expiresIn: "1h" });
|
|
575
|
+
```
|
|
576
|
+
|
|
577
|
+
### 4.10 Shared Service Account Anti-Pattern
|
|
578
|
+
|
|
579
|
+
Using a single set of credentials across multiple services or teams makes it impossible
|
|
580
|
+
to audit who accessed what, prevents scoped rotation, and means one compromise affects
|
|
581
|
+
all consumers. Each service should have its own credential with minimum required permissions.
|
|
582
|
+
|
|
583
|
+
---
|
|
584
|
+
|
|
585
|
+
## 5. Security Checklist
|
|
586
|
+
|
|
587
|
+
Use this checklist for every project, PR review, and security audit.
|
|
588
|
+
|
|
589
|
+
### Prevention (Pre-commit)
|
|
590
|
+
- [ ] Pre-commit secret scanning hook is installed and active (detect-secrets or gitleaks)
|
|
591
|
+
- [ ] `.gitignore` covers `.env`, `*.pem`, `*.key`, credentials files, tfstate
|
|
592
|
+
- [ ] `.env.example` exists with placeholder values (no real secrets)
|
|
593
|
+
- [ ] No secrets in `docker-compose.yml`, `Dockerfile`, or Kubernetes manifests committed to VCS
|
|
594
|
+
- [ ] No API keys or tokens in client-side JavaScript, mobile app bundles, or HTML
|
|
595
|
+
|
|
596
|
+
### Storage
|
|
597
|
+
- [ ] All production secrets stored in a dedicated secret manager (Vault, AWS SM, GCP SM)
|
|
598
|
+
- [ ] Secrets encrypted at rest with AES-256 or equivalent
|
|
599
|
+
- [ ] No secrets in environment variables of container orchestration definitions committed to VCS
|
|
600
|
+
- [ ] Kubernetes Secrets encrypted at rest in etcd
|
|
601
|
+
- [ ] No secrets in Terraform state stored in plaintext (use encrypted S3 backend)
|
|
602
|
+
|
|
603
|
+
### Access Control
|
|
604
|
+
- [ ] Each service has its own credentials (no shared service accounts)
|
|
605
|
+
- [ ] Secret access follows least privilege principle
|
|
606
|
+
- [ ] RBAC configured on secret manager — developers cannot read production secrets
|
|
607
|
+
- [ ] Multi-factor authentication required for secret manager admin access
|
|
608
|
+
- [ ] Break-glass procedure documented for emergency secret access
|
|
609
|
+
|
|
610
|
+
### Rotation
|
|
611
|
+
- [ ] Automated rotation schedule defined (90 days maximum, 30 days for high-privilege)
|
|
612
|
+
- [ ] Rotation tested in staging before production
|
|
613
|
+
- [ ] Rotation does not cause downtime (dual-credential overlap period)
|
|
614
|
+
- [ ] Rotation events logged and alerted
|
|
615
|
+
|
|
616
|
+
### Monitoring & Response
|
|
617
|
+
- [ ] Secret access logs enabled and forwarded to SIEM
|
|
618
|
+
- [ ] Alerts configured for anomalous secret access (unusual time, IP, volume)
|
|
619
|
+
- [ ] CI/CD pipeline includes secret scanning step
|
|
620
|
+
- [ ] Incident response playbook for leaked secrets exists and is tested
|
|
621
|
+
- [ ] GitHub secret scanning and push protection enabled on all repositories
|
|
622
|
+
|
|
623
|
+
### Code Review
|
|
624
|
+
- [ ] PR reviews include explicit check for hardcoded secrets
|
|
625
|
+
- [ ] Logging does not output secrets (redaction filters in place)
|
|
626
|
+
- [ ] Error messages do not include credentials or connection strings
|
|
627
|
+
- [ ] Test fixtures use fake/generated secrets, never production values
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
## 6. Tools & Automation
|
|
632
|
+
|
|
633
|
+
### 6.1 Pre-commit Hooks
|
|
634
|
+
|
|
635
|
+
**detect-secrets (Yelp)**
|
|
636
|
+
```bash
|
|
637
|
+
# Install
|
|
638
|
+
pip install detect-secrets
|
|
639
|
+
|
|
640
|
+
# Generate baseline (marks existing secrets as known)
|
|
641
|
+
detect-secrets scan > .secrets.baseline
|
|
642
|
+
|
|
643
|
+
# Install pre-commit hook
|
|
644
|
+
# In .pre-commit-config.yaml:
|
|
645
|
+
repos:
|
|
646
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
647
|
+
rev: v1.5.0
|
|
648
|
+
hooks:
|
|
649
|
+
- id: detect-secrets
|
|
650
|
+
args: ['--baseline', '.secrets.baseline']
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
**git-secrets (AWS Labs)**
|
|
654
|
+
```bash
|
|
655
|
+
# Install
|
|
656
|
+
brew install git-secrets # macOS
|
|
657
|
+
# or: git clone https://github.com/awslabs/git-secrets && cd git-secrets && make install
|
|
658
|
+
|
|
659
|
+
# Register AWS patterns
|
|
660
|
+
git secrets --register-aws
|
|
661
|
+
|
|
662
|
+
# Install hooks for current repo
|
|
663
|
+
git secrets --install
|
|
664
|
+
|
|
665
|
+
# Add custom patterns
|
|
666
|
+
git secrets --add 'PRIVATE_KEY'
|
|
667
|
+
git secrets --add --allowed 'EXAMPLE_KEY'
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
**Gitleaks**
|
|
671
|
+
```bash
|
|
672
|
+
# Install
|
|
673
|
+
brew install gitleaks # macOS
|
|
674
|
+
|
|
675
|
+
# Scan current repo
|
|
676
|
+
gitleaks detect --source . --verbose
|
|
677
|
+
|
|
678
|
+
# Scan specific commit range
|
|
679
|
+
gitleaks detect --source . --log-opts="HEAD~10..HEAD"
|
|
680
|
+
|
|
681
|
+
# Pre-commit hook (.pre-commit-config.yaml)
|
|
682
|
+
repos:
|
|
683
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
684
|
+
rev: v8.21.2
|
|
685
|
+
hooks:
|
|
686
|
+
- id: gitleaks
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
### 6.2 CI/CD Secret Scanning
|
|
690
|
+
|
|
691
|
+
**TruffleHog**
|
|
692
|
+
```bash
|
|
693
|
+
# Install
|
|
694
|
+
brew install trufflehog # macOS
|
|
695
|
+
|
|
696
|
+
# Scan a repository (includes Git history)
|
|
697
|
+
trufflehog git file://. --only-verified
|
|
698
|
+
|
|
699
|
+
# Scan a GitHub org
|
|
700
|
+
trufflehog github --org=mycompany --only-verified
|
|
701
|
+
|
|
702
|
+
# Scan Docker images
|
|
703
|
+
trufflehog docker --image=myapp:latest
|
|
704
|
+
|
|
705
|
+
# Scan S3 buckets
|
|
706
|
+
trufflehog s3 --bucket=my-bucket
|
|
707
|
+
|
|
708
|
+
# GitHub Action
|
|
709
|
+
# .github/workflows/secrets-scan.yml
|
|
710
|
+
name: Secret Scan
|
|
711
|
+
on: [push, pull_request]
|
|
712
|
+
jobs:
|
|
713
|
+
scan:
|
|
714
|
+
runs-on: ubuntu-latest
|
|
715
|
+
steps:
|
|
716
|
+
- uses: actions/checkout@v4
|
|
717
|
+
with:
|
|
718
|
+
fetch-depth: 0
|
|
719
|
+
- uses: trufflesecurity/trufflehog@main
|
|
720
|
+
with:
|
|
721
|
+
extra_args: --only-verified
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
**GitHub Secret Scanning (Native)**
|
|
725
|
+
- Automatically scans all pushes for known secret patterns
|
|
726
|
+
- Supports 200+ secret types from partner providers
|
|
727
|
+
- Push protection blocks commits containing detected secrets before they reach the repo
|
|
728
|
+
- Available free for public repos; requires GitHub Advanced Security for private repos
|
|
729
|
+
- 75% precision score (true positive rate)
|
|
730
|
+
|
|
731
|
+
**Semgrep Secrets Rules**
|
|
732
|
+
```bash
|
|
733
|
+
# Scan for hardcoded secrets using Semgrep
|
|
734
|
+
semgrep --config "p/secrets" .
|
|
735
|
+
|
|
736
|
+
# Key rules include:
|
|
737
|
+
# - generic.secrets.security.detected-generic-secret
|
|
738
|
+
# - javascript.express.security.hardcoded-secret
|
|
739
|
+
# - python.django.security.hardcoded-secret-key
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
### 6.3 Tool Comparison Matrix
|
|
743
|
+
|
|
744
|
+
| Tool | Pre-commit | CI/CD | Git History | Docker | Verified | Language |
|
|
745
|
+
|-----------------|:----------:|:-----:|:-----------:|:------:|:--------:|------------|
|
|
746
|
+
| detect-secrets | Yes | Yes | No | No | No | Python |
|
|
747
|
+
| git-secrets | Yes | Yes | No | No | No | Bash |
|
|
748
|
+
| Gitleaks | Yes | Yes | Yes | No | No | Go |
|
|
749
|
+
| TruffleHog | Yes | Yes | Yes | Yes | Yes | Go |
|
|
750
|
+
| GitHub Scanning | No (push) | Yes | Yes | No | Yes | Integrated |
|
|
751
|
+
| Semgrep | Yes | Yes | No | No | No | Multi |
|
|
752
|
+
| Talisman | Yes | Yes | Yes | No | No | Go |
|
|
753
|
+
| GitGuardian | Yes | Yes | Yes | Yes | Yes | SaaS |
|
|
754
|
+
|
|
755
|
+
### 6.4 Talisman (ThoughtWorks)
|
|
756
|
+
|
|
757
|
+
```bash
|
|
758
|
+
# Install as pre-push hook
|
|
759
|
+
curl --silent \
|
|
760
|
+
https://raw.githubusercontent.com/thoughtworks/talisman/main/global_install_scripts/install.bash \
|
|
761
|
+
> /tmp/install_talisman.bash && /bin/bash /tmp/install_talisman.bash
|
|
762
|
+
|
|
763
|
+
# Configure exceptions in .talismanrc
|
|
764
|
+
fileignoreconfig:
|
|
765
|
+
- filename: testdata/fake-key.pem
|
|
766
|
+
checksum: abc123def456
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
## 7. Platform-Specific Guidance
|
|
772
|
+
|
|
773
|
+
### 7.1 Web Applications
|
|
774
|
+
|
|
775
|
+
**Server-side secrets:**
|
|
776
|
+
- Load from environment variables or secret manager at startup
|
|
777
|
+
- Never bundle server secrets into client-side JavaScript
|
|
778
|
+
- Use server-side API routes to proxy calls requiring secret keys
|
|
779
|
+
- Framework-specific patterns:
|
|
780
|
+
- Next.js: only `NEXT_PUBLIC_*` vars are client-exposed; all others are server-only
|
|
781
|
+
- Vite: only `VITE_*` vars are embedded in the client bundle
|
|
782
|
+
- Create React App: only `REACT_APP_*` vars are client-exposed
|
|
783
|
+
|
|
784
|
+
**Client-side secrets (there are none):**
|
|
785
|
+
- Any value shipped to the browser is public. Period.
|
|
786
|
+
- Use backend proxies for third-party API calls requiring keys
|
|
787
|
+
- Use restricted/publishable keys for client-side SDKs (e.g., Stripe publishable key)
|
|
788
|
+
- Never embed admin or server-level API keys in frontend code
|
|
789
|
+
|
|
790
|
+
**.env handling for web projects:**
|
|
791
|
+
```
|
|
792
|
+
.env # Shared defaults (NO secrets) — committed
|
|
793
|
+
.env.local # Local overrides with secrets — .gitignore'd
|
|
794
|
+
.env.development # Dev defaults (NO secrets) — committed
|
|
795
|
+
.env.production # Prod defaults (NO secrets) — committed
|
|
796
|
+
.env.*.local # Local overrides — .gitignore'd
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
### 7.2 Mobile Applications
|
|
800
|
+
|
|
801
|
+
**Critical principle:** Mobile apps are distributed binaries that can be decompiled.
|
|
802
|
+
Every string literal, embedded key, or bundled config file is extractable.
|
|
803
|
+
|
|
804
|
+
- Never embed API secrets in the app binary
|
|
805
|
+
- Use platform-specific secure storage:
|
|
806
|
+
- iOS: Keychain Services (`kSecClassGenericPassword`)
|
|
807
|
+
- Android: Android Keystore + EncryptedSharedPreferences
|
|
808
|
+
- Fetch secrets from a secure backend at runtime over TLS
|
|
809
|
+
- Use certificate pinning to prevent MITM attacks on secret retrieval
|
|
810
|
+
- Implement app attestation (Apple App Attest, Google Play Integrity) to verify
|
|
811
|
+
that the requesting client is a legitimate build
|
|
812
|
+
- Obfuscation (ProGuard/R8) slows but does not prevent extraction
|
|
813
|
+
|
|
814
|
+
### 7.3 CI/CD Pipelines
|
|
815
|
+
|
|
816
|
+
**GitHub Actions:**
|
|
817
|
+
- Store secrets in repository or organization settings (Settings > Secrets and variables)
|
|
818
|
+
- Use environment-scoped secrets for production deployments
|
|
819
|
+
- Use OIDC to assume cloud IAM roles instead of storing long-lived access keys:
|
|
820
|
+
```yaml
|
|
821
|
+
permissions:
|
|
822
|
+
id-token: write
|
|
823
|
+
steps:
|
|
824
|
+
- uses: aws-actions/configure-aws-credentials@v4
|
|
825
|
+
with:
|
|
826
|
+
role-to-assume: arn:aws:iam::123456789:role/deploy
|
|
827
|
+
aws-region: us-east-1
|
|
828
|
+
```
|
|
829
|
+
- Review Actions workflow permissions — minimize `GITHUB_TOKEN` scope
|
|
830
|
+
- Never use `${{ secrets.* }}` in `if:` conditions (value is masked but the comparison leaks info)
|
|
831
|
+
|
|
832
|
+
**GitLab CI:**
|
|
833
|
+
- Set variables as "Protected" (only available on protected branches/tags)
|
|
834
|
+
- Set variables as "Masked" (redacted in job logs)
|
|
835
|
+
- Use file-type variables for multi-line secrets (certificates, keys)
|
|
836
|
+
- Scope variables to specific environments
|
|
837
|
+
|
|
838
|
+
**General CI/CD rules:**
|
|
839
|
+
- Audit which workflows and jobs have access to which secrets
|
|
840
|
+
- Rotate secrets after team member departures
|
|
841
|
+
- Use short-lived, scoped tokens over long-lived keys
|
|
842
|
+
- Never store secrets in pipeline definition files committed to the repository
|
|
843
|
+
|
|
844
|
+
### 7.4 Cloud Infrastructure
|
|
845
|
+
|
|
846
|
+
**IAM Roles vs. Access Keys:**
|
|
847
|
+
|
|
848
|
+
| Approach | Security | Rotation | Risk |
|
|
849
|
+
|---------------------|----------|----------|---------------------------------|
|
|
850
|
+
| Long-lived keys | Low | Manual | Key leak = persistent access |
|
|
851
|
+
| Short-lived tokens | Medium | Auto | Token theft window limited |
|
|
852
|
+
| IAM roles (EC2/ECS) | High | Auto | No keys to leak |
|
|
853
|
+
| OIDC federation | High | Auto | No keys to leak, cross-cloud |
|
|
854
|
+
| Workload identity | High | Auto | Native cloud identity, no keys |
|
|
855
|
+
|
|
856
|
+
**AWS best practices:**
|
|
857
|
+
- Use IAM roles for EC2, ECS, Lambda — never embed access keys
|
|
858
|
+
- Use OIDC federation for CI/CD (GitHub Actions, GitLab CI)
|
|
859
|
+
- Enable AWS CloudTrail for API key usage auditing
|
|
860
|
+
- Use Service Control Policies (SCPs) to prevent key creation in production accounts
|
|
861
|
+
- Use AWS Secrets Manager with automated rotation for RDS credentials
|
|
862
|
+
|
|
863
|
+
**GCP best practices:**
|
|
864
|
+
- Use Workload Identity for GKE pods — no service account key files
|
|
865
|
+
- Use Workload Identity Federation for external CI/CD — no key files
|
|
866
|
+
- Restrict service account key creation via Organization Policy
|
|
867
|
+
- Use Secret Manager with IAM conditions (time-based, IP-based access)
|
|
868
|
+
|
|
869
|
+
---
|
|
870
|
+
|
|
871
|
+
## 8. Incident Patterns
|
|
872
|
+
|
|
873
|
+
### 8.1 Leaked Credential Detection
|
|
874
|
+
|
|
875
|
+
Indicators that a secret has been compromised:
|
|
876
|
+
|
|
877
|
+
- Secret scanning tool alert (GitHub, GitGuardian, TruffleHog)
|
|
878
|
+
- Unexpected API usage spikes or requests from unknown IPs
|
|
879
|
+
- Cloud provider notification (AWS emails about exposed keys)
|
|
880
|
+
- Bug bounty report or external researcher disclosure
|
|
881
|
+
- Anomalous authentication patterns in logs
|
|
882
|
+
- Unexpected resource creation in cloud accounts (crypto mining)
|
|
883
|
+
|
|
884
|
+
### 8.2 Incident Response Playbook
|
|
885
|
+
|
|
886
|
+
**Phase 1: Immediate Response (0-15 minutes)**
|
|
887
|
+
1. **Rotate the compromised secret immediately** — do not wait for investigation
|
|
888
|
+
2. Revoke the old credential entirely (do not just create a new one)
|
|
889
|
+
3. Verify that dependent services switch to the new credential
|
|
890
|
+
4. If an access key: disable the key first, then delete after confirming no breakage
|
|
891
|
+
|
|
892
|
+
**Phase 2: Assess Blast Radius (15-60 minutes)**
|
|
893
|
+
1. Determine when the secret was first exposed (git log, file timestamps)
|
|
894
|
+
2. Identify what the secret grants access to (scope, permissions, resources)
|
|
895
|
+
3. Audit access logs for the compromised credential:
|
|
896
|
+
- Cloud provider API logs (CloudTrail, GCP Audit Logs, Azure Activity Log)
|
|
897
|
+
- Application access logs
|
|
898
|
+
- Secret manager audit logs
|
|
899
|
+
4. Check for lateral movement: did the attacker use initial access to obtain more secrets?
|
|
900
|
+
5. Identify all systems, data stores, and services accessible via the compromised credential
|
|
901
|
+
|
|
902
|
+
**Phase 3: Containment & Eradication (1-4 hours)**
|
|
903
|
+
1. Remove the secret from the source where it was leaked (Git history, Docker image, logs)
|
|
904
|
+
2. For Git: use `git filter-repo` or BFG Repo Cleaner to purge from history — then
|
|
905
|
+
force push and notify all contributors to re-clone
|
|
906
|
+
3. For Docker images: rebuild without the secret, re-push, delete compromised tags
|
|
907
|
+
4. Rotate all other secrets that were stored alongside the compromised one
|
|
908
|
+
5. If data access is confirmed: begin data breach notification process
|
|
909
|
+
|
|
910
|
+
**Phase 4: Prevention of Re-occurrence (1-7 days)**
|
|
911
|
+
1. Install pre-commit hooks if not already present
|
|
912
|
+
2. Enable push protection on the repository
|
|
913
|
+
3. Add the secret pattern to CI/CD scanning rules
|
|
914
|
+
4. Review and tighten secret access policies
|
|
915
|
+
5. Conduct a team retrospective on how the leak occurred
|
|
916
|
+
6. Update documentation and runbooks
|
|
917
|
+
|
|
918
|
+
### 8.3 Git History Purging
|
|
919
|
+
|
|
920
|
+
```bash
|
|
921
|
+
# Option 1: BFG Repo Cleaner (recommended — faster, simpler)
|
|
922
|
+
# Install: brew install bfg
|
|
923
|
+
bfg --replace-text passwords.txt repo.git
|
|
924
|
+
cd repo.git
|
|
925
|
+
git reflog expire --expire=now --all
|
|
926
|
+
git gc --prune=now --aggressive
|
|
927
|
+
|
|
928
|
+
# Option 2: git filter-repo (more flexible)
|
|
929
|
+
# Install: pip install git-filter-repo
|
|
930
|
+
git filter-repo --invert-paths --path secrets.env
|
|
931
|
+
git filter-repo --blob-callback '
|
|
932
|
+
if b"sk_live_" in blob.data:
|
|
933
|
+
blob.data = blob.data.replace(b"sk_live_XXXX", b"REDACTED")
|
|
934
|
+
'
|
|
935
|
+
```
|
|
936
|
+
|
|
937
|
+
**After purging history:**
|
|
938
|
+
- Force push all branches and tags
|
|
939
|
+
- Notify all contributors to delete their local clones and re-clone
|
|
940
|
+
- Invalidate GitHub/GitLab caches
|
|
941
|
+
- The secret must still be rotated — purging history does not un-expose a secret
|
|
942
|
+
|
|
943
|
+
---
|
|
944
|
+
|
|
945
|
+
## 9. Compliance & Standards
|
|
946
|
+
|
|
947
|
+
### 9.1 OWASP
|
|
948
|
+
|
|
949
|
+
**Secrets Management Cheat Sheet** — Covers the full lifecycle:
|
|
950
|
+
- Secret generation with cryptographic strength
|
|
951
|
+
- Centralized storage with access controls
|
|
952
|
+
- Secret transmission via secure channels
|
|
953
|
+
- Metadata tracking (who created, rotated, consumed, deleted)
|
|
954
|
+
- Preference for passwordless authentication (OIDC) where possible
|
|
955
|
+
|
|
956
|
+
**OWASP Top 10 (2021):**
|
|
957
|
+
- **A02: Cryptographic Failures** — Includes exposure of secrets, weak key management
|
|
958
|
+
- **A07: Identification & Authentication Failures** — Includes hardcoded credentials
|
|
959
|
+
|
|
960
|
+
**OWASP SAMM (Software Assurance Maturity Model):**
|
|
961
|
+
- Implementation > Secure Deployment > Stream B: Secret Management
|
|
962
|
+
- Maturity levels from ad-hoc to automated secret lifecycle management
|
|
963
|
+
|
|
964
|
+
### 9.2 NIST
|
|
965
|
+
|
|
966
|
+
**NIST SP 800-57: Recommendation for Key Management**
|
|
967
|
+
- Key lifecycle: generation, registration, storage, distribution, use, rotation, destruction
|
|
968
|
+
- Minimum key lengths: AES-128 for symmetric, RSA-2048/EC-P256 for asymmetric
|
|
969
|
+
- Crypto periods: maximum time a key should remain active before rotation
|
|
970
|
+
- Key separation: different keys for different purposes (encryption, signing, authentication)
|
|
971
|
+
|
|
972
|
+
**NIST SP 800-53 (Rev. 5): Security and Privacy Controls**
|
|
973
|
+
- IA-5: Authenticator Management — proper handling of passwords, keys, tokens
|
|
974
|
+
- SC-12: Cryptographic Key Establishment and Management
|
|
975
|
+
- SC-28: Protection of Information at Rest — secrets encrypted at rest
|
|
976
|
+
|
|
977
|
+
### 9.3 SOC 2
|
|
978
|
+
|
|
979
|
+
SOC 2 Type II — Trust Services Criteria relevant to secrets:
|
|
980
|
+
|
|
981
|
+
- **CC6.1**: Logical access security — restrict access to secrets based on role
|
|
982
|
+
- **CC6.6**: Restrict external access — secrets not exposed to unauthorized parties
|
|
983
|
+
- **CC6.7**: Restrict data movement — secrets not transmitted insecurely
|
|
984
|
+
- **CC7.1**: Detect and respond to security events — monitoring for secret misuse
|
|
985
|
+
- **CC8.1**: Change management — secrets rotation is a controlled change
|
|
986
|
+
|
|
987
|
+
Key requirements:
|
|
988
|
+
- Encryption of secrets at rest and in transit
|
|
989
|
+
- Access logging for all secret operations
|
|
990
|
+
- Regular access reviews for secret management systems
|
|
991
|
+
- Documented secret rotation procedures
|
|
992
|
+
|
|
993
|
+
### 9.4 PCI-DSS v4.0.1
|
|
994
|
+
|
|
995
|
+
Requirements relevant to secrets and key management:
|
|
996
|
+
|
|
997
|
+
- **Req 3.6**: Cryptographic keys used to protect stored account data are secured
|
|
998
|
+
- **Req 3.7**: Cryptographic keys used to protect stored account data are managed
|
|
999
|
+
- 3.7.1: Key management policies and procedures
|
|
1000
|
+
- 3.7.2: Secure key distribution
|
|
1001
|
+
- 3.7.4: Key changes for keys past their cryptoperiod
|
|
1002
|
+
- 3.7.5: Retirement/replacement of keys when integrity is weakened
|
|
1003
|
+
- 3.7.6: Split knowledge and dual control for manual key operations
|
|
1004
|
+
- **Req 8.3**: Strong authentication for users and administrators
|
|
1005
|
+
- 8.3.6: Minimum password complexity (12 characters for application/system accounts)
|
|
1006
|
+
- **Req 8.6**: Application and system account credentials managed securely
|
|
1007
|
+
- 8.6.1: Interactive logins by system accounts are managed on an exception basis
|
|
1008
|
+
- 8.6.3: Passwords for application/system accounts changed periodically and on suspicion of compromise
|
|
1009
|
+
- Hashes must be keyed (HMAC) — plain hashing of credentials is insufficient
|
|
1010
|
+
|
|
1011
|
+
---
|
|
1012
|
+
|
|
1013
|
+
## 10. Code Examples — Vulnerable vs. Secure Pairs
|
|
1014
|
+
|
|
1015
|
+
### 10.1 Configuration Loading
|
|
1016
|
+
|
|
1017
|
+
```typescript
|
|
1018
|
+
// ---- VULNERABLE ----
|
|
1019
|
+
// Hardcoded credentials in source code
|
|
1020
|
+
const config = {
|
|
1021
|
+
db: {
|
|
1022
|
+
host: "prod-db.example.com",
|
|
1023
|
+
user: "admin",
|
|
1024
|
+
password: "P@ssw0rd!2024",
|
|
1025
|
+
},
|
|
1026
|
+
stripe: {
|
|
1027
|
+
secretKey: "REDACTED_STRIPE_KEY",
|
|
1028
|
+
},
|
|
1029
|
+
jwt: {
|
|
1030
|
+
secret: "my-jwt-secret",
|
|
1031
|
+
},
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
// ---- SECURE ----
|
|
1035
|
+
// Configuration loaded from environment with validation
|
|
1036
|
+
import { z } from "zod";
|
|
1037
|
+
|
|
1038
|
+
const ConfigSchema = z.object({
|
|
1039
|
+
DATABASE_URL: z.string().url(),
|
|
1040
|
+
STRIPE_SECRET_KEY: z.string().startsWith("sk_"),
|
|
1041
|
+
JWT_SECRET: z.string().min(64, "JWT secret must be at least 64 characters"),
|
|
1042
|
+
NODE_ENV: z.enum(["development", "staging", "production"]),
|
|
1043
|
+
});
|
|
1044
|
+
|
|
1045
|
+
function loadConfig() {
|
|
1046
|
+
const result = ConfigSchema.safeParse(process.env);
|
|
1047
|
+
if (!result.success) {
|
|
1048
|
+
// Log WHICH vars are missing, never their VALUES
|
|
1049
|
+
const missing = result.error.issues.map((i) => i.path.join("."));
|
|
1050
|
+
throw new Error(`Invalid configuration. Missing/invalid: ${missing.join(", ")}`);
|
|
1051
|
+
}
|
|
1052
|
+
return result.data;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
export const config = loadConfig();
|
|
1056
|
+
```
|
|
1057
|
+
|
|
1058
|
+
### 10.2 Pre-commit Hook Setup — Complete
|
|
1059
|
+
|
|
1060
|
+
```bash
|
|
1061
|
+
#!/usr/bin/env bash
|
|
1062
|
+
# setup-secret-scanning.sh — Installs pre-commit hooks for secret detection
|
|
1063
|
+
|
|
1064
|
+
set -euo pipefail
|
|
1065
|
+
|
|
1066
|
+
echo "Installing pre-commit framework..."
|
|
1067
|
+
pip install pre-commit
|
|
1068
|
+
|
|
1069
|
+
echo "Installing gitleaks..."
|
|
1070
|
+
brew install gitleaks 2>/dev/null || go install github.com/gitleaks/gitleaks/v8@latest
|
|
1071
|
+
|
|
1072
|
+
# Create .pre-commit-config.yaml if it doesn't exist
|
|
1073
|
+
cat > .pre-commit-config.yaml << 'YAML'
|
|
1074
|
+
repos:
|
|
1075
|
+
# Gitleaks — fast regex and entropy-based detection
|
|
1076
|
+
- repo: https://github.com/gitleaks/gitleaks
|
|
1077
|
+
rev: v8.21.2
|
|
1078
|
+
hooks:
|
|
1079
|
+
- id: gitleaks
|
|
1080
|
+
|
|
1081
|
+
# detect-secrets — baseline-aware, lower false positives
|
|
1082
|
+
- repo: https://github.com/Yelp/detect-secrets
|
|
1083
|
+
rev: v1.5.0
|
|
1084
|
+
hooks:
|
|
1085
|
+
- id: detect-secrets
|
|
1086
|
+
args: ['--baseline', '.secrets.baseline']
|
|
1087
|
+
|
|
1088
|
+
# Check for large files that might contain secrets
|
|
1089
|
+
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
1090
|
+
rev: v5.0.0
|
|
1091
|
+
hooks:
|
|
1092
|
+
- id: check-added-large-files
|
|
1093
|
+
args: ['--maxkb=500']
|
|
1094
|
+
- id: detect-private-key
|
|
1095
|
+
YAML
|
|
1096
|
+
|
|
1097
|
+
# Generate detect-secrets baseline
|
|
1098
|
+
echo "Generating detect-secrets baseline..."
|
|
1099
|
+
detect-secrets scan > .secrets.baseline
|
|
1100
|
+
|
|
1101
|
+
# Install the hooks
|
|
1102
|
+
echo "Installing pre-commit hooks..."
|
|
1103
|
+
pre-commit install
|
|
1104
|
+
|
|
1105
|
+
echo "Running initial scan..."
|
|
1106
|
+
pre-commit run --all-files || true
|
|
1107
|
+
|
|
1108
|
+
echo "Secret scanning hooks installed successfully."
|
|
1109
|
+
echo "Commits will now be checked for secrets automatically."
|
|
1110
|
+
```
|
|
1111
|
+
|
|
1112
|
+
### 10.3 Logging with Secret Redaction
|
|
1113
|
+
|
|
1114
|
+
```typescript
|
|
1115
|
+
// ---- VULNERABLE ----
|
|
1116
|
+
app.use((req, res, next) => {
|
|
1117
|
+
// Logs full headers including Authorization tokens
|
|
1118
|
+
console.log(`${req.method} ${req.url}`, req.headers);
|
|
1119
|
+
next();
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1122
|
+
// ---- SECURE ----
|
|
1123
|
+
const SENSITIVE_HEADERS = new Set([
|
|
1124
|
+
"authorization",
|
|
1125
|
+
"cookie",
|
|
1126
|
+
"x-api-key",
|
|
1127
|
+
"proxy-authorization",
|
|
1128
|
+
]);
|
|
1129
|
+
|
|
1130
|
+
const SENSITIVE_PATTERNS = [
|
|
1131
|
+
/(?:password|secret|token|key|credential)=([^&\s]+)/gi,
|
|
1132
|
+
/Bearer\s+[A-Za-z0-9\-._~+\/]+=*/g,
|
|
1133
|
+
/sk_live_[A-Za-z0-9]+/g,
|
|
1134
|
+
/AKIA[0-9A-Z]{16}/g, // AWS Access Key ID
|
|
1135
|
+
];
|
|
1136
|
+
|
|
1137
|
+
function redactSensitive(value: string): string {
|
|
1138
|
+
let redacted = value;
|
|
1139
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
1140
|
+
redacted = redacted.replace(pattern, "[REDACTED]");
|
|
1141
|
+
}
|
|
1142
|
+
return redacted;
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
function safeHeaders(headers: Record<string, string>): Record<string, string> {
|
|
1146
|
+
const safe: Record<string, string> = {};
|
|
1147
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1148
|
+
safe[key] = SENSITIVE_HEADERS.has(key.toLowerCase())
|
|
1149
|
+
? "[REDACTED]"
|
|
1150
|
+
: redactSensitive(value);
|
|
1151
|
+
}
|
|
1152
|
+
return safe;
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
app.use((req, res, next) => {
|
|
1156
|
+
console.log(`${req.method} ${redactSensitive(req.url)}`, safeHeaders(req.headers));
|
|
1157
|
+
next();
|
|
1158
|
+
});
|
|
1159
|
+
```
|
|
1160
|
+
|
|
1161
|
+
### 10.4 Docker Secrets — BuildKit Pattern
|
|
1162
|
+
|
|
1163
|
+
```dockerfile
|
|
1164
|
+
# ---- VULNERABLE Dockerfile ----
|
|
1165
|
+
FROM node:20-alpine
|
|
1166
|
+
COPY .env /app/.env
|
|
1167
|
+
# Secret is now baked into image layer forever
|
|
1168
|
+
RUN source /app/.env && npm run build
|
|
1169
|
+
RUN rm /app/.env # Useless: layer still contains .env
|
|
1170
|
+
|
|
1171
|
+
# ---- SECURE Dockerfile ----
|
|
1172
|
+
# syntax=docker/dockerfile:1
|
|
1173
|
+
FROM node:20-alpine AS builder
|
|
1174
|
+
WORKDIR /app
|
|
1175
|
+
COPY package*.json ./
|
|
1176
|
+
RUN npm ci --ignore-scripts
|
|
1177
|
+
COPY . .
|
|
1178
|
+
# Secret is mounted at build time, never persisted in any layer
|
|
1179
|
+
RUN --mount=type=secret,id=env_file \
|
|
1180
|
+
cp /run/secrets/env_file .env && \
|
|
1181
|
+
npm run build && \
|
|
1182
|
+
rm .env
|
|
1183
|
+
|
|
1184
|
+
FROM node:20-alpine
|
|
1185
|
+
WORKDIR /app
|
|
1186
|
+
COPY --from=builder /app/dist ./dist
|
|
1187
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
1188
|
+
# Runtime secrets injected via orchestrator (Docker Swarm / Kubernetes)
|
|
1189
|
+
CMD ["node", "dist/server.js"]
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
Build command:
|
|
1193
|
+
```bash
|
|
1194
|
+
DOCKER_BUILDKIT=1 docker build --secret id=env_file,src=.env -t myapp:latest .
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
---
|
|
1198
|
+
|
|
1199
|
+
## References
|
|
1200
|
+
|
|
1201
|
+
- [GitHub: 39M Secret Leaks in 2024](https://github.blog/security/application-security/next-evolution-github-advanced-security/)
|
|
1202
|
+
- [GitGuardian State of Secrets Sprawl 2025](https://www.gitguardian.com/state-of-secrets-sprawl-report-2025)
|
|
1203
|
+
- [OWASP Secrets Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Secrets_Management_Cheat_Sheet.html)
|
|
1204
|
+
- [HashiCorp 18-Point Secrets Management Checklist](https://www.hashicorp.com/en/blog/the-18-point-secrets-management-checklist)
|
|
1205
|
+
- [CWE-798: Use of Hard-coded Credentials](https://cwe.mitre.org/data/definitions/798.html)
|
|
1206
|
+
- [Palo Alto Unit 42: Large-Scale .env Extortion](https://unit42.paloaltonetworks.com/large-scale-cloud-extortion-operation/)
|
|
1207
|
+
- [Toyota GitHub Key Exposure](https://blog.gitguardian.com/toyota-accidently-exposed-a-secret-key-publicly-on-github-for-five-years/)
|
|
1208
|
+
- [CircleCI January 2023 Incident Report](https://circleci.com/blog/jan-4-2023-incident-report/)
|
|
1209
|
+
- [Uber 2016 Breach Timeline](https://www.techtarget.com/searchsecurity/news/252488361/The-Uber-data-breach-cover-up-A-timeline-of-events)
|
|
1210
|
+
- [Samsung Lapsus$ Breach Analysis](https://www.gitguardian.com/videos/analyzing-the-samsung-hack-thousands-of-credentials-secrets-exposed)
|
|
1211
|
+
- [AWS .env Credential Theft](https://www.csoonline.com/article/3488207/aws-environments-compromised-through-exposed-env-files.html)
|
|
1212
|
+
- [Kubernetes Secrets Good Practices](https://kubernetes.io/docs/concepts/security/secrets-good-practices/)
|
|
1213
|
+
- [External Secrets Operator Security](https://external-secrets.io/latest/guides/security-best-practices/)
|
|
1214
|
+
- [NIST SP 800-57: Key Management](https://csrc.nist.gov/publications/detail/sp/800-57-part-1/rev-5/final)
|
|
1215
|
+
- [TruffleHog](https://github.com/trufflesecurity/trufflehog)
|
|
1216
|
+
- [Gitleaks](https://github.com/gitleaks/gitleaks)
|
|
1217
|
+
- [detect-secrets](https://github.com/Yelp/detect-secrets)
|