Skip to content

Commit 090da0b

Browse files
committed
feat: add standalone OWASP AI and Top 10 importers
1 parent 0e16c2e commit 090da0b

14 files changed

Lines changed: 746 additions & 0 deletions

application/cmd/cre_main.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -911,6 +911,36 @@ def run(args: argparse.Namespace) -> None: # pragma: no cover
911911
BaseParser().register_resource(
912912
secure_headers.SecureHeaders, db_connection_str=args.cache_file
913913
)
914+
if args.owasp_top10_2025_in:
915+
from application.utils.external_project_parsers.parsers import owasp_top10_2025
916+
917+
BaseParser().register_resource(
918+
owasp_top10_2025.OwaspTop10_2025, db_connection_str=args.cache_file
919+
)
920+
if args.owasp_api_top10_2023_in:
921+
from application.utils.external_project_parsers.parsers import (
922+
owasp_api_top10_2023,
923+
)
924+
925+
BaseParser().register_resource(
926+
owasp_api_top10_2023.OwaspApiTop10_2023,
927+
db_connection_str=args.cache_file,
928+
)
929+
if args.owasp_llm_top10_2025_in:
930+
from application.utils.external_project_parsers.parsers import (
931+
owasp_llm_top10_2025,
932+
)
933+
934+
BaseParser().register_resource(
935+
owasp_llm_top10_2025.OwaspLlmTop10_2025,
936+
db_connection_str=args.cache_file,
937+
)
938+
if args.owasp_aisvs_in:
939+
from application.utils.external_project_parsers.parsers import owasp_aisvs
940+
941+
BaseParser().register_resource(
942+
owasp_aisvs.OwaspAisvs, db_connection_str=args.cache_file
943+
)
914944
if args.pci_dss_4_in:
915945
from application.utils.external_project_parsers.parsers import pci_dss
916946

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import unittest
2+
3+
from application import create_app, sqla # type: ignore
4+
from application.database import db
5+
from application.defs import cre_defs as defs
6+
from application.prompt_client import prompt_client
7+
from application.utils.external_project_parsers.parsers import owasp_aisvs
8+
9+
10+
class TestOwaspAisvsParser(unittest.TestCase):
11+
def tearDown(self) -> None:
12+
sqla.session.remove()
13+
sqla.drop_all()
14+
self.app_context.pop()
15+
16+
def setUp(self) -> None:
17+
self.app = create_app(mode="test")
18+
self.app_context = self.app.app_context()
19+
self.app_context.push()
20+
sqla.create_all()
21+
self.collection = db.Node_collection()
22+
23+
def test_parse(self) -> None:
24+
for cre_id, name in [
25+
("227-045", "Identify sensitive data and subject it to a policy"),
26+
(
27+
"307-507",
28+
"Allow only trusted sources both build time and runtime; therefore perform integrity checks on all resources and code",
29+
),
30+
(
31+
"162-655",
32+
"Documentation of all components' business or security function",
33+
),
34+
]:
35+
self.collection.add_cre(defs.CRE(id=cre_id, name=name, description=""))
36+
37+
result = owasp_aisvs.OwaspAisvs().parse(
38+
self.collection, prompt_client.PromptHandler(database=self.collection)
39+
)
40+
41+
entries = result.results["OWASP AI Security Verification Standard (AISVS)"]
42+
self.assertEqual(14, len(entries))
43+
self.assertEqual("AISVS1", entries[0].sectionID)
44+
self.assertEqual(
45+
"Training Data Governance & Bias Management", entries[0].section
46+
)
47+
self.assertEqual(
48+
"https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C01-Training-Data-Integrity-and-Traceability.md",
49+
entries[0].hyperlink,
50+
)
51+
self.assertEqual(
52+
["227-045", "307-507"],
53+
[link.document.id for link in entries[0].links],
54+
)
55+
self.assertEqual("AISVS14", entries[-1].sectionID)
56+
self.assertEqual(
57+
"Human Oversight, Accountability & Governance", entries[-1].section
58+
)
59+
self.assertEqual(
60+
"https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C14-Human-Oversight.md",
61+
entries[-1].hyperlink,
62+
)
63+
self.assertEqual(
64+
["162-655"],
65+
[link.document.id for link in entries[-1].links],
66+
)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import unittest
2+
3+
from application import create_app, sqla # type: ignore
4+
from application.database import db
5+
from application.defs import cre_defs as defs
6+
from application.prompt_client import prompt_client
7+
from application.utils.external_project_parsers.parsers import owasp_api_top10_2023
8+
9+
10+
class TestOwaspApiTop10_2023Parser(unittest.TestCase):
11+
def tearDown(self) -> None:
12+
sqla.session.remove()
13+
sqla.drop_all()
14+
self.app_context.pop()
15+
16+
def setUp(self) -> None:
17+
self.app = create_app(mode="test")
18+
self.app_context = self.app.app_context()
19+
self.app_context.push()
20+
sqla.create_all()
21+
self.collection = db.Node_collection()
22+
23+
def test_parse(self) -> None:
24+
for cre_id, name in [
25+
("304-667", "Protect API against unauthorized access/modification (IDOR)"),
26+
("724-770", "Technical application access control"),
27+
("715-223", "Ensure trusted origin of third party resources"),
28+
]:
29+
self.collection.add_cre(defs.CRE(id=cre_id, name=name, description=""))
30+
31+
result = owasp_api_top10_2023.OwaspApiTop10_2023().parse(
32+
self.collection, prompt_client.PromptHandler(database=self.collection)
33+
)
34+
35+
entries = result.results["OWASP API Security Top 10 2023"]
36+
self.assertEqual(10, len(entries))
37+
self.assertEqual("API1", entries[0].sectionID)
38+
self.assertEqual("Broken Object Level Authorization", entries[0].section)
39+
self.assertEqual(
40+
["304-667", "724-770"],
41+
[link.document.id for link in entries[0].links],
42+
)
43+
self.assertEqual("API10", entries[-1].sectionID)
44+
self.assertEqual(
45+
["715-223"],
46+
[link.document.id for link in entries[-1].links],
47+
)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import unittest
2+
3+
from application import create_app, sqla # type: ignore
4+
from application.database import db
5+
from application.defs import cre_defs as defs
6+
from application.prompt_client import prompt_client
7+
from application.utils.external_project_parsers.parsers import owasp_llm_top10_2025
8+
9+
10+
class TestOwaspLlmTop10_2025Parser(unittest.TestCase):
11+
def tearDown(self) -> None:
12+
sqla.session.remove()
13+
sqla.drop_all()
14+
self.app_context.pop()
15+
16+
def setUp(self) -> None:
17+
self.app = create_app(mode="test")
18+
self.app_context = self.app.app_context()
19+
self.app_context.push()
20+
sqla.create_all()
21+
self.collection = db.Node_collection()
22+
23+
def test_parse(self) -> None:
24+
for cre_id, name in [
25+
("161-451", "Output encoding and injection prevention"),
26+
("064-808", "Encode output context-specifically"),
27+
("760-764", "Injection protection"),
28+
("623-550", "Denial Of Service protection"),
29+
]:
30+
self.collection.add_cre(defs.CRE(id=cre_id, name=name, description=""))
31+
32+
result = owasp_llm_top10_2025.OwaspLlmTop10_2025().parse(
33+
self.collection, prompt_client.PromptHandler(database=self.collection)
34+
)
35+
36+
entries = result.results["OWASP Top 10 for LLM and Gen AI Apps 2025"]
37+
self.assertEqual(10, len(entries))
38+
self.assertEqual("LLM01", entries[0].sectionID)
39+
self.assertEqual("Prompt Injection", entries[0].section)
40+
self.assertEqual(
41+
["161-451", "760-764"], [link.document.id for link in entries[0].links]
42+
)
43+
self.assertEqual(["064-808"], [link.document.id for link in entries[4].links])
44+
self.assertEqual("LLM10", entries[-1].sectionID)
45+
self.assertEqual(["623-550"], [link.document.id for link in entries[-1].links])
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import unittest
2+
3+
from application import create_app, sqla # type: ignore
4+
from application.database import db
5+
from application.defs import cre_defs as defs
6+
from application.prompt_client import prompt_client
7+
from application.utils.external_project_parsers.parsers import owasp_top10_2025
8+
9+
10+
class TestOwaspTop10_2025Parser(unittest.TestCase):
11+
def tearDown(self) -> None:
12+
sqla.session.remove()
13+
sqla.drop_all()
14+
self.app_context.pop()
15+
16+
def setUp(self) -> None:
17+
self.app = create_app(mode="test")
18+
self.app_context = self.app.app_context()
19+
self.app_context.push()
20+
sqla.create_all()
21+
self.collection = db.Node_collection()
22+
23+
def test_parse(self) -> None:
24+
self.collection.add_cre(
25+
defs.CRE(id="177-260", name="Session management", description="")
26+
)
27+
self.collection.add_cre(
28+
defs.CRE(
29+
id="117-371",
30+
name="Use a centralized access control mechanism",
31+
description="",
32+
)
33+
)
34+
self.collection.add_cre(
35+
defs.CRE(
36+
id="724-770",
37+
name="Technical application access control",
38+
description="",
39+
)
40+
)
41+
self.collection.add_cre(
42+
defs.CRE(
43+
id="031-447", name="Whitelist all external (HTTP) input", description=""
44+
)
45+
)
46+
self.collection.add_cre(
47+
defs.CRE(
48+
id="064-808", name="Encode output context-specifically", description=""
49+
)
50+
)
51+
self.collection.add_cre(
52+
defs.CRE(id="760-764", name="Injection protection", description="")
53+
)
54+
self.collection.add_cre(
55+
defs.CRE(id="513-183", name="Error handling", description="")
56+
)
57+
58+
result = owasp_top10_2025.OwaspTop10_2025().parse(
59+
self.collection,
60+
prompt_client.PromptHandler(database=self.collection),
61+
)
62+
63+
entries = result.results["OWASP Top 10 2025"]
64+
self.assertEqual(10, len(entries))
65+
self.assertEqual("A01", entries[0].sectionID)
66+
self.assertEqual("Broken Access Control", entries[0].section)
67+
self.assertEqual(
68+
"https://owasp.org/Top10/2025/A01_2025-Broken_Access_Control/",
69+
entries[0].hyperlink,
70+
)
71+
self.assertEqual(
72+
["117-371", "177-260", "724-770"],
73+
[link.document.id for link in entries[0].links],
74+
)
75+
self.assertEqual(
76+
["031-447", "064-808", "760-764"],
77+
[link.document.id for link in entries[4].links],
78+
)
79+
self.assertEqual("A10", entries[-1].sectionID)
80+
self.assertEqual(["513-183"], [link.document.id for link in entries[-1].links])
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
[
2+
{
3+
"section_id": "AISVS1",
4+
"section": "Training Data Governance & Bias Management",
5+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C01-Training-Data-Integrity-and-Traceability.md",
6+
"cre_ids": ["227-045", "307-507"]
7+
},
8+
{
9+
"section_id": "AISVS2",
10+
"section": "User Input Validation",
11+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C02-Input-Validation.md",
12+
"cre_ids": ["031-447", "760-764"]
13+
},
14+
{
15+
"section_id": "AISVS3",
16+
"section": "Model Lifecycle Management & Change Control",
17+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C03-Model-Lifecycle-Management.md",
18+
"cre_ids": ["148-853", "613-285"]
19+
},
20+
{
21+
"section_id": "AISVS4",
22+
"section": "Infrastructure, Configuration & Deployment Security",
23+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C04-Infrastructure.md",
24+
"cre_ids": ["233-748", "486-813"]
25+
},
26+
{
27+
"section_id": "AISVS5",
28+
"section": "Access Control & Identity for AI Components & Users",
29+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C05-Access-Control-and-Identity.md",
30+
"cre_ids": ["633-428", "724-770"]
31+
},
32+
{
33+
"section_id": "AISVS6",
34+
"section": "Supply Chain Security for Models, Frameworks & Data",
35+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C06-Supply-Chain.md",
36+
"cre_ids": ["613-285", "613-287", "863-521"]
37+
},
38+
{
39+
"section_id": "AISVS7",
40+
"section": "Model Behavior, Output Control & Safety Assurance",
41+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C07-Model-Behavior.md",
42+
"cre_ids": ["064-808", "141-555"]
43+
},
44+
{
45+
"section_id": "AISVS8",
46+
"section": "Memory, Embeddings & Vector Database Security",
47+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C08-Memory-Embeddings-and-Vector-Database.md",
48+
"cre_ids": ["126-668", "538-770"]
49+
},
50+
{
51+
"section_id": "AISVS9",
52+
"section": "Autonomous Orchestration & Agentic Action Security",
53+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C09-Orchestration-and-Agentic-Action.md",
54+
"cre_ids": ["117-371", "650-560"]
55+
},
56+
{
57+
"section_id": "AISVS10",
58+
"section": "Model Context Protocol (MCP) Security",
59+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C10-MCP-Security.md",
60+
"cre_ids": ["307-507", "715-223"]
61+
},
62+
{
63+
"section_id": "AISVS11",
64+
"section": "Adversarial Robustness & Privacy Defense",
65+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C11-Adversarial-Robustness.md",
66+
"cre_ids": ["141-555", "623-550"]
67+
},
68+
{
69+
"section_id": "AISVS12",
70+
"section": "Privacy Protection & Personal Data Management",
71+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C12-Privacy.md",
72+
"cre_ids": ["126-668", "227-045", "482-866"]
73+
},
74+
{
75+
"section_id": "AISVS13",
76+
"section": "Monitoring, Logging & Anomaly Detection",
77+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C13-Monitoring-and-Logging.md",
78+
"cre_ids": ["058-083", "148-420", "402-706", "843-841"]
79+
},
80+
{
81+
"section_id": "AISVS14",
82+
"section": "Human Oversight, Accountability & Governance",
83+
"hyperlink": "https://github.com/OWASP/AISVS/blob/main/1.0/en/0x10-C14-Human-Oversight.md",
84+
"cre_ids": ["162-655", "766-162"]
85+
}
86+
]

0 commit comments

Comments
 (0)