Skip to content

Add OWASP AI resource importer support for issue #471#8

Open
Bornunique911 wants to merge 76 commits into
review/issue-471-top10-api-importersfrom
review/issue-471-ai-resource-importers
Open

Add OWASP AI resource importer support for issue #471#8
Bornunique911 wants to merge 76 commits into
review/issue-471-top10-api-importersfrom
review/issue-471-ai-resource-importers

Conversation

@Bornunique911

@Bornunique911 Bornunique911 commented Mar 24, 2026

Copy link
Copy Markdown
Owner

Related Issue

This PR addresses:

Problem

OpenCRE does not yet import newer OWASP AI-focused resources needed for practical AI/LLM mapping coverage.

Solution

This PR adds parser/data support for:

  • OWASP Top 10 for LLM and Gen AI Apps 2025
  • OWASP AI Security Verification Standard (AISVS)

These resources are added through explicit parser and data files so they remain maintainable and reviewable.

Testing

Executed focused parser validation for the added AI resources.

Scope

Standards and parser layer

  • LLM Top 10 data and parser
  • AISVS data and parser
  • parser wiring and focused parser tests

@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from e704114 to 63528a8 Compare April 1, 2026 10:09
@Bornunique911 Bornunique911 force-pushed the review/issue-471-top10-api-importers branch from 7f38846 to 6033a92 Compare April 1, 2026 10:09
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from 42c4e6b to fab3098 Compare April 11, 2026 07:58
@Bornunique911 Bornunique911 force-pushed the review/issue-471-top10-api-importers branch from 0659489 to 508dcc0 Compare April 11, 2026 07:58
@Bornunique911 Bornunique911 force-pushed the review/issue-471-top10-api-importers branch from 508dcc0 to c27cc7a Compare April 21, 2026 16:57
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from fab3098 to a11c5af Compare April 21, 2026 16:57
Add ga_parity helpers, CLI verification scripts, and regression tests so
import and gap-analysis workflows can be checked against both stores.

Made-with: Cursor
Add application-level backoff for RAG and fallback chat calls so brief
quota pressure is less likely to surface as hard 500s (configure via
GEMINI_GENERATE_MAX_RETRIES and GEMINI_GENERATE_RETRY_SLEEP_SECONDS).

Made-with: Cursor
Harden Postgres migrations, refine gap analysis scheduling and web admin
paths, extend PCI DSS parsing, refresh staging scripts and benchmarks,
and align unit tests with the updated behavior.

Made-with: Cursor
- Use shorter default retries/sleeps on Heroku web dynos (DYNO=web.*) so
  requests finish before the ~30s router timeout; keep env overrides.
- Log Gemini ClientError details (http_code, api status, message, details)
  for debugging 429s without exposing secrets.
- Treat google.genai ClientError HTTP status via .code (not .status_code)
  and return 503 JSON for rate limits from /rest/v1/completion.
- Add unit tests for retry helpers and completion route behavior.

Made-with: Cursor
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from a11c5af to 42553e4 Compare April 21, 2026 17:06
Gunicorn kills sync workers on timeout while time.sleep() runs after Gemini
429. Default to zero retries on web.* so /rest/v1/completion returns 503 JSON
instead of 500. Treat DYNO case-insensitively so Heroku-style limits always apply.
Resolves the "Resource Exhausted" error when using a standard API key
by defaulting to the correct embedding model (`embedding-001`). Also
introduces environment variables for configuring the chat and embedding
models, and improves exception handling to correctly catch and report
rate limiting and quota issues to the user.
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch 2 times, most recently from b6290af to afdcaf6 Compare April 21, 2026 19:25
…ate (OWASP#884)

ENABLE_MYOPENCRE and GAP_ANALYSIS_OPTIMIZED were evaluated once at import/class definition time, freezing their values. Upstream has since removed all usages of both flags, so their frozen definitions in config.py are dropped.

Introduces application/feature_flags.py with is_cre_import_allowed(), which reads os.getenv("CRE_ALLOW_IMPORT") fresh on every call using a TRUE_VALUES whitelist matching upstream gate semantics (1, true, yes).

Also fixes a pre-existing inconsistency in the /rest/v1/config endpoint: it previously returned True only for "1", while the gate accepted "1", "true", and "yes". Both now use is_cre_import_allowed() so the frontend reflects the actual gate state.

Tests updated to remove stale flag patches and use patch.dict for proper env isolation.
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from afdcaf6 to 5f0f501 Compare April 26, 2026 20:53
Bornunique911 and others added 11 commits April 27, 2026 21:49
* Add OpenCRE as a map analysis resource

* Preserve multiple OpenCRE map analysis overlaps

* Clean issue OWASP#469 web_main.py

* Add direct-only OpenCRE map analysis

* Fix OpenCRE map analysis hover payload

* Add OpenCRE as a map analysis resource

* Preserve multiple OpenCRE map analysis overlaps

* Add direct-only OpenCRE map analysis

* Fix OpenCRE map analysis hover payload

* Enhance map analysis by enforcing two standards input and improving Redis fallback handling

* Fix missing newline at end of file in web_main.py

---------

Signed-off-by: Bornunique911 <69379200+Bornunique911@users.noreply.github.com>
Implement RFC improve-embedding-accuracy: CRE_EMBED_SMART_EXTRACT (off/on/shadow),
HTML block segmentation, LLM JSON alignment (OpenAI + Vertex), validated #fragments,
page cache by URL and alignment cache by (url, section_key). Node hyperlink unchanged;
persist narrowed URLs on Embeddings.embeddings_url. Extend add_embedding for optional
embeddings_url. Unit tests plus pytest -m llm_e2e for live OWASP AI Exchange pages.
Restrict incremental embedding test mocks with spec so default-on does not
treat MagicMock as a real align_embedding_span_json implementation.
…nt JSON with Pydantic

- Vertex/Gemini: exit if VERTEX_EMBED_CONTENT_MODEL is unset; document defaults in .env.example.
- Smart extract: add AlignmentPayload schema, provider json_schema for OpenAI and Gemini alignment calls.
- Tests: invalid alignment payload fallback; missing env var guard.

Embeddings rebuild: run locally with cre.py --regenerate_embeddings after setting env.
- Node_collection.delete_all_embeddings + --regenerate_embeddings / regenerate_embeddings()
- Chatbot: narrow embeddings_url in LLM context and reference table hyperlink when it differs from catalog link
- Docs: developmentSetup + RFC note; db_test for delete_all_embeddings
API reference rows keep catalog hyperlink; optional embeddingsUrl for scoped
source link. LLM context uses Embeddings_URL label. Update types and dev docs.
Tolerate fenced or prefixed JSON wrapper text from provider structured-output calls so smart extract falls back less often on parse-only formatting issues. Add focused unit tests for OpenAI and Vertex parser behavior to keep malformed wrappers from regressing alignment reliability.

Made-with: Cursor
Prevent env SQLALCHEMY_DATABASE_URI from overriding CMDConfig-provided CLI database targets, and normalize postgres:// URLs to postgresql:// for SQLAlchemy compatibility.

Made-with: Cursor
Ignore local agent/editor workspaces and local database artifacts to keep development-only files out of commits.

Made-with: Cursor
…lure

Capture a safely truncated response snippet when alignment JSON parsing fails in OpenAI and Vertex clients to improve debugging while preserving existing error propagation.

Made-with: Cursor
northdpole and others added 18 commits June 11, 2026 14:21
Track AGENTS.md and .cursor/rules so the team shares human-plan-then-agent-execute workflows, CI/PR policies, and domain safety guardrails.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add modular .cursor/rules for requirements gates, tickets, TDD, and
verification; tighten plan-first and multi-agent flows; slim AGENTS.md
to an index aligned with make lint/mypy/test checks.

Co-authored-by: Cursor <cursoragent@cursor.com>
The test expected tags="1,2" but dbNodeFromCode joins the input list
["111-111", "222-222"] with commas, producing "111-111,222-222".
The expected value in the test was wrong.
Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Closes OWASP#862

request.args.get('text') returns None if the query param is absent.
Passing None into db.text_search() causes re.search() to raise
TypeError: expected string or bytes-like object.
Return a 400 before reaching the database call.
Replace get_all_records() with get_all_values() to bypass gspread's
numericise() which converts section codes like '5.10' to float 5.1.
get_all_values() returns raw strings, preserving trailing zeros.

Fixes OWASP#574
Fixes OWASP#546
Align spreadsheet_test with get_all_values-based read path so section
codes like 5.10 stay strings instead of being float-coerced.

Co-authored-by: Cursor <cursoragent@cursor.com>
Handle empty worksheets and pad short rows so section IDs are preserved
as strings without IndexError or truncated dict keys.
Fail fast with GSpreadException when worksheet header row contains
duplicates, use zip(strict=True) after row padding, and add regression
tests for the helper and read_spreadsheet integration.
Fix production H12 timeouts from GET /all_cres?per_page=1000 by batching
N+1 link hydration in the DB layer, capping per_page at 100, scoping
DataProvider to Explorer routes with incremental page loads, and using
ensureFullExplorerData for graph views.

Closes OWASP#930. Related: OWASP#847, OWASP#848.

Co-authored-by: Cursor <cursoragent@cursor.com>
Fix buildTree sibling keyPath mutation, serialize loadPage via promise
chain with exposed dataLoadError, hoist Explorer layout wrappers,
surface load failures in graph views, restore viewport zoom, and
harden pagination link parity test.

Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(api): add feature-flagged /rest/v1/health endpoint

Adds a lightweight deploy/uptime health probe at GET /rest/v1/health, gated behind the CRE_ENABLE_HEALTH feature flag (off by default).

Behavior:
- Flag off (default): endpoint returns 404, as if it does not exist.
- Flag on, healthy: 200 with {ok, db_reachable, cre_count, standards_count} when the serving DB is reachable and holds a non-empty dataset.
- Flag on, unhealthy: 503 when the DB is unreachable or the dataset is empty/broken (reason explains which).

Node_collection.health_check() runs cheap COUNT queries over CRE and Node, never raises (connectivity errors are reported as ok=False), and treats a zero count for either as an empty dataset.

Scope is intentionally limited to DB reachability + data sanity. Deeper checks (gap-analysis completeness, mapping coverage, Neo4j, Redis) are deliberately excluded by design and belong in ops tooling.

* fix: load .env in feature_flags and document CRE_ENABLE_HEALTH flag

* Modified the .env issue
…ASP#939)

* cwe: add XXE search aliases and enforce prohibited CWE exclusions

This commit builds on the earlier CWE mapping work (PR OWASP#823) and
addresses two gaps found during local verification after the previous
merge.

Problem:
Searching for terms like 'XXE' did not reliably surface the expected
top-level CWE result, even when the corresponding CWE data existed
locally. This created a mismatch between the intended curated CWE
import behavior and actual API/UI discoverability.

Solution:
- Expand text-search aliases to include common security shorthand
  terms (e.g., XXE), ensuring related CWE and CRE records surface
  correctly.
- Strengthen CWE import filtering to consistently exclude prohibited
  entries.

Scope:
- CWE import filtering logic
- Search alias expansion for XXE and related terms
- Unit tests covering prohibited CWE exclusion and XXE search behavior
- Script messaging update for the CWE refresh workflow

Testing:
./venv/bin/python -m pytest application/tests/cwe_parser_test.py -k 'register_CWE or prohibited' -q
./venv/bin/python -m pytest application/tests/db_test.py -k 'text_search' -q

Follows-up: OWASP#823
References: OWASP#472

* Update application/database/db.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Bornunique911 <69379200+Bornunique911@users.noreply.github.com>

* Updated the code as per CodeRabbit review.

* Fixed linting issues.

* Added import for SQLAlchemyError and narrow exception handler in health_check.

* Fixed linting issues.

* Fixed whitespace-only searches issue.

---------

Signed-off-by: Bornunique911 <69379200+Bornunique911@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…ataset (OWASP#913)

* feat(module-b): add Pydantic v2 schemas + hashing for Module A input contract

Establishes the data contract Module B consumes from Module A. ChangeRecord
is a Pydantic v2 model matching A's actual emission shape: nested source
(discriminated union on type for github/rss), span (chunk position +
heading_path + char/line offsets), and locator (addressing scheme). Internal
models ClassifyResult and QueuePayload prep for later stages.

hashing.py provides normalize_text + compute_content_hash since Module A
does not emit content_hash; B computes its own (SHA-256 of normalized text)
for use as the knowledge_queue dedup key.

22 unittest cases cover the round-trip, the discriminated union, hash
determinism, normalization rules, code-fence preservation, and idempotency.
Full make test: 271 passing, no regressions.

Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B.

* feat(module-b): add Module A mock fixture + generated JSON Schema artifact

module_a_mock.jsonl: Module A's canonical 20-record mock shared 2026-05-29,
saved as JSONL (one record per line per the contract). Becomes a permanent
integration-test fixture for B's parser and a reference shape for the
Module A contributor.

module_a_contract.schema.json: JSON Schema generated from B's Pydantic
ChangeRecord model via model_json_schema(). 246 lines covering all four
nested types (ChangeRecord, GithubSource, RssSource, Span, Locator).
Source of truth for cross-module CI validation.

Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B.

* feat(module-b): add OWASP harvester, labeling TUI, and labeled dataset

build_labeled_dataset.py: PyGithub-based harvester that acts as Module A's
stand-in for producing benchmark data. Fetches recent commits from 4 OWASP
repos (WSTG, ASVS, CheatSheetSeries, SAMM), applies the contract's
normalization rules, splits into chunks at markdown heading boundaries
with a fence-aware stack-based walker that tracks heading_path + char/line
offsets, and emits records in Module A's actual nested shape. Pluggable
via GITHUB_TOKEN env var. Reproducible: python scripts/build_labeled_dataset.py
regenerates the candidate set.

label_dataset.py: resumable interactive TUI for manual classification.
Atomic-writes labeled_data.json after every keystroke; lookup by chunk_id
for resume. Embeds the recall-first definition (agreed with maintainer
2026-06-01) so labelers see the rule front-of-mind: KNOWLEDGE for any
chunk with security signal, NOISE only for pure organizational content.

candidate_commits.json: 100 records, 25 per repo, all Pydantic-valid
against ChangeRecord. 90/100 have non-empty heading_path; 10 multi-chunk
artifacts captured.

labeled_data.json: 100/100 labeled by hand under the recall-first rule.
Distribution 55 KNOWLEDGE / 40 NOISE / 5 UNCERTAIN. Per-repo skew is
visible: CheatSheetSeries 92% K, SAMM 0% K (the SAMM commits sampled
landed entirely on Website/Sponsorship/meetings paths -- empirical input
for Week 2's noise_patterns.yaml).

Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B.

* style(module-b): apply Black formatting to Week 1 files

Super-Linter (Black 24.4.2) flagged 4 files in the previous push.
Applied `black` (same pinned version) to bring them in line with the
repo's formatting standard. Cosmetic changes only: blank lines around
section-separator comments, one multi-line dict join. No behavior or
test changes -- `make test` remains 271 passing, 1 skip.

* chore(module-b): address CodeRabbit Week 1 review comments

- Sort __all__ lists in hashing.py and schemas.py to satisfy
  Ruff RUF022.
- Declare JSON Schema dialect ($schema = draft 2020-12, which is
  what Pydantic v2 model_json_schema() emits) on the contract artifact.
- Wrap load_labeled() in scripts/label_dataset.py with try/except so a
  corrupted labeled_data.json prints an actionable hint instead of a
  raw JSONDecodeError stack trace.

Deferred to Week 2 (will be addressed when we touch the harvester):
- chunker should also track <pre> open/close, not just ``` fences
- _split_chunk_by_size cursor arithmetic assumes \\n\\n separator even
  on hard-split sub-chunks

Tests: 271 passing, 1 skip (unchanged). Black: clean.
OWASP#928)

* feat(module-b): add Pydantic v2 schemas + hashing for Module A input contract

Establishes the data contract Module B consumes from Module A. ChangeRecord
is a Pydantic v2 model matching A's actual emission shape: nested source
(discriminated union on type for github/rss), span (chunk position +
heading_path + char/line offsets), and locator (addressing scheme). Internal
models ClassifyResult and QueuePayload prep for later stages.

hashing.py provides normalize_text + compute_content_hash since Module A
does not emit content_hash; B computes its own (SHA-256 of normalized text)
for use as the knowledge_queue dedup key.

22 unittest cases cover the round-trip, the discriminated union, hash
determinism, normalization rules, code-fence preservation, and idempotency.
Full make test: 271 passing, no regressions.

Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B.

* feat(module-b): add Module A mock fixture + generated JSON Schema artifact

module_a_mock.jsonl: Module A's canonical 20-record mock shared 2026-05-29,
saved as JSONL (one record per line per the contract). Becomes a permanent
integration-test fixture for B's parser and a reference shape for the
Module A contributor.

module_a_contract.schema.json: JSON Schema generated from B's Pydantic
ChangeRecord model via model_json_schema(). 246 lines covering all four
nested types (ChangeRecord, GithubSource, RssSource, Span, Locator).
Source of truth for cross-module CI validation.

Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B.

* feat(module-b): add OWASP harvester, labeling TUI, and labeled dataset

build_labeled_dataset.py: PyGithub-based harvester that acts as Module A's
stand-in for producing benchmark data. Fetches recent commits from 4 OWASP
repos (WSTG, ASVS, CheatSheetSeries, SAMM), applies the contract's
normalization rules, splits into chunks at markdown heading boundaries
with a fence-aware stack-based walker that tracks heading_path + char/line
offsets, and emits records in Module A's actual nested shape. Pluggable
via GITHUB_TOKEN env var. Reproducible: python scripts/build_labeled_dataset.py
regenerates the candidate set.

label_dataset.py: resumable interactive TUI for manual classification.
Atomic-writes labeled_data.json after every keystroke; lookup by chunk_id
for resume. Embeds the recall-first definition (agreed with maintainer
2026-06-01) so labelers see the rule front-of-mind: KNOWLEDGE for any
chunk with security signal, NOISE only for pure organizational content.

candidate_commits.json: 100 records, 25 per repo, all Pydantic-valid
against ChangeRecord. 90/100 have non-empty heading_path; 10 multi-chunk
artifacts captured.

labeled_data.json: 100/100 labeled by hand under the recall-first rule.
Distribution 55 KNOWLEDGE / 40 NOISE / 5 UNCERTAIN. Per-repo skew is
visible: CheatSheetSeries 92% K, SAMM 0% K (the SAMM commits sampled
landed entirely on Website/Sponsorship/meetings paths -- empirical input
for Week 2's noise_patterns.yaml).

Part of GSoC 2026 OpenCRE Scraper & Indexer (Project OIE) Module B.

* style(module-b): apply Black formatting to Week 1 files

Super-Linter (Black 24.4.2) flagged 4 files in the previous push.
Applied `black` (same pinned version) to bring them in line with the
repo's formatting standard. Cosmetic changes only: blank lines around
section-separator comments, one multi-line dict join. No behavior or
test changes -- `make test` remains 271 passing, 1 skip.

* chore(module-b): address CodeRabbit Week 1 review comments

- Sort __all__ lists in hashing.py and schemas.py to satisfy
  Ruff RUF022.
- Declare JSON Schema dialect ($schema = draft 2020-12, which is
  what Pydantic v2 model_json_schema() emits) on the contract artifact.
- Wrap load_labeled() in scripts/label_dataset.py with try/except so a
  corrupted labeled_data.json prints an actionable hint instead of a
  raw JSONDecodeError stack trace.

Deferred to Week 2 (will be addressed when we touch the harvester):
- chunker should also track <pre> open/close, not just ``` fences
- _split_chunk_by_size cursor arithmetic assumes \\n\\n separator even
  on hard-split sub-chunks

Tests: 271 passing, 1 skip (unchanged). Black: clean.

* feat(module-b): add Stage 1.5 sanitize.py vendored from TRACT

Defensive text cleanup (PDF ligatures, zero-width chars, HTML, hyphenation).
Vendored from rocklambros/TRACT under CC0; drops their whitespace-collapse
step so structure (newlines, paragraphs) is preserved for Module B's LLM.

26 unit tests, all passing.

* feat(module-b): add Stage 1 regex_filter + noise_patterns.yaml

Path-based filter with extension/filename/glob deny rules and allow_overrides.
Patterns are deliberately conservative under the recall-first labeling rule.

15 unit tests including >=90% rejection / 0% false-positive acceptance criteria.

* fix(module-b): chunker tracks <pre> blocks; correct hard-split cursor math

Addresses CodeRabbit comments #4 and #5 on the Week 1 PR.

* chore(module-b): address CodeRabbit Week 2 review comments

* chore(module-b): address Week 2 maintainer review on noise_patterns.yaml

---------

Signed-off-by: Manshu Saini <149303743+manshusainishab@users.noreply.github.com>
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from 896d219 to 47ed2a1 Compare June 24, 2026 20:32
Abhijeet2409 and others added 10 commits June 30, 2026 10:51
…P#921)

* feat: implement structured extraction checkpoints B1 and B2

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* docs: add docstrings

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* fix: validate normalized string field values correctly

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* fix: validate normalized string field values correctly

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* feat: implement structured extraction checkpoint B3

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* feat: add B4 tests for cheatsheet extractor

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* docs: add checkpoint B5 documentation and refine test comments

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>

* docs: refine malformed heading behavior notes

Signed-off-by: Abhijeet <abhijeetsaharan2236@gmail.com>

---------

Signed-off-by: Abhijeet Saharan <abhijeetsaharan2236@gmail.com>
Signed-off-by: Abhijeet <abhijeetsaharan2236@gmail.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: Bornunique911 <69379200+Bornunique911@users.noreply.github.com>
@Bornunique911 Bornunique911 force-pushed the review/issue-471-ai-resource-importers branch from 809b23c to a1c8289 Compare July 1, 2026 15:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants