ansede-static 2.3.0.dev0__tar.gz → 2.3.1__tar.gz

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.
Files changed (219) hide show
  1. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/CHANGELOG.md +49 -0
  2. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/PKG-INFO +55 -64
  3. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/README.md +54 -63
  4. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/pyproject.toml +1 -1
  5. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/__init__.py +63 -5
  6. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cli.py +159 -14
  7. ansede_static-2.3.1/src/ansede_static/engine/audit.py +967 -0
  8. ansede_static-2.3.1/src/ansede_static/engine/llm_triage.py +461 -0
  9. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine_version.py +6 -3
  10. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/ir/global_graph.py +56 -2
  11. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_analyzer.py +9 -2
  12. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_ast_analyzer.py +96 -7
  13. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/common.py +5 -0
  14. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/project.py +30 -3
  15. ansede_static-2.3.1/src/ansede_static/js_engine/project_context.py +297 -0
  16. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/routes.py +44 -17
  17. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/structure.py +17 -4
  18. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/taint_checks.py +13 -0
  19. ansede_static-2.3.1/src/ansede_static/profiler.py +98 -0
  20. ansede_static-2.3.1/tests/test_audit_engine.py +284 -0
  21. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_community_rules.py +20 -0
  22. ansede_static-2.3.1/tests/test_js_minified_project_index.py +53 -0
  23. ansede_static-2.3.1/tests/test_js_pratt_parser.py +41 -0
  24. ansede_static-2.3.1/tests/test_js_structure_cache.py +28 -0
  25. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_quality_benchmark.py +2 -2
  26. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/.gitignore +0 -0
  27. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/LICENSE +0 -0
  28. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/_types.py +0 -0
  29. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cache/__init__.py +0 -0
  30. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cache/incremental.py +0 -0
  31. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cache/sqlite_store.py +0 -0
  32. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/config.py +0 -0
  33. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cpg/__init__.py +0 -0
  34. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cpg/builder.py +0 -0
  35. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cpg/graph.py +0 -0
  36. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/cpg/taint_engine.py +0 -0
  37. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/csharp_analyzer.py +0 -0
  38. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/__init__.py +0 -0
  39. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/async_scanner.py +0 -0
  40. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/ci_baseline.py +0 -0
  41. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/clustering.py +0 -0
  42. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/confidence.py +0 -0
  43. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/cvss.py +0 -0
  44. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/dump_failures.py +0 -0
  45. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/explain.py +0 -0
  46. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/learning_triage.py +0 -0
  47. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/nuclei.py +0 -0
  48. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/remediation.py +0 -0
  49. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/semgrep_.py +0 -0
  50. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/shadow_scan.py +0 -0
  51. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/symbolic_guards.py +0 -0
  52. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/engine/triage.py +0 -0
  53. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/entropy.py +0 -0
  54. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/go_engine/__init__.py +0 -0
  55. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/go_engine/go_analyzer.py +0 -0
  56. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/go_engine/go_parser.py +0 -0
  57. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/hardening.py +0 -0
  58. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/ir/__init__.py +0 -0
  59. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/ir/issues.py +0 -0
  60. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/ir/stir.py +0 -0
  61. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/java_analyzer.py +0 -0
  62. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/__init__.py +0 -0
  63. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/backends.py +0 -0
  64. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/constants.py +0 -0
  65. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/context_checks.py +0 -0
  66. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/minified_scanner.py +0 -0
  67. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/module_resolver.py +0 -0
  68. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/pattern_rules.py +0 -0
  69. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/pratt/__init__.py +0 -0
  70. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/pratt/ast_nodes.py +0 -0
  71. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/pratt/lexer.py +0 -0
  72. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/pratt/parser.py +0 -0
  73. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/pratt_analyzer.py +0 -0
  74. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/react.py +0 -0
  75. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/source_map_resolver.py +0 -0
  76. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/sourcemap_rescanner.py +0 -0
  77. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/js_engine/taint.py +0 -0
  78. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/licensing.py +0 -0
  79. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/lsp_server.py +0 -0
  80. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/monorepo.py +0 -0
  81. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/php_analyzer.py +0 -0
  82. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/pypi_validator.py +0 -0
  83. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/python_analyzer.py +0 -0
  84. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/__init__.py +0 -0
  85. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/aiohttp_web.yaml +0 -0
  86. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/angular_js.yaml +0 -0
  87. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/api_security.yaml +0 -0
  88. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/archive_extraction_py.yaml +0 -0
  89. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/aspnet_core.yaml +0 -0
  90. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/axios_js.yaml +0 -0
  91. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/boto3_aws.yaml +0 -0
  92. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/celery.yaml +0 -0
  93. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/cloud_security.yaml +0 -0
  94. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/community.py +0 -0
  95. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/cryptography_lib.yaml +0 -0
  96. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/deserialization_py.yaml +0 -0
  97. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/django.yaml +0 -0
  98. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/django_rest.yaml +0 -0
  99. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/express_js.yaml +0 -0
  100. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/fastapi.yaml +0 -0
  101. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/flask.yaml +0 -0
  102. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/graphql_js.yaml +0 -0
  103. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/graphql_py.yaml +0 -0
  104. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/jwt_js.yaml +0 -0
  105. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/jwt_py.yaml +0 -0
  106. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/knex_js.yaml +0 -0
  107. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/ldap_js.yaml +0 -0
  108. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/ldap_py.yaml +0 -0
  109. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/loader.py +0 -0
  110. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/mongoose_js.yaml +0 -0
  111. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/mysql2_js.yaml +0 -0
  112. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/nestjs_framework.yaml +0 -0
  113. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/nextjs_framework.yaml +0 -0
  114. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/nodejs_core.yaml +0 -0
  115. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/pg_js.yaml +0 -0
  116. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/prisma_orm.yaml +0 -0
  117. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/prototype_pollution_js.yaml +0 -0
  118. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/pug_js.yaml +0 -0
  119. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/pydantic.yaml +0 -0
  120. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/pymongo.yaml +0 -0
  121. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/race_condition_py.yaml +0 -0
  122. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/react_frontend.yaml +0 -0
  123. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/redis_py.yaml +0 -0
  124. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/requests_lib.yaml +0 -0
  125. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/second_order_sql.yaml +0 -0
  126. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/sequelize_orm.yaml +0 -0
  127. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/sharded_loader.py +0 -0
  128. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/socketio.yaml +0 -0
  129. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/spring_boot.yaml +0 -0
  130. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/sqlalchemy.yaml +0 -0
  131. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/subprocess_lib.yaml +0 -0
  132. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/supply_chain.yaml +0 -0
  133. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/template_engines_py.yaml +0 -0
  134. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/tornado_web.yaml +0 -0
  135. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/typeorm_js.yaml +0 -0
  136. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/vue_js.yaml +0 -0
  137. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/xml_parsers.yaml +0 -0
  138. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry/yaml_load.yaml +0 -0
  139. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/registry.py +0 -0
  140. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/reporters.py +0 -0
  141. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/ruby_analyzer.py +0 -0
  142. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/rules.py +0 -0
  143. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/rulesets/__init__.py +0 -0
  144. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/rulesets/datascience.py +0 -0
  145. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/sanitizers.json +0 -0
  146. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/sarif_validator.py +0 -0
  147. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/sbom.py +0 -0
  148. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/schema.py +0 -0
  149. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/schemas/__init__.py +0 -0
  150. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/schemas/ansede.schema.json +0 -0
  151. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/taint_specs.json +0 -0
  152. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/template_transpiler.py +0 -0
  153. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/__init__.py +0 -0
  154. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/baseline.py +0 -0
  155. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/call_graph.py +0 -0
  156. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/engine.py +0 -0
  157. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/ifds.py +0 -0
  158. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/interprocedural_taint.py +0 -0
  159. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/model.py +0 -0
  160. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/nodes.py +0 -0
  161. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/normalizer.py +0 -0
  162. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rule_protocol.py +0 -0
  163. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/__init__.py +0 -0
  164. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/javascript/__init__.py +0 -0
  165. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/javascript/crypto.py +0 -0
  166. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/javascript/framework.py +0 -0
  167. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/javascript/injection.py +0 -0
  168. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/javascript/xss.py +0 -0
  169. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/__init__.py +0 -0
  170. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/auth.py +0 -0
  171. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/crypto.py +0 -0
  172. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/deserialization.py +0 -0
  173. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/framework.py +0 -0
  174. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/injection.py +0 -0
  175. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/logging_.py +0 -0
  176. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/path_traversal.py +0 -0
  177. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/secrets.py +0 -0
  178. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/python/ssrf.py +0 -0
  179. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/shared/__init__.py +0 -0
  180. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/rules/shared/sql_injection.py +0 -0
  181. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/suppression.py +0 -0
  182. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/v2/taint.py +0 -0
  183. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/src/ansede_static/yaml_rules.py +0 -0
  184. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/__init__.py +0 -0
  185. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/conftest.py +0 -0
  186. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_async_scanner.py +0 -0
  187. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_cache.py +0 -0
  188. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_cli.py +0 -0
  189. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_confidence.py +0 -0
  190. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_config.py +0 -0
  191. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_corpus_offline.py +0 -0
  192. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_cpg.py +0 -0
  193. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_cvss.py +0 -0
  194. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_datascience.py +0 -0
  195. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_entropy.py +0 -0
  196. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_explain.py +0 -0
  197. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_external_corpus.py +0 -0
  198. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_ifds.py +0 -0
  199. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_ifds_e2e_integration.py +0 -0
  200. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_ifds_ide_lattice.py +0 -0
  201. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_ifds_realistic_scenarios.py +0 -0
  202. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_incremental.py +0 -0
  203. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_interprocedural_taint.py +0 -0
  204. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_java_csharp_analyzers.py +0 -0
  205. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_js.py +0 -0
  206. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_js_ast.py +0 -0
  207. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_lsp_server.py +0 -0
  208. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_noise_policies.py +0 -0
  209. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_phase2_registry_expansion.py +0 -0
  210. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_phase4_diagnostics.py +0 -0
  211. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_python.py +0 -0
  212. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_real_world_compare.py +0 -0
  213. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_remediation.py +0 -0
  214. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_reporters.py +0 -0
  215. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_rules.py +0 -0
  216. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_symbolic_guards.py +0 -0
  217. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_triage.py +0 -0
  218. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_web_wild_harness.py +0 -0
  219. {ansede_static-2.3.0.dev0 → ansede_static-2.3.1}/tests/test_yaml_rules.py +0 -0
@@ -3,6 +3,55 @@
3
3
  All notable changes to ansede-static are documented here.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/).
5
5
 
6
+ ## [2.3.1] — 2026-05-26
7
+
8
+ ### Changed — Honest Metrics & Documentation Overhaul
9
+
10
+ - **Replaced all benchmarks with honest real-world data.** Old curated/synthetic metrics replaced with fresh 10-repo + prior 25-repo real open-source benchmarks (35 unique repos, 71.25 MB, 5 languages, 4,649 findings).
11
+ - **Updated README.md** — badges, comparison table, verified performance, and detection coverage now reflect actual measurements.
12
+ - **Updated BENCHMARKS.md** — complete rewrite with raw unfiltered real-world metrics, honest caveats, and reproducible methodology.
13
+ - **Updated final_scorecard.json** — now reflects real-world scan data instead of curated metrics.
14
+ - **Updated CHANGELOG.md** — this entry.
15
+ - **Version bumped to 2.3.1** for PyPI release.
16
+
17
+ ### Performance — Second Speed Pass
18
+
19
+ - **63.6% faster overall** (226.4s → 82.5s on 25-repo benchmark).
20
+ - JS project index reuse: structural analyzer passes its `project` to the classic fallback instead of rebuilding.
21
+ - Route-block `@lru_cache`: 6 cached functions in `routes.py` prevent 11 checkers from recomputing the same route data.
22
+ - `GlobalGraph._normalize_path()` memoized with `@lru_cache(maxsize=32768)`.
23
+ - `GlobalGraph.load_summary()` remembers absent keys to skip redundant SQLite queries.
24
+ - All metrics (findings, clustering, noise quotient) unchanged — verified by before/after benchmark comparison.
25
+
26
+ ## [2.3.0] — 2026-05-22
27
+
28
+ ### Added — LLM-Assisted Triage Engine
29
+ - **`--llm` flag** — local Ollama integration (gemma3:4b) for classifying remaining NEEDS_REVIEW findings. Zero cloud dependency.
30
+ - **Persistent Few-Shot Memory** (`~/.ansede/llm_memory.json`) — 354 curated examples across 26 CWE/agent groups. Automatically trains on high-confidence LLM verdicts.
31
+ - **`--audit` pipeline boost** — heuristic + LLM combo now achieves ~96% auto-classification across 6 scanned production repos (5,575 files, 7 languages).
32
+
33
+ ### Added — Training Pipeline
34
+ - **Batch scanning framework** — `scan_repos.py` pattern for automated scanning, auditing, and LLM triage across multiple repositories.
35
+ - **Confidence-gated memory** — only stores entries with confidence >= 0.75 with dedup and smart eviction (keeps highest-quality per group).
36
+ - **Cross-language coverage** — memory entries span Ruby, JavaScript, TypeScript, Go, PHP, and Python analyzers.
37
+
38
+ ### Performance
39
+ - Heuristic classification: ~72-94% (language-dependent)
40
+ - LLM + Heuristic combo: **~93-100%** across all scanned repos
41
+ - pocketbase (Go/JS): 93%
42
+ - docuseal (Ruby/JS): 97%
43
+ - monica (PHP): 93%
44
+ - gogs (Go): ✅
45
+ - hoppscotch (JS/TS): 97%
46
+ - hedgedoc (JS/TS): 100%
47
+ - fastapi (Python): 100%
48
+ - LLM triage throughput: ~2 sec/finding on RTX 5070 (12GB)
49
+
50
+ ### Fixed
51
+ - `check_ollama_available()` — updated for ollama Python library v0.6.2 API (ListResponse.models, Model.model)
52
+ - Reduced confidence thresholds for gemma3:4b compatibility (memory gate: 0.75, triage gate: 0.70)
53
+ - `--audit` flag now properly recognized via `python -m ansede_static.cli`
54
+
6
55
  ## [2.2.1] — 2026-05-18
7
56
 
8
57
  ### Added — Master Engineering Directive: World-Best Finalization
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ansede-static
3
- Version: 2.3.0.dev0
3
+ Version: 2.3.1
4
4
  Summary: AST-based SAST for Python and JavaScript — detects IDOR, auth bypass, and ownership flaws that Bandit misses.
5
5
  Project-URL: Homepage, https://github.com/mattybellx/Ansede
6
6
  Project-URL: Repository, https://github.com/mattybellx/Ansede
@@ -55,8 +55,8 @@ Description-Content-Type: text/markdown
55
55
  </p>
56
56
 
57
57
  <p align="center">
58
- <strong>The world's most precise offline static application security testing engine.</strong><br>
59
- Zero dependencies. 98.8% CVE recall. Five languages. Ships as a single <code>.exe</code>.
58
+ <strong>Offline static application security testing engine.</strong><br>
59
+ Zero dependencies. Real-world validated. 5 languages. LLM-assisted triage. Ships as a single <code>.exe</code>.
60
60
  </p>
61
61
 
62
62
  <p align="center">
@@ -64,8 +64,9 @@ Description-Content-Type: text/markdown
64
64
  <a href="https://pypi.org/project/ansede-static/"><img src="https://img.shields.io/pypi/v/ansede-static?label=pypi&color=0078D4" alt="PyPI"></a>
65
65
  <a href="https://pypi.org/project/ansede-static/"><img src="https://img.shields.io/pypi/dm/ansede-static?label=downloads&color=107C10" alt="Downloads"></a>
66
66
  <a href="https://github.com/mattybellx/Ansede/actions/workflows/ci.yml"><img src="https://github.com/mattybellx/Ansede/actions/workflows/ci.yml/badge.svg?branch=master" alt="CI"></a>
67
- <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/CVE%20Recall-98.8%25-brightgreen" alt="CVE Recall 98.8%"></a>
68
- <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/FP%20Rate-3.6%25-brightgreen" alt="FP Rate 3.6%"></a>
67
+ <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/Real%20Repos%20Scanned-35-blue" alt="35 real repos scanned"></a>
68
+ <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/CWE%20Types-33%2B-yellow" alt="33+ CWE types"></a>
69
+ <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/LLM%20Triage-96%25%20auto-yellowgreen" alt="LLM Auto 96%"></a>
69
70
  <a href="https://github.com/mattybellx/Ansede/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-yellow.svg" alt="License MIT"></a>
70
71
  <a href="https://github.com/mattybellx/Ansede/stargazers"><img src="https://img.shields.io/github/stars/mattybellx/Ansede?style=social" alt="Stars"></a>
71
72
  </p>
@@ -150,7 +151,7 @@ def delete_post(post_id):
150
151
  # no if post.author_id != current_user.id: abort(403)
151
152
  ```
152
153
 
153
- **ansede-static models routes, decorators, auth guards, and ownership patterns at the AST level.** This is how it achieves 98.8% CVE recall while Bandit OSS sits at ~65%.
154
+ **ansede-static models routes, decorators, auth guards, and ownership patterns at the AST level.** This is how it catches access-control vulnerabilities that regex-only tools miss.
154
155
 
155
156
  ---
156
157
 
@@ -184,71 +185,59 @@ ansede-static src/ --incremental
184
185
 
185
186
  ## Verified Performance — May 2026
186
187
 
187
- | Benchmark | Result |
188
- |---|---|
189
- | Regression suite | **919 tests passed** |
190
- | NVD CVE recall | **81/82 (98.78%)** |
191
- | NVD CVE precision | **96.43%** |
192
- | False positive rate | **3.57%** |
193
- | Web-wild recall | **100.00%** |
194
- | Web-wild precision | **95.00%** |
195
- | External real-world corpus | **15/15 cases, 30/30 checks (100%)** |
196
- | Noise quotient | **0.861 findings / kLOC** |
197
- | Raw engine speed | **~0.02s per 100k LOC** |
198
- | Languages | Python · JavaScript · TypeScript · Go · Java · C# |
199
- | World-Best Audit | ✅ All quality gates passed |
188
+ For the full methodology and raw data, see [`BENCHMARKS.md`](BENCHMARKS.md).
200
189
 
201
- Full methodology and machine-readable artifacts: [`BENCHMARKS.md`](BENCHMARKS.md)
190
+ ### Real-World Validation 35 Repos Scanned
202
191
 
203
- ### 🌍 Real-World Validation 21 Repos Scanned
192
+ ansede-static has been run against **35 real open-source repos** totaling over **71 MB of supported source code** across **5 languages**. Every finding was classified by the audit engine.
204
193
 
205
- To validate beyond synthetic benchmarks, ansede-static was run against **21 real production open-source repos** totaling over **2.5 GB of source code** across 8 languages. Every finding was triaged by reading source context to distinguish genuine vulnerabilities from false positives.
194
+ | Metric | 25 Small (≤2MB) | 10 Medium (2-10MB) | **Combined** |
195
+ |---|---|---:|---:|
196
+ | Repos scanned | 25 | 10 | **35** |
197
+ | Zero failures | ✅ | ✅ | **✅ 35/35** |
198
+ | Files scanned | 2,873 | 9,499 | **12,372** |
199
+ | Lines scanned | 333,811 | 1,426,143 | **1,759,954** |
200
+ | Source MB | 12.30 | 58.95 | **71.25 MB** |
201
+ | Total findings | 1,037 | 3,612 | **4,649** |
202
+ | Findings per kLOC | 3.11 | 2.53 | **2.64** |
203
+ | CWE types detected | 25+ | 33 | **35+** |
204
+ | True Positives | — | 11 | **11+** |
205
+ | NEEDS_REVIEW | — | 1,224 | **1,224+** |
206
206
 
207
- | Metric | Result |
207
+ **Top CWEs detected across all repos:** CWE-862 (missing auth), CWE-1333 (ReDoS), CWE-798 (hardcoded creds), CWE-352 (CSRF), CWE-95 (eval injection), CWE-79 (XSS), CWE-89 (SQLi).
208
+
209
+ ### Synthetic Benchmarks
210
+
211
+ | Benchmark | Result |
208
212
  |---|---|
209
- | **Repos scanned** | 21 (GitHub popular repos) |
210
- | **Total findings** | 1,032 |
211
- | **Confirmed real vulnerabilities** | **62** |
212
- | **Structural engine FP rate** | **0%** (zero false positives on taint findings) |
213
- | **Languages** | Python, JavaScript, TypeScript, Java, C#, Go, Ruby, PHP |
214
- | FP rate (YAML rules) | ~54% (context-free regex patterns — improved with confidence + path_exclude) |
215
- | **FP reductions applied** | −81% (59% ~11% via confidence tuning + exclusions + path_exclude) |
216
-
217
- **Key real-world discoveries:**
218
-
219
- | Repo | Stars | Confirmed Vulns | Types Found |
220
- |------|-------|----------------|-------------|
221
- | **uptime-kuma** | ⭐ 60k | **16** 🔥 | Path traversal, SSRF, XSS, code injection |
222
- | **pocketbase** | ⭐ 42k | **11** 🔥 | SQLi, path traversal, SSRF, command injection |
223
- | **hoppscotch** | ⭐ 68k | **9** 🔥 | XSS, SQLi in OAuth, path traversal |
224
- | **dashy** | ⭐ 20k | **7** | Dynamic require, path traversal, SSRF |
225
- | **speedtest** | ⭐ 14k | **6** | Path traversal, open redirect, SSRF |
226
- | **stackedit** | ⭐ 22k | **2** | Open redirect, eval injection |
227
- | **docuseal** | — | **2** | XSS, SSRF |
228
- | **appwrite** | ⭐ 37k | **1** | Path traversal |
229
- | **linkding** | — | **1** | SQL injection |
230
- | NodeGoat, dvna | — | 7 | Validation targets |
231
-
232
- All confirmed findings were disclosed responsibly via GitHub Issues from `@mattybellx`.
233
-
234
- > **Verdict:** The structural taint engine is genuinely **world-class** — **zero false positives** on interprocedural taint analysis across 8 languages. The YAML registry rules (context-free regex patterns) have higher FP rates and are being progressively tuned via the new `confidence` and `path_exclude` rule schema features. See [`tools/responsible_disclosure.py`](tools/responsible_disclosure.py) for the automated disclosure pipeline.
213
+ | NVD CVE snippet recall | **100%** (115/115 synthetic cases) |
214
+ | Web-wild recall | **100%** (6/6 vulnerable-by-design apps) |
215
+ | Web-wild F1 | **92.31%** |
216
+ | LLM auto-classification | **95.9%** across 632 findings, 7 languages |
217
+ | Languages | Python · JavaScript · TypeScript · Go · Java · C# |
218
+
219
+ **Honest note:** CVE snippet benchmarks measure pattern coverage, not real-world field performance. The real-world benchmark data above is the best measure of actual field behavior.
235
220
 
236
221
  ---
237
222
 
238
223
  ## Detection Coverage
239
224
 
240
- | Category | CWEs detected | Example |
241
- |---|---|---|
242
- | Broken Access Control (IDOR, auth bypass) | CWE-639, CWE-862, CWE-285, CWE-287 | Route missing `@login_required`, no ownership check on DB query |
243
- | Injection | CWE-89, CWE-78, CWE-94, CWE-95 | SQLi via f-string, command injection via `subprocess(shell=True)`, eval injection |
244
- | Cryptographic Failures | CWE-327, CWE-328, CWE-798 | MD5/SHA1 for passwords, hardcoded AWS keys, API tokens in source |
245
- | Path Traversal & SSRF | CWE-22, CWE-918 | Unsanitized `os.path.join`, user-controlled URLs in `requests.get()` |
246
- | Cross-Site Issues | CWE-79, CWE-352 | `innerHTML` with user data, missing CSRF tokens |
247
- | Deserialization | CWE-502 | `pickle.loads()` on untrusted input |
248
- | Open Redirect | CWE-601 | User-controlled `next` parameter in `redirect()` |
249
- | Log Injection | CWE-117 | Unsanitized user input in log messages |
225
+ | Category | CWEs detected (verified in fresh benchmark) | Example |
226
+ |---|---|---|---|
227
+ | Missing Authentication | CWE-862, CWE-287 | Route missing `@login_required` |
228
+ | IDOR / Broken Access Control | CWE-639, CWE-285 | No ownership check on DB query |
229
+ | Injection (SQL, Command, Eval) | CWE-89, CWE-78, CWE-95, CWE-94 | SQLi via f-string, `subprocess(shell=True)`, eval injection |
250
230
  | ReDoS | CWE-1333 | Catastrophic backtracking in regex patterns |
251
- | And more | 20+ categories | See `ansede-static --list-rules` for the full catalog |
231
+ | Hardcoded Credentials | CWE-798 | API tokens, AWS keys, passwords in source |
232
+ | CSRF | CWE-352 | Missing CSRF tokens on mutating routes |
233
+ | XSS | CWE-79 | `innerHTML` with user data |
234
+ | Path Traversal & SSRF | CWE-22, CWE-918 | Unsanitized `os.path.join`, user-controlled URLs |
235
+ | Open Redirect | CWE-601 | User-controlled `next` in `redirect()` |
236
+ | Deserialization | CWE-502 | `pickle.loads()` on untrusted input |
237
+ | Prototype Pollution | CWE-1321 | Unsafe object merge |
238
+ | Log Injection | CWE-117 | Unsanitized input in log messages |
239
+ | Weak Cryptography | CWE-327, CWE-328 | MD5/SHA1 for passwords |
240
+ | And more | 33+ CWE types detected in one 10-repo run | See `ansede-static --list-rules` |
252
241
 
253
242
  ---
254
243
 
@@ -306,15 +295,17 @@ All confirmed findings were disclosed responsibly via GitHub Issues from `@matty
306
295
 
307
296
  | | ansede-static | Bandit OSS | Semgrep OSS | CodeQL CLI |
308
297
  |---|---|---|---|---|
309
- | CVE Recall | **98.8%** | ~65% | ~72% | ~88% |
310
- | FP Rate | **3.6%** | ~45% | ~30% | ~12% |
298
+ | Real repos validated | **35** | 1 (Python only) | Community | Limited |
299
+ | CWE types detected | **33+** in one run | ~10 | ~15-25 | ~25-40 |
300
+ | Interprocedural taint | **Full** | ❌ | ❌ (Pro only) | ✅ |
301
+ | Route/auth analysis | **11 checkers** | ❌ | Basic patterns | Limited |
302
+ | Auto-triage + clustering | **✅ 49% reduction** | ❌ | ❌ | ❌ |
311
303
  | Offline (no network) | ✓ | ✓ | ✗ | ✗ |
312
304
  | Zero dependencies | ✓ | ✗ | ✗ | ✗ |
313
305
  | Single binary (.exe) | ✓ | ✗ | ✗ | ✗ |
314
- | IDOR / Auth bypass | | ✗ | Partial | Partial |
306
+ | IDOR / Auth bypass | **✓** | ✗ | Partial | Partial |
315
307
  | Languages | 5 | 1 | 20+ | 7 |
316
308
  | Install size | <5 MB | ~15 MB | ~200 MB | ~600 MB |
317
- | Speed (scan_file) | **0.02s/100k LOC** | 0.5s | 3s | 10s |
318
309
 
319
310
  ---
320
311
 
@@ -7,8 +7,8 @@
7
7
  </p>
8
8
 
9
9
  <p align="center">
10
- <strong>The world's most precise offline static application security testing engine.</strong><br>
11
- Zero dependencies. 98.8% CVE recall. Five languages. Ships as a single <code>.exe</code>.
10
+ <strong>Offline static application security testing engine.</strong><br>
11
+ Zero dependencies. Real-world validated. 5 languages. LLM-assisted triage. Ships as a single <code>.exe</code>.
12
12
  </p>
13
13
 
14
14
  <p align="center">
@@ -16,8 +16,9 @@
16
16
  <a href="https://pypi.org/project/ansede-static/"><img src="https://img.shields.io/pypi/v/ansede-static?label=pypi&color=0078D4" alt="PyPI"></a>
17
17
  <a href="https://pypi.org/project/ansede-static/"><img src="https://img.shields.io/pypi/dm/ansede-static?label=downloads&color=107C10" alt="Downloads"></a>
18
18
  <a href="https://github.com/mattybellx/Ansede/actions/workflows/ci.yml"><img src="https://github.com/mattybellx/Ansede/actions/workflows/ci.yml/badge.svg?branch=master" alt="CI"></a>
19
- <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/CVE%20Recall-98.8%25-brightgreen" alt="CVE Recall 98.8%"></a>
20
- <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/FP%20Rate-3.6%25-brightgreen" alt="FP Rate 3.6%"></a>
19
+ <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/Real%20Repos%20Scanned-35-blue" alt="35 real repos scanned"></a>
20
+ <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/CWE%20Types-33%2B-yellow" alt="33+ CWE types"></a>
21
+ <a href="https://github.com/mattybellx/Ansede/blob/master/BENCHMARKS.md"><img src="https://img.shields.io/badge/LLM%20Triage-96%25%20auto-yellowgreen" alt="LLM Auto 96%"></a>
21
22
  <a href="https://github.com/mattybellx/Ansede/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-yellow.svg" alt="License MIT"></a>
22
23
  <a href="https://github.com/mattybellx/Ansede/stargazers"><img src="https://img.shields.io/github/stars/mattybellx/Ansede?style=social" alt="Stars"></a>
23
24
  </p>
@@ -102,7 +103,7 @@ def delete_post(post_id):
102
103
  # no if post.author_id != current_user.id: abort(403)
103
104
  ```
104
105
 
105
- **ansede-static models routes, decorators, auth guards, and ownership patterns at the AST level.** This is how it achieves 98.8% CVE recall while Bandit OSS sits at ~65%.
106
+ **ansede-static models routes, decorators, auth guards, and ownership patterns at the AST level.** This is how it catches access-control vulnerabilities that regex-only tools miss.
106
107
 
107
108
  ---
108
109
 
@@ -136,71 +137,59 @@ ansede-static src/ --incremental
136
137
 
137
138
  ## Verified Performance — May 2026
138
139
 
139
- | Benchmark | Result |
140
- |---|---|
141
- | Regression suite | **919 tests passed** |
142
- | NVD CVE recall | **81/82 (98.78%)** |
143
- | NVD CVE precision | **96.43%** |
144
- | False positive rate | **3.57%** |
145
- | Web-wild recall | **100.00%** |
146
- | Web-wild precision | **95.00%** |
147
- | External real-world corpus | **15/15 cases, 30/30 checks (100%)** |
148
- | Noise quotient | **0.861 findings / kLOC** |
149
- | Raw engine speed | **~0.02s per 100k LOC** |
150
- | Languages | Python · JavaScript · TypeScript · Go · Java · C# |
151
- | World-Best Audit | ✅ All quality gates passed |
140
+ For the full methodology and raw data, see [`BENCHMARKS.md`](BENCHMARKS.md).
152
141
 
153
- Full methodology and machine-readable artifacts: [`BENCHMARKS.md`](BENCHMARKS.md)
142
+ ### Real-World Validation 35 Repos Scanned
154
143
 
155
- ### 🌍 Real-World Validation 21 Repos Scanned
144
+ ansede-static has been run against **35 real open-source repos** totaling over **71 MB of supported source code** across **5 languages**. Every finding was classified by the audit engine.
156
145
 
157
- To validate beyond synthetic benchmarks, ansede-static was run against **21 real production open-source repos** totaling over **2.5 GB of source code** across 8 languages. Every finding was triaged by reading source context to distinguish genuine vulnerabilities from false positives.
146
+ | Metric | 25 Small (≤2MB) | 10 Medium (2-10MB) | **Combined** |
147
+ |---|---|---:|---:|
148
+ | Repos scanned | 25 | 10 | **35** |
149
+ | Zero failures | ✅ | ✅ | **✅ 35/35** |
150
+ | Files scanned | 2,873 | 9,499 | **12,372** |
151
+ | Lines scanned | 333,811 | 1,426,143 | **1,759,954** |
152
+ | Source MB | 12.30 | 58.95 | **71.25 MB** |
153
+ | Total findings | 1,037 | 3,612 | **4,649** |
154
+ | Findings per kLOC | 3.11 | 2.53 | **2.64** |
155
+ | CWE types detected | 25+ | 33 | **35+** |
156
+ | True Positives | — | 11 | **11+** |
157
+ | NEEDS_REVIEW | — | 1,224 | **1,224+** |
158
158
 
159
- | Metric | Result |
159
+ **Top CWEs detected across all repos:** CWE-862 (missing auth), CWE-1333 (ReDoS), CWE-798 (hardcoded creds), CWE-352 (CSRF), CWE-95 (eval injection), CWE-79 (XSS), CWE-89 (SQLi).
160
+
161
+ ### Synthetic Benchmarks
162
+
163
+ | Benchmark | Result |
160
164
  |---|---|
161
- | **Repos scanned** | 21 (GitHub popular repos) |
162
- | **Total findings** | 1,032 |
163
- | **Confirmed real vulnerabilities** | **62** |
164
- | **Structural engine FP rate** | **0%** (zero false positives on taint findings) |
165
- | **Languages** | Python, JavaScript, TypeScript, Java, C#, Go, Ruby, PHP |
166
- | FP rate (YAML rules) | ~54% (context-free regex patterns — improved with confidence + path_exclude) |
167
- | **FP reductions applied** | −81% (59% ~11% via confidence tuning + exclusions + path_exclude) |
168
-
169
- **Key real-world discoveries:**
170
-
171
- | Repo | Stars | Confirmed Vulns | Types Found |
172
- |------|-------|----------------|-------------|
173
- | **uptime-kuma** | ⭐ 60k | **16** 🔥 | Path traversal, SSRF, XSS, code injection |
174
- | **pocketbase** | ⭐ 42k | **11** 🔥 | SQLi, path traversal, SSRF, command injection |
175
- | **hoppscotch** | ⭐ 68k | **9** 🔥 | XSS, SQLi in OAuth, path traversal |
176
- | **dashy** | ⭐ 20k | **7** | Dynamic require, path traversal, SSRF |
177
- | **speedtest** | ⭐ 14k | **6** | Path traversal, open redirect, SSRF |
178
- | **stackedit** | ⭐ 22k | **2** | Open redirect, eval injection |
179
- | **docuseal** | — | **2** | XSS, SSRF |
180
- | **appwrite** | ⭐ 37k | **1** | Path traversal |
181
- | **linkding** | — | **1** | SQL injection |
182
- | NodeGoat, dvna | — | 7 | Validation targets |
183
-
184
- All confirmed findings were disclosed responsibly via GitHub Issues from `@mattybellx`.
185
-
186
- > **Verdict:** The structural taint engine is genuinely **world-class** — **zero false positives** on interprocedural taint analysis across 8 languages. The YAML registry rules (context-free regex patterns) have higher FP rates and are being progressively tuned via the new `confidence` and `path_exclude` rule schema features. See [`tools/responsible_disclosure.py`](tools/responsible_disclosure.py) for the automated disclosure pipeline.
165
+ | NVD CVE snippet recall | **100%** (115/115 synthetic cases) |
166
+ | Web-wild recall | **100%** (6/6 vulnerable-by-design apps) |
167
+ | Web-wild F1 | **92.31%** |
168
+ | LLM auto-classification | **95.9%** across 632 findings, 7 languages |
169
+ | Languages | Python · JavaScript · TypeScript · Go · Java · C# |
170
+
171
+ **Honest note:** CVE snippet benchmarks measure pattern coverage, not real-world field performance. The real-world benchmark data above is the best measure of actual field behavior.
187
172
 
188
173
  ---
189
174
 
190
175
  ## Detection Coverage
191
176
 
192
- | Category | CWEs detected | Example |
193
- |---|---|---|
194
- | Broken Access Control (IDOR, auth bypass) | CWE-639, CWE-862, CWE-285, CWE-287 | Route missing `@login_required`, no ownership check on DB query |
195
- | Injection | CWE-89, CWE-78, CWE-94, CWE-95 | SQLi via f-string, command injection via `subprocess(shell=True)`, eval injection |
196
- | Cryptographic Failures | CWE-327, CWE-328, CWE-798 | MD5/SHA1 for passwords, hardcoded AWS keys, API tokens in source |
197
- | Path Traversal & SSRF | CWE-22, CWE-918 | Unsanitized `os.path.join`, user-controlled URLs in `requests.get()` |
198
- | Cross-Site Issues | CWE-79, CWE-352 | `innerHTML` with user data, missing CSRF tokens |
199
- | Deserialization | CWE-502 | `pickle.loads()` on untrusted input |
200
- | Open Redirect | CWE-601 | User-controlled `next` parameter in `redirect()` |
201
- | Log Injection | CWE-117 | Unsanitized user input in log messages |
177
+ | Category | CWEs detected (verified in fresh benchmark) | Example |
178
+ |---|---|---|---|
179
+ | Missing Authentication | CWE-862, CWE-287 | Route missing `@login_required` |
180
+ | IDOR / Broken Access Control | CWE-639, CWE-285 | No ownership check on DB query |
181
+ | Injection (SQL, Command, Eval) | CWE-89, CWE-78, CWE-95, CWE-94 | SQLi via f-string, `subprocess(shell=True)`, eval injection |
202
182
  | ReDoS | CWE-1333 | Catastrophic backtracking in regex patterns |
203
- | And more | 20+ categories | See `ansede-static --list-rules` for the full catalog |
183
+ | Hardcoded Credentials | CWE-798 | API tokens, AWS keys, passwords in source |
184
+ | CSRF | CWE-352 | Missing CSRF tokens on mutating routes |
185
+ | XSS | CWE-79 | `innerHTML` with user data |
186
+ | Path Traversal & SSRF | CWE-22, CWE-918 | Unsanitized `os.path.join`, user-controlled URLs |
187
+ | Open Redirect | CWE-601 | User-controlled `next` in `redirect()` |
188
+ | Deserialization | CWE-502 | `pickle.loads()` on untrusted input |
189
+ | Prototype Pollution | CWE-1321 | Unsafe object merge |
190
+ | Log Injection | CWE-117 | Unsanitized input in log messages |
191
+ | Weak Cryptography | CWE-327, CWE-328 | MD5/SHA1 for passwords |
192
+ | And more | 33+ CWE types detected in one 10-repo run | See `ansede-static --list-rules` |
204
193
 
205
194
  ---
206
195
 
@@ -258,15 +247,17 @@ All confirmed findings were disclosed responsibly via GitHub Issues from `@matty
258
247
 
259
248
  | | ansede-static | Bandit OSS | Semgrep OSS | CodeQL CLI |
260
249
  |---|---|---|---|---|
261
- | CVE Recall | **98.8%** | ~65% | ~72% | ~88% |
262
- | FP Rate | **3.6%** | ~45% | ~30% | ~12% |
250
+ | Real repos validated | **35** | 1 (Python only) | Community | Limited |
251
+ | CWE types detected | **33+** in one run | ~10 | ~15-25 | ~25-40 |
252
+ | Interprocedural taint | **Full** | ❌ | ❌ (Pro only) | ✅ |
253
+ | Route/auth analysis | **11 checkers** | ❌ | Basic patterns | Limited |
254
+ | Auto-triage + clustering | **✅ 49% reduction** | ❌ | ❌ | ❌ |
263
255
  | Offline (no network) | ✓ | ✓ | ✗ | ✗ |
264
256
  | Zero dependencies | ✓ | ✗ | ✗ | ✗ |
265
257
  | Single binary (.exe) | ✓ | ✗ | ✗ | ✗ |
266
- | IDOR / Auth bypass | | ✗ | Partial | Partial |
258
+ | IDOR / Auth bypass | **✓** | ✗ | Partial | Partial |
267
259
  | Languages | 5 | 1 | 20+ | 7 |
268
260
  | Install size | <5 MB | ~15 MB | ~200 MB | ~600 MB |
269
- | Speed (scan_file) | **0.02s/100k LOC** | 0.5s | 3s | 10s |
270
261
 
271
262
  ---
272
263
 
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "ansede-static"
7
- version = "2.3.0-dev"
7
+ version = "2.3.1"
8
8
  description = "AST-based SAST for Python and JavaScript — detects IDOR, auth bypass, and ownership flaws that Bandit misses."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -20,7 +20,9 @@ from ansede_static.python_analyzer import analyze_python, analyze_file as _py_fi
20
20
  from ansede_static.js_engine.backends import list_js_backends, run_js_analysis
21
21
  from ansede_static import yaml_rules as _yaml_rules
22
22
 
23
+ from functools import lru_cache
23
24
  from pathlib import Path
25
+ from types import SimpleNamespace
24
26
 
25
27
 
26
28
  __all__ = [
@@ -46,6 +48,65 @@ _RUBY_EXTS = frozenset({".rb", ".rake", ".gemspec"})
46
48
  _PHP_EXTS = frozenset({".php", ".phtml", ".php3", ".php4", ".php5", ".php7", ".phps"})
47
49
 
48
50
 
51
+ def _rule_mtime(path: Path) -> int:
52
+ try:
53
+ return path.stat().st_mtime_ns
54
+ except OSError:
55
+ return -1
56
+
57
+
58
+ def _community_rules_token() -> tuple[tuple[str, int], ...]:
59
+ try:
60
+ rule_dir = Path(_yaml_rules.default_community_rules_dir()).resolve(strict=False)
61
+ except (OSError, TypeError, ValueError):
62
+ return tuple()
63
+
64
+ if not rule_dir.is_dir():
65
+ return tuple()
66
+
67
+ entries: list[tuple[str, int]] = []
68
+ for child in sorted(rule_dir.iterdir()):
69
+ if child.is_file() and child.suffix.lower() in {".yaml", ".yml", ".json"}:
70
+ entries.append((str(child.resolve(strict=False)), _rule_mtime(child)))
71
+ return tuple(entries)
72
+
73
+
74
+ @lru_cache(maxsize=64)
75
+ def _load_runtime_rules_cached(
76
+ workspace_root: str,
77
+ custom_rules_file: str,
78
+ custom_rules_mtime: int,
79
+ community_rules_token: tuple[tuple[str, int], ...],
80
+ ) -> tuple[object, ...]:
81
+ config_stub = SimpleNamespace(custom_rules_file=custom_rules_file) if custom_rules_file else None
82
+ return tuple(_yaml_rules.load_runtime_rules(config=config_stub, workspace_root=Path(workspace_root)))
83
+
84
+
85
+ def _get_runtime_rules(
86
+ config: AnsedeConfig | None,
87
+ *,
88
+ workspace_root: Path,
89
+ ) -> list[object]:
90
+ resolved_root = str(workspace_root.resolve(strict=False))
91
+ custom_rules_file = str(getattr(config, "custom_rules_file", "") or "").strip() if config else ""
92
+ custom_rules_path = ""
93
+ custom_rules_mtime = -1
94
+ if custom_rules_file:
95
+ custom_path = Path(custom_rules_file)
96
+ if not custom_path.is_absolute():
97
+ custom_path = (workspace_root / custom_path).resolve(strict=False)
98
+ custom_rules_path = str(custom_path)
99
+ custom_rules_mtime = _rule_mtime(custom_path)
100
+ return list(
101
+ _load_runtime_rules_cached(
102
+ resolved_root,
103
+ custom_rules_path,
104
+ custom_rules_mtime,
105
+ _community_rules_token(),
106
+ )
107
+ )
108
+
109
+
49
110
  def _apply_runtime_and_registry_rules(
50
111
  code: str,
51
112
  *,
@@ -89,13 +150,10 @@ def scan_file(
89
150
  """
90
151
  p = Path(path)
91
152
  ext = p.suffix.lower()
92
- runtime_rules = _yaml_rules.load_runtime_rules(config=config, workspace_root=Path.cwd())
153
+ runtime_rules = _get_runtime_rules(config, workspace_root=Path.cwd())
93
154
  code = p.read_text(encoding="utf-8", errors="replace")
94
155
 
95
156
  # Create a shared GlobalGraph for IFDS-based interprocedural taint transfer.
96
- # Both Python and JS analyzers feed summaries into it and query it during
97
- # helper-call resolution, giving JS the same IDE-lattice-powered cross-file
98
- # taint tracking that Python already uses.
99
157
  try:
100
158
  from ansede_static.ir.global_graph import GlobalGraph # noqa: PLC0415
101
159
  shared_graph = GlobalGraph()
@@ -152,7 +210,7 @@ def scan_code(
152
210
  Raises:
153
211
  ValueError: if language is not supported.
154
212
  """
155
- runtime_rules = _yaml_rules.load_runtime_rules(config=config, workspace_root=Path.cwd())
213
+ runtime_rules = _get_runtime_rules(config, workspace_root=Path.cwd())
156
214
  with temporary_analyzer_config(config):
157
215
  if language == "python":
158
216
  result = analyze_python(code, filename=filename)