@hoanghainh/komagu 2.5.0 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/ai-run-stats.json +87 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/auth-model.md +120 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/index.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/injection-001.json +383 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/injection-002.json +205 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/privilege-001.json +838 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/privilege-002.json +124 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-001.json +778 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-002.json +546 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-003.json +661 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-004.json +659 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-005.json +612 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/batches/routes-006.json +106 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/coverage.json +19 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-001.json +516 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-002.json +332 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-003.json +218 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-004.json +561 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-005.json +316 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/bola-routes-006.json +14 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/inj-injection-001.json +782 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/inj-injection-002.json +418 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/priv-privilege-001.json +627 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/priv-privilege-002.json +253 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-1.json +68 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-10.json +68 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-11.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-12.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-13.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-14.json +66 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-15.json +69 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-16.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-17.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-18.json +69 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-19.json +64 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-2.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-20.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-21.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-22.json +50 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-3.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-4.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-5.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-6.json +70 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-7.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-8.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings/verified-9.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/findings.json +4857 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/mass-assignment.candidates.json +232 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/report.ja.md +2112 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/report.md +2112 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-001.json +425 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-002.json +333 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-003.json +400 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-004.json +403 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-005.json +398 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/routes/routes-006.json +63 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/score.json +82 -0
- package/assess/lsa/examples/eval-run-6/gptoss-a/stack-profile.json +225 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/ai-run-stats.json +91 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/auth-model.md +120 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/index.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/injection-001.json +383 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/injection-002.json +205 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/privilege-001.json +838 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/privilege-002.json +124 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-001.json +778 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-002.json +546 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-003.json +661 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-004.json +659 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-005.json +612 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/batches/routes-006.json +106 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/coverage.json +21 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-001.json +593 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-002.json +367 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-003.json +207 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-004.json +477 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-005.json +341 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/bola-routes-006.json +14 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/inj-injection-001.json +821 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/inj-injection-002.json +410 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/priv-privilege-001.json +649 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/priv-privilege-002.json +222 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-1.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-10.json +67 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-11.json +68 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-12.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-13.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-14.json +64 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-15.json +70 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-16.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-17.json +61 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-18.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-19.json +65 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-2.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-20.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-21.json +62 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-22.json +50 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-3.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-4.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-5.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-6.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-7.json +64 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-8.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings/verified-9.json +60 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/findings.json +4966 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/mass-assignment.candidates.json +232 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-001.json +425 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-002.json +333 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-003.json +400 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-004.json +403 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-005.json +398 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/routes/routes-006.json +63 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/score.json +87 -0
- package/assess/lsa/examples/eval-run-6/gptoss-b/stack-profile.json +225 -0
- package/assess/lsa/examples/eval-run-6/ground-truth.json +851 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/ai-run-stats.json +96 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/auth-model.md +191 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/index.json +60 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/injection-001.json +383 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/injection-002.json +205 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/privilege-001.json +838 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/privilege-002.json +124 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-001.json +778 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-002.json +546 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-003.json +661 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-004.json +659 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-005.json +612 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/batches/routes-006.json +106 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/coverage.json +31 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-001.json +527 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-002.json +568 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-003.json +467 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-004.json +342 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-005.json +693 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/bola-routes-006.json +16 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/inj-injection-001.json +1123 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/inj-injection-002.json +391 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/priv-privilege-001.json +726 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/priv-privilege-002.json +306 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-1.json +137 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-10.json +106 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-11.json +81 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-12.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-13.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-14.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-15.json +110 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-16.json +116 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-17.json +141 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-18.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-19.json +140 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-2.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-20.json +82 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-21.json +74 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-22.json +99 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-3.json +140 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-4.json +145 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-5.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-6.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-7.json +87 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-8.json +125 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings/verified-9.json +135 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/findings.json +6989 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/mass-assignment.candidates.json +232 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/memory.log +36 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-001.json +425 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-002.json +333 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-003.json +400 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-004.json +403 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-005.json +398 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/routes/routes-006.json +63 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/score.json +106 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-nothink/stack-profile.json +225 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/auth-model.md +517 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-001.json +5 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-002.json +428 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-003.json +388 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-004.json +463 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-005.json +5 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/bola-routes-006.json +67 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings/inj-injection-001.json +964 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/findings.partial.json +1872 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/memory.log +194 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/score.partial.json +108 -0
- package/assess/lsa/examples/eval-run-6/qwen-16k-partial/stack-profile.json +225 -0
- package/assess/lsa/scripts/laravel_routes.py +102 -0
- package/assess/lsa/scripts/map_routes.py +4 -1
- package/assess/lsa/tests/EVAL-RESULTS.md +126 -0
- package/assess/lsa/tests/test_eval_run_6.py +104 -0
- package/assess/lsa/tests/test_laravel_routes.py +95 -0
- package/examples/member-portal/backend-dotnet/Auth/DemoAuthenticationHandler.cs +75 -0
- package/examples/member-portal/backend-dotnet/Program.cs +1 -72
- package/examples/member-portal/backend-spring/src/main/kotlin/io/komagu/portal/Application.kt +4 -0
- package/examples/member-portal/backend-spring/src/main/kotlin/io/komagu/portal/controller/Controllers.kt +3 -0
- package/examples/member-portal/backend-spring/src/main/kotlin/io/komagu/portal/model/Entities.kt +4 -0
- package/examples/member-portal/tests/test_d6_demo_app.py +4 -4
- package/examples/member-portal/tests/test_d6_remediation_verification.py +6 -6
- package/operate/ai/client.py +27 -10
- package/operate/ai/runner.py +4 -2
- package/operate/cli/__init__.py +1 -1
- package/operate/cli/commands/scan.py +8 -1
- package/operate/cross_user_tester/runner.py +4 -1
- package/operate/devsecops/sbom.py +12 -4
- package/operate/simulate/scenarios.py +11 -2
- package/operate/tests/test_ai_reasoning_effort.py +65 -0
- package/operate/tests/test_ai_route_inventory.py +53 -0
- package/operate/tests/test_audit_minimum_versions.py +89 -0
- package/operate/tests/test_cli.py +1 -1
- package/operate/tests/test_scheme_and_xml_guards.py +67 -0
- package/package.json +1 -1
- package/remediate/authz/dotnet/src/Komagu.Security.Authorization/LoggingSecurityAuditSink.cs +19 -3
- package/remediate/authz/golang/authz_test.go +5 -2
- package/remediate/authz/spring/src/main/kotlin/io/komagu/security/authorization/DefaultKomaguSecurityManager.kt +74 -78
- package/remediate/authz/spring/src/main/kotlin/io/komagu/security/spring/OwnershipAspect.kt +129 -158
- package/remediate/deps/patcher.py +2 -1
- package/remediate/edge/mock-backend/app.py +2 -1
- package/remediate/edge/tests/test_edge_security.py +5 -5
- package/remediate/ekyc/requirements.txt +1 -1
- package/remediate/identity/dotnet/src/Komagu.Security.Identity/OidcServiceCollectionExtensions.cs +19 -6
- package/remediate/identity/python/requirements.txt +2 -2
- package/remediate/identity/spring/src/main/kotlin/io/komagu/security/identity/KomaguIdentityAutoConfiguration.kt +31 -38
- package/remediate/legacy_shims/tests/test_legacy_shims.py +8 -8
- package/remediate/query/dotnet/src/Komagu.Security.Query/SafeSortAllowList.cs +5 -2
- package/remediate/query/spring/src/main/kotlin/io/komagu/security/query/SafeSortAllowList.kt +10 -11
- package/remediate/query/spring/src/main/kotlin/io/komagu/security/query/detekt/StringBuiltSqlQueryRule.kt +19 -24
|
@@ -47,46 +47,12 @@ class KomaguIdentityAutoConfiguration {
|
|
|
47
47
|
else -> ""
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
check(properties.audience.isNotBlank()) { "komagu.security.oidc.audience must not be blank" }
|
|
51
|
+
check(properties.clockSkewSeconds in 0L..120L) {
|
|
52
|
+
"komagu.security.oidc.clock-skew-seconds must be between 0 and 120 (got ${properties.clockSkewSeconds})"
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
|
|
55
|
-
throw IllegalStateException(
|
|
56
|
-
"komagu.security.oidc.clock-skew-seconds must be between 0 and 120 (got ${properties.clockSkewSeconds})"
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
val jwkUri = properties.jwkSetUri?.trim()
|
|
61
|
-
val decoder: NimbusJwtDecoder = when {
|
|
62
|
-
!jwkUri.isNullOrBlank() -> {
|
|
63
|
-
if (effectiveIssuer.isBlank()) {
|
|
64
|
-
throw IllegalStateException("komagu.security.oidc.issuer must not be blank")
|
|
65
|
-
}
|
|
66
|
-
if (!properties.allowInsecureHttpJwks && !jwkUri.lowercase().startsWith("https://")) {
|
|
67
|
-
throw IllegalStateException(
|
|
68
|
-
"komagu.security.oidc.jwk-set-uri must use HTTPS ($jwkUri). " +
|
|
69
|
-
"Set komagu.security.oidc.allow-insecure-http-jwks=true only for testing."
|
|
70
|
-
)
|
|
71
|
-
}
|
|
72
|
-
NimbusJwtDecoder.withJwkSetUri(jwkUri).build()
|
|
73
|
-
}
|
|
74
|
-
effectiveIssuer.isNotBlank() -> {
|
|
75
|
-
if (!properties.allowInsecureHttpJwks && !effectiveIssuer.lowercase().startsWith("https://")) {
|
|
76
|
-
throw IllegalStateException(
|
|
77
|
-
"OIDC issuer URI must use HTTPS ($effectiveIssuer). " +
|
|
78
|
-
"Set komagu.security.oidc.allow-insecure-http-jwks=true only for testing."
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
NimbusJwtDecoder.withIssuerLocation(effectiveIssuer).build()
|
|
82
|
-
}
|
|
83
|
-
else -> {
|
|
84
|
-
throw IllegalStateException(
|
|
85
|
-
"Either komagu.security.oidc.jwk-set-uri or komagu.security.oidc.issuer " +
|
|
86
|
-
"(or spring.security.oauth2.resourceserver.jwt.issuer-uri) must be configured"
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
55
|
+
val decoder = buildDecoder(properties, effectiveIssuer)
|
|
90
56
|
|
|
91
57
|
val expirationValidator = KomaguExpirationValidator()
|
|
92
58
|
val timestampValidator = JwtTimestampValidator(Duration.ofSeconds(properties.clockSkewSeconds))
|
|
@@ -106,6 +72,33 @@ class KomaguIdentityAutoConfiguration {
|
|
|
106
72
|
return decoder
|
|
107
73
|
}
|
|
108
74
|
|
|
75
|
+
private fun buildDecoder(properties: KomaguOidcProperties, effectiveIssuer: String): NimbusJwtDecoder {
|
|
76
|
+
val jwkUri = properties.jwkSetUri?.trim()
|
|
77
|
+
return when {
|
|
78
|
+
!jwkUri.isNullOrBlank() -> {
|
|
79
|
+
check(effectiveIssuer.isNotBlank()) { "komagu.security.oidc.issuer must not be blank" }
|
|
80
|
+
check(properties.allowInsecureHttpJwks || isHttps(jwkUri)) {
|
|
81
|
+
"komagu.security.oidc.jwk-set-uri must use HTTPS ($jwkUri). " +
|
|
82
|
+
"Set komagu.security.oidc.allow-insecure-http-jwks=true only for testing."
|
|
83
|
+
}
|
|
84
|
+
NimbusJwtDecoder.withJwkSetUri(jwkUri).build()
|
|
85
|
+
}
|
|
86
|
+
effectiveIssuer.isNotBlank() -> {
|
|
87
|
+
check(properties.allowInsecureHttpJwks || isHttps(effectiveIssuer)) {
|
|
88
|
+
"OIDC issuer URI must use HTTPS ($effectiveIssuer). " +
|
|
89
|
+
"Set komagu.security.oidc.allow-insecure-http-jwks=true only for testing."
|
|
90
|
+
}
|
|
91
|
+
NimbusJwtDecoder.withIssuerLocation(effectiveIssuer).build()
|
|
92
|
+
}
|
|
93
|
+
else -> error(
|
|
94
|
+
"Either komagu.security.oidc.jwk-set-uri or komagu.security.oidc.issuer " +
|
|
95
|
+
"(or spring.security.oauth2.resourceserver.jwt.issuer-uri) must be configured"
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private fun isHttps(uri: String): Boolean = uri.lowercase().startsWith("https://")
|
|
101
|
+
|
|
109
102
|
@Bean
|
|
110
103
|
@ConditionalOnMissingBean(SecurityFilterChain::class)
|
|
111
104
|
fun komaguSecurityFilterChain(
|
|
@@ -222,23 +222,23 @@ public class OwnershipEnforcerBehaviouralTest {
|
|
|
222
222
|
def test_php_shim_behavioural_execution(self) -> None:
|
|
223
223
|
"""Verify PHP shim behavioral normalization and denial with SQLite in-memory PDO."""
|
|
224
224
|
php_file = SHIMS_ROOT / "php" / "komagu_authz_shim.php"
|
|
225
|
-
php_test_script =
|
|
226
|
-
require_once '
|
|
225
|
+
php_test_script = """
|
|
226
|
+
require_once '__PHP_FILE__';
|
|
227
227
|
|
|
228
228
|
// 1. Test komagu_normalize_id
|
|
229
229
|
assert(komagu_normalize_id(1) === 1);
|
|
230
230
|
assert(komagu_normalize_id('42') === 42);
|
|
231
231
|
|
|
232
232
|
$invalidIds = [null, '', false, true, 0, '0', -1, '-5', '007', '1e2', '0x5', '1.5'];
|
|
233
|
-
foreach ($invalidIds as $inv) {
|
|
234
|
-
try {
|
|
233
|
+
foreach ($invalidIds as $inv) {
|
|
234
|
+
try {
|
|
235
235
|
komagu_normalize_id($inv);
|
|
236
236
|
echo "FAIL: Expected exception for " . var_export($inv, true) . "\\n";
|
|
237
237
|
exit(1);
|
|
238
|
-
}
|
|
238
|
+
} catch (InvalidArgumentException $e) {
|
|
239
239
|
// Expected
|
|
240
|
-
}
|
|
241
|
-
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
242
|
|
|
243
243
|
// 2. Test komagu_check_ownership with SQLite in-memory PDO
|
|
244
244
|
$pdo = new PDO('sqlite::memory:');
|
|
@@ -258,7 +258,7 @@ public class OwnershipEnforcerBehaviouralTest {
|
|
|
258
258
|
assert(komagu_check_ownership($pdo, 'orders', 'id', '', 'user_id', 100, $allowed) === false);
|
|
259
259
|
|
|
260
260
|
echo "ALL_PHP_BEHAVIOURAL_TESTS_PASSED\\n";
|
|
261
|
-
"""
|
|
261
|
+
""".replace("__PHP_FILE__", str(php_file)) # nosec B608 # PHP test script with a fixed repo path, not a query
|
|
262
262
|
proc = subprocess.run(
|
|
263
263
|
["php", "-r", php_test_script],
|
|
264
264
|
capture_output=True,
|
|
@@ -16,9 +16,9 @@ public enum SortDirection
|
|
|
16
16
|
/// Strict allow-list validator for dynamic column names and sort clauses.
|
|
17
17
|
/// Prevents SQL injection via dynamic ORDER BY clauses.
|
|
18
18
|
/// </summary>
|
|
19
|
-
public sealed class SafeSortAllowList
|
|
19
|
+
public sealed partial class SafeSortAllowList
|
|
20
20
|
{
|
|
21
|
-
private static readonly Regex SafeIdentifierRegex =
|
|
21
|
+
private static readonly Regex SafeIdentifierRegex = SafeIdentifier();
|
|
22
22
|
private readonly HashSet<string> _allowedColumns;
|
|
23
23
|
|
|
24
24
|
public SafeSortAllowList(IEnumerable<string> allowedColumns)
|
|
@@ -73,4 +73,7 @@ public sealed class SafeSortAllowList
|
|
|
73
73
|
var dirString = direction == SortDirection.Descending ? "DESC" : "ASC";
|
|
74
74
|
return $"{validColumn} {dirString}";
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
[GeneratedRegex("^[a-zA-Z_][a-zA-Z0-9_]*$")]
|
|
78
|
+
private static partial Regex SafeIdentifier();
|
|
76
79
|
}
|
package/remediate/query/spring/src/main/kotlin/io/komagu/security/query/SafeSortAllowList.kt
CHANGED
|
@@ -25,18 +25,17 @@ class SafeSortAllowList(allowedColumns: Collection<String>) {
|
|
|
25
25
|
* Throws SecurityException on validation failure.
|
|
26
26
|
*/
|
|
27
27
|
fun validateColumnName(columnName: String?): String {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!safeIdentifierRegex.matches(trimmed)) {
|
|
35
|
-
throw SecurityException("Potential SQL injection detected in sort column: '$columnName'. Illegal characters detected.")
|
|
36
|
-
}
|
|
28
|
+
val trimmed = columnName?.trim().orEmpty()
|
|
29
|
+
val isIdentifier = trimmed.isNotEmpty() && safeIdentifierRegex.matches(trimmed)
|
|
30
|
+
val canonical = if (isIdentifier) allowedMap[trimmed.lowercase()] else null
|
|
31
|
+
return canonical ?: throw SecurityException(rejectionReason(columnName, trimmed))
|
|
32
|
+
}
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
private fun rejectionReason(columnName: String?, trimmed: String): String = when {
|
|
35
|
+
trimmed.isEmpty() -> "Sort column name cannot be null or blank"
|
|
36
|
+
!safeIdentifierRegex.matches(trimmed) ->
|
|
37
|
+
"Potential SQL injection detected in sort column: '$columnName'. Illegal characters detected."
|
|
38
|
+
else -> "Unauthorized sort column requested: '$columnName'. Column is not in allowed list."
|
|
40
39
|
}
|
|
41
40
|
|
|
42
41
|
/**
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
package io.komagu.security.query.detekt
|
|
2
2
|
|
|
3
|
-
import io.gitlab.arturbosch.detekt.api
|
|
3
|
+
import io.gitlab.arturbosch.detekt.api.CodeSmell
|
|
4
|
+
import io.gitlab.arturbosch.detekt.api.Config
|
|
5
|
+
import io.gitlab.arturbosch.detekt.api.Debt
|
|
6
|
+
import io.gitlab.arturbosch.detekt.api.Entity
|
|
7
|
+
import io.gitlab.arturbosch.detekt.api.Issue
|
|
8
|
+
import io.gitlab.arturbosch.detekt.api.Rule
|
|
9
|
+
import io.gitlab.arturbosch.detekt.api.Severity
|
|
4
10
|
import org.jetbrains.kotlin.lexer.KtTokens
|
|
5
11
|
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
|
6
12
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
|
@@ -33,37 +39,26 @@ class StringBuiltSqlQueryRule(config: Config = Config.empty) : Rule(config) {
|
|
|
33
39
|
override fun visitCallExpression(expression: KtCallExpression) {
|
|
34
40
|
super.visitCallExpression(expression)
|
|
35
41
|
|
|
36
|
-
val callee = expression.calleeExpression?.text
|
|
37
|
-
|
|
42
|
+
val callee = expression.calleeExpression?.text
|
|
43
|
+
val firstArg = expression.valueArguments.firstOrNull()?.getArgumentExpression()
|
|
44
|
+
if (callee == null || callee !in targetSqlMethods || firstArg == null) {
|
|
38
45
|
return
|
|
39
46
|
}
|
|
40
47
|
|
|
41
|
-
val
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
// 1. String template with variable interpolation: "SELECT * FROM orders WHERE id = $orderId"
|
|
49
|
-
if (firstArg is KtStringTemplateExpression && firstArg.hasInterpolation()) {
|
|
50
|
-
report(
|
|
51
|
-
CodeSmell(
|
|
52
|
-
issue = issue,
|
|
53
|
-
entity = Entity.from(firstArg),
|
|
54
|
-
message = "SQL/JPQL query in '$callee' uses string template interpolation. All parameters must be passed as parameterized bindings."
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
return
|
|
48
|
+
val construction = when {
|
|
49
|
+
// 1. String template with variable interpolation: "SELECT * FROM orders WHERE id = $orderId"
|
|
50
|
+
firstArg is KtStringTemplateExpression && firstArg.hasInterpolation() -> "uses string template interpolation"
|
|
51
|
+
// 2. Binary string concatenation: "SELECT * FROM orders WHERE id = " + orderId
|
|
52
|
+
firstArg is KtBinaryExpression && firstArg.operationToken == KtTokens.PLUS ->
|
|
53
|
+
"is built using binary string concatenation (+)"
|
|
54
|
+
else -> null
|
|
58
55
|
}
|
|
59
|
-
|
|
60
|
-
// 2. Binary string concatenation: "SELECT * FROM orders WHERE id = " + orderId
|
|
61
|
-
if (firstArg is KtBinaryExpression && firstArg.operationToken == KtTokens.PLUS) {
|
|
56
|
+
if (construction != null) {
|
|
62
57
|
report(
|
|
63
58
|
CodeSmell(
|
|
64
59
|
issue = issue,
|
|
65
60
|
entity = Entity.from(firstArg),
|
|
66
|
-
message = "SQL/JPQL query in '$callee'
|
|
61
|
+
message = "SQL/JPQL query in '$callee' $construction. All parameters must be passed as parameterized bindings."
|
|
67
62
|
)
|
|
68
63
|
)
|
|
69
64
|
}
|