feat: Implement Filesystem and MongoDB provenance writers for PackRun execution context
- Added `FilesystemPackRunProvenanceWriter` to write provenance manifests to the filesystem. - Introduced `MongoPackRunArtifactReader` to read artifacts from MongoDB. - Created `MongoPackRunProvenanceWriter` to store provenance manifests in MongoDB. - Developed unit tests for filesystem and MongoDB provenance writers. - Established `ITimelineEventStore` and `ITimelineIngestionService` interfaces for timeline event handling. - Implemented `TimelineIngestionService` to validate and persist timeline events with hashing. - Created PostgreSQL schema and migration scripts for timeline indexing. - Added dependency injection support for timeline indexer services. - Developed tests for timeline ingestion and schema validation.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "java-spring-deserialize:201",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Java deserialization sink reachable",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "JavaDeserialize::handleRequest",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"src/AppTest.java"
|
||||
],
|
||||
"coverage_files": []
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/upload",
|
||||
"App.handleRequest",
|
||||
"ObjectInputStream.readObject"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "No guard; base64 payload deserialized"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "java-spring-guarded:202",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Deserialization unreachable by default",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "JavaDeserializeGuarded::handleRequest",
|
||||
"label": "unreachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": ["src/AppTest.java"],
|
||||
"coverage_files": []
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/upload",
|
||||
"App.handleRequest",
|
||||
"guard: ALLOW_DESER!=true"
|
||||
]
|
||||
},
|
||||
"config_conditions": ["ALLOW_DESER == 'true'"]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "js-express-eval:003",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Admin eval reachable",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "ExpressEval::exec",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_reach.js"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/admin/exec",
|
||||
"createServer.exec",
|
||||
"eval(code)"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "No guard on admin path"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "js-express-guarded:004",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Admin exec unreachable when ALLOW_EXEC!=true",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "ExpressGuarded::exec",
|
||||
"label": "unreachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_unreachable.js"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/admin/exec",
|
||||
"createServer.exec",
|
||||
"guard: ALLOW_EXEC!=true"
|
||||
]
|
||||
},
|
||||
"config_conditions": [
|
||||
"ALLOW_EXEC == 'true'"
|
||||
],
|
||||
"notes": "Only reachable when ALLOW_EXEC=true"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "js-fastify-template:005",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Template rendering reachable",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "FastifyTemplate::render",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_reach.js"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/render",
|
||||
"createServer.render",
|
||||
"template replace"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "Simple template replace used as sink"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "js-guarded-eval:002",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Eval sink guarded by FEATURE_ENABLE; unreachable when flag off",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "GuardedEval::handleRequest",
|
||||
"label": "unreachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_unreachable.js"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/exec",
|
||||
"app.js::handleRequest",
|
||||
"guard: FEATURE_ENABLE != 1"
|
||||
]
|
||||
},
|
||||
"config_conditions": [
|
||||
"FEATURE_ENABLE == '1'"
|
||||
],
|
||||
"notes": "Sink only executes when FEATURE_ENABLE=1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "js-unsafe-eval:001",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Unsafe eval sink reachable via POST /api/exec",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "UnsafeEval::handleRequest",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_reach.js"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/exec",
|
||||
"app.js::handleRequest",
|
||||
"eval(code)"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "No guards; direct eval on user input"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "py-django-ssti:105",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Template rendering reachable (autoescape off)",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "DjangoSSTI::render",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_reach.py"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /render",
|
||||
"app.handle_request",
|
||||
"render"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "Autoescape disabled"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "py-fastapi-guarded:104",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Eval unreachable unless ALLOW_EXEC=true",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "FastApiGuarded::handle_request",
|
||||
"label": "unreachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_unreachable.py"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /exec",
|
||||
"app.handle_request",
|
||||
"guard: ALLOW_EXEC!=true"
|
||||
]
|
||||
},
|
||||
"config_conditions": [
|
||||
"ALLOW_EXEC == 'true'"
|
||||
],
|
||||
"notes": "Feature flag blocks sink by default"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "py-flask-template:103",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Template rendering reachable",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "FlaskTemplate::render",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_reach.py"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /render",
|
||||
"app.handle_request",
|
||||
"render"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "Simple template placeholder replacement"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "py-guarded-exec:102",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Eval unreachable unless FEATURE_ENABLE=1",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "PyGuardedExec::handle_request",
|
||||
"label": "unreachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_unreachable.py"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/exec",
|
||||
"app.handle_request",
|
||||
"guard: FEATURE_ENABLE != 1"
|
||||
]
|
||||
},
|
||||
"config_conditions": [
|
||||
"FEATURE_ENABLE == '1'"
|
||||
],
|
||||
"notes": "Feature flag required"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"cases": [
|
||||
{
|
||||
"case_id": "py-unsafe-exec:101",
|
||||
"case_version": "1.0.0",
|
||||
"notes": "Eval reachable",
|
||||
"sinks": [
|
||||
{
|
||||
"sink_id": "PyUnsafeExec::handle_request",
|
||||
"label": "reachable",
|
||||
"confidence": "high",
|
||||
"dynamic_evidence": {
|
||||
"covered_by_tests": [
|
||||
"tests/test_reach.py"
|
||||
],
|
||||
"coverage_files": [
|
||||
"outputs/coverage.json"
|
||||
]
|
||||
},
|
||||
"static_evidence": {
|
||||
"call_path": [
|
||||
"POST /api/exec",
|
||||
"app.handle_request",
|
||||
"eval(code)"
|
||||
]
|
||||
},
|
||||
"config_conditions": [],
|
||||
"notes": "No guards"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user