@runsec/mcp 1.0.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/dist/index.js +578 -0
- package/package.json +43 -0
- package/src/rules/data/rule-compliance-map.json +43563 -0
- package/src/rules/data/semgrep-rules/README-taint-overlays.md +21 -0
- package/src/rules/data/semgrep-rules/advanced-agent-cloud.yaml +802 -0
- package/src/rules/data/semgrep-rules/app-logic.yaml +445 -0
- package/src/rules/data/semgrep-rules/auth-keycloak.yaml +831 -0
- package/src/rules/data/semgrep-rules/browser-agent.yaml +260 -0
- package/src/rules/data/semgrep-rules/cloud-secrets.yaml +316 -0
- package/src/rules/data/semgrep-rules/csharp-dotnet.yaml +4864 -0
- package/src/rules/data/semgrep-rules/desktop-electron-pro.yaml +30 -0
- package/src/rules/data/semgrep-rules/desktop-vsto-suite.yaml +2759 -0
- package/src/rules/data/semgrep-rules/devops-security.yaml +393 -0
- package/src/rules/data/semgrep-rules/domain-access-management.yaml +1023 -0
- package/src/rules/data/semgrep-rules/domain-data-privacy.yaml +852 -0
- package/src/rules/data/semgrep-rules/domain-input-validation.yaml +2894 -0
- package/src/rules/data/semgrep-rules/domain-platform-hardening.yaml +1715 -0
- package/src/rules/data/semgrep-rules/ds-ml-security.yaml +2431 -0
- package/src/rules/data/semgrep-rules/fastapi-async.yaml +5953 -0
- package/src/rules/data/semgrep-rules/frontend-react.yaml +4035 -0
- package/src/rules/data/semgrep-rules/frontend-security.yaml +200 -0
- package/src/rules/data/semgrep-rules/go-core.yaml +4959 -0
- package/src/rules/data/semgrep-rules/hft-cpp-security.yaml +631 -0
- package/src/rules/data/semgrep-rules/infra-k8s-helm.yaml +4968 -0
- package/src/rules/data/semgrep-rules/integration-security.yaml +2362 -0
- package/src/rules/data/semgrep-rules/java-enterprise.yaml +14756 -0
- package/src/rules/data/semgrep-rules/java-spring.yaml +397 -0
- package/src/rules/data/semgrep-rules/license-compliance.yaml +186 -0
- package/src/rules/data/semgrep-rules/mobile-flutter.yaml +37 -0
- package/src/rules/data/semgrep-rules/mobile-security.yaml +721 -0
- package/src/rules/data/semgrep-rules/nodejs-nestjs.yaml +5164 -0
- package/src/rules/data/semgrep-rules/nodejs-security.yaml +326 -0
- package/src/rules/data/semgrep-rules/observability.yaml +381 -0
- package/src/rules/data/semgrep-rules/php-security.yaml +3601 -0
- package/src/rules/data/semgrep-rules/python-backend-pro.yaml +30 -0
- package/src/rules/data/semgrep-rules/python-django.yaml +181 -0
- package/src/rules/data/semgrep-rules/python-security.yaml +284 -0
- package/src/rules/data/semgrep-rules/ru-regulatory.yaml +496 -0
- package/src/rules/data/semgrep-rules/ruby-rails.yaml +3078 -0
- package/src/rules/data/semgrep-rules/rust-security.yaml +2701 -0
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: runsec.auth-keycloak.ak-001
|
|
3
|
+
metadata:
|
|
4
|
+
runsec_version: v1.0
|
|
5
|
+
confidence: |-
|
|
6
|
+
0.9
|
|
7
|
+
exploit_scenario: |-
|
|
8
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
9
|
+
fix_template: |-
|
|
10
|
+
from jose import jwt header = jwt.get_unverified_header(token) if header.get(\"alg\") not in {\"RS256\", \"ES256\", \"GOST3410\"}: raise ValueError(\"unsupported alg\") claims = jwt.decode( token, jwk, algorithms=[\"RS256\", \"ES256\", \"GOST3410\"], issuer=issuer_url, audience=client_id, options={\"verify_signature\": True}, ) # для контура Клинкера включить профиль российских криптоалгоритмов (ГОСТ)
|
|
11
|
+
pattern-either:
|
|
12
|
+
- pattern: |-
|
|
13
|
+
from jose import jwt
|
|
14
|
+
claims = jwt.decode(token, key="", algorithms=["none"])
|
|
15
|
+
# либо library defaults без allowlist alg
|
|
16
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-001\\b'
|
|
17
|
+
message: |-
|
|
18
|
+
RunSec Detection [AK-001]: Auth0 JWT Handbook, Validate JSON Web Tokens > Manually implement checks (disallow none)
|
|
19
|
+
languages:
|
|
20
|
+
- python
|
|
21
|
+
severity: WARNING
|
|
22
|
+
- id: runsec.auth-keycloak.ak-002
|
|
23
|
+
metadata:
|
|
24
|
+
runsec_version: v1.0
|
|
25
|
+
confidence: |-
|
|
26
|
+
0.9
|
|
27
|
+
exploit_scenario: |-
|
|
28
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
29
|
+
fix_template: |-
|
|
30
|
+
import jwt claims = jwt.decode( token, pub_key, algorithms=[\"RS256\", \"ES256\"], issuer=issuer_url, audience=client_id, options={\"verify_signature\": True, \"verify_exp\": True, \"verify_nbf\": True, \"verify_iat\": True}, )
|
|
31
|
+
pattern-either:
|
|
32
|
+
- pattern: |-
|
|
33
|
+
import jwt
|
|
34
|
+
claims = jwt.decode(token, pub_key, algorithms=["RS256"], options={"verify_signature": True, "verify_exp": True})
|
|
35
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-002\\b'
|
|
36
|
+
message: |-
|
|
37
|
+
RunSec Detection [AK-002]: Auth0 JWT Handbook, Validate JSON Web Tokens > Issuer Validation + Audience Validation
|
|
38
|
+
languages:
|
|
39
|
+
- python
|
|
40
|
+
severity: WARNING
|
|
41
|
+
- id: runsec.auth-keycloak.ak-003
|
|
42
|
+
metadata:
|
|
43
|
+
runsec_version: v1.0
|
|
44
|
+
confidence: |-
|
|
45
|
+
0.9
|
|
46
|
+
exploit_scenario: |-
|
|
47
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
48
|
+
fix_template: |-
|
|
49
|
+
header = jwt.get_unverified_header(token) kid = header.get(\"kid\") trusted_kids = {k[\"kid\"] for k in jwks[\"keys\"]} if kid not in trusted_kids: raise ValueError(\"untrusted kid\") jwk = next(k for k in jwks[\"keys\"] if k[\"kid\"] == kid) claims = jwt.decode(token, jwk, algorithms=[\"RS256\", \"ES256\"], issuer=issuer_url, audience=client_id)
|
|
50
|
+
pattern-either:
|
|
51
|
+
- pattern: |-
|
|
52
|
+
header = jwt.get_unverified_header(token)
|
|
53
|
+
jwk = jwks[header["kid"]]
|
|
54
|
+
claims = jwt.decode(token, jwk, algorithms=["RS256"])
|
|
55
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-003\\b'
|
|
56
|
+
message: |-
|
|
57
|
+
RunSec Detection [AK-003]: Auth0 JWT Handbook, Validate JSON Web Tokens > Key ID (kid) Header and JWKS Matching
|
|
58
|
+
languages:
|
|
59
|
+
- python
|
|
60
|
+
severity: WARNING
|
|
61
|
+
- id: runsec.auth-keycloak.ak-004
|
|
62
|
+
metadata:
|
|
63
|
+
runsec_version: v1.0
|
|
64
|
+
confidence: |-
|
|
65
|
+
0.9
|
|
66
|
+
exploit_scenario: |-
|
|
67
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
68
|
+
fix_template: |-
|
|
69
|
+
allowed_redirects = { \"https://app.example.com/oidc/callback\", \"https://admin.example.com/oidc/callback\", } if redirect_uri not in allowed_redirects: raise ValueError(\"redirect_uri mismatch\")
|
|
70
|
+
pattern-either:
|
|
71
|
+
- pattern: |-
|
|
72
|
+
allowed_redirects = ["https://app.example.com/*", "http://localhost/*"]
|
|
73
|
+
if redirect_uri.startswith("https://app.example.com/"):
|
|
74
|
+
pass
|
|
75
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-004\\b'
|
|
76
|
+
message: |-
|
|
77
|
+
RunSec Detection [AK-004]: RFC 6819, section 5.2.3.5
|
|
78
|
+
languages:
|
|
79
|
+
- python
|
|
80
|
+
severity: WARNING
|
|
81
|
+
- id: runsec.auth-keycloak.ak-005
|
|
82
|
+
metadata:
|
|
83
|
+
runsec_version: v1.0
|
|
84
|
+
confidence: |-
|
|
85
|
+
0.9
|
|
86
|
+
exploit_scenario: |-
|
|
87
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
88
|
+
fix_template: |-
|
|
89
|
+
import os from keycloak import KeycloakOpenID kc = KeycloakOpenID( server_url=os.environ[\"KEYCLOAK_URL\"], realm_name=os.environ[\"KEYCLOAK_REALM\"], client_id=os.environ[\"KEYCLOAK_CLIENT_ID\"], client_secret_key=os.environ[\"KEYCLOAK_CLIENT_SECRET\"], )
|
|
90
|
+
pattern-either:
|
|
91
|
+
- pattern: |-
|
|
92
|
+
from keycloak import KeycloakOpenID
|
|
93
|
+
kc = KeycloakOpenID(
|
|
94
|
+
server_url="https://id.example.com",
|
|
95
|
+
realm_name="prod",
|
|
96
|
+
client_id="backend",
|
|
97
|
+
client_secret_key="hardcoded-secret",
|
|
98
|
+
)
|
|
99
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-005\\b'
|
|
100
|
+
message: |-
|
|
101
|
+
RunSec Detection [AK-005]: RFC 6819, section 5.2.3.6; OAuth 2.0 (RFC 6749), section 10.1
|
|
102
|
+
languages:
|
|
103
|
+
- python
|
|
104
|
+
severity: WARNING
|
|
105
|
+
- id: runsec.auth-keycloak.ak-006
|
|
106
|
+
metadata:
|
|
107
|
+
runsec_version: v1.0
|
|
108
|
+
confidence: |-
|
|
109
|
+
0.9
|
|
110
|
+
exploit_scenario: |-
|
|
111
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
112
|
+
fix_template: |-
|
|
113
|
+
claims = jwt.decode(token, jwk, algorithms=[\"RS256\", \"ES256\"], issuer=issuer_url, audience=client_id, options={\"verify_exp\": True, \"verify_nbf\": True, \"verify_iat\": True}) user = db.get_user_by_id(current_user_id) if claims.get(\"sub\") != user.oidc_sub: raise ValueError(\"subject mismatch\")
|
|
114
|
+
pattern-either:
|
|
115
|
+
- pattern: |-
|
|
116
|
+
claims = jwt.decode(token, jwk, algorithms=["RS256"], issuer=issuer_url, audience=client_id)
|
|
117
|
+
user = db.get_user_by_email(claims.get("email"))
|
|
118
|
+
# sub не проверяется
|
|
119
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-006\\b'
|
|
120
|
+
message: |-
|
|
121
|
+
RunSec Detection [AK-006]: Auth0 JWT Handbook, Validate JSON Web Tokens > Validate claims
|
|
122
|
+
languages:
|
|
123
|
+
- python
|
|
124
|
+
severity: WARNING
|
|
125
|
+
- id: runsec.auth-keycloak.ak-007
|
|
126
|
+
metadata:
|
|
127
|
+
runsec_version: v1.0
|
|
128
|
+
confidence: |-
|
|
129
|
+
0.9
|
|
130
|
+
exploit_scenario: |-
|
|
131
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
132
|
+
fix_template: |-
|
|
133
|
+
assert request_client_id == stored_client_id_for_code(code) assert request_redirect_uri == stored_redirect_uri_for_code(code) token = exchange_code_for_token(code=code, client_id=request_client_id, redirect_uri=request_redirect_uri)
|
|
134
|
+
pattern-either:
|
|
135
|
+
- pattern: |-
|
|
136
|
+
token = exchange_code_for_token(code=code, client_id=client_id)
|
|
137
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-007\\b'
|
|
138
|
+
message: |-
|
|
139
|
+
RunSec Detection [AK-007]: RFC 6819, section 5.2.4.5
|
|
140
|
+
languages:
|
|
141
|
+
- python
|
|
142
|
+
severity: WARNING
|
|
143
|
+
- id: runsec.auth-keycloak.ak-008
|
|
144
|
+
metadata:
|
|
145
|
+
runsec_version: v1.0
|
|
146
|
+
confidence: |-
|
|
147
|
+
0.9
|
|
148
|
+
exploit_scenario: |-
|
|
149
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
150
|
+
fix_template: |-
|
|
151
|
+
claims = jwt.decode(token, jwk, algorithms=[\"RS256\", \"ES256\"], issuer=issuer_url, audience=client_id, options={\"verify_exp\": True, \"verify_nbf\": True, \"verify_iat\": True})
|
|
152
|
+
pattern-either:
|
|
153
|
+
- pattern: |-
|
|
154
|
+
claims = jwt.decode(token, jwk, algorithms=["RS256"], issuer=issuer_url, audience=client_id, options={"verify_exp": False, "verify_nbf": False, "verify_iat": False})
|
|
155
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-008\\b'
|
|
156
|
+
message: |-
|
|
157
|
+
RunSec Detection [AK-008]: Auth0 JWT Handbook, Validate JSON Web Tokens > JWT validation checks structure, claims, and signature
|
|
158
|
+
languages:
|
|
159
|
+
- python
|
|
160
|
+
severity: WARNING
|
|
161
|
+
- id: runsec.auth-keycloak.ak-009
|
|
162
|
+
metadata:
|
|
163
|
+
runsec_version: v1.0
|
|
164
|
+
confidence: |-
|
|
165
|
+
0.9
|
|
166
|
+
exploit_scenario: |-
|
|
167
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
168
|
+
fix_template: |-
|
|
169
|
+
auth_url = f"{issuer}/protocol/openid-connect/auth?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&code_challenge={code_challenge}&code_challenge_method=S256" token = exchange_code(code=code, code_verifier=code_verifier) if not code_verifier: raise ValueError("pkce required")
|
|
170
|
+
pattern-either:
|
|
171
|
+
- pattern: |-
|
|
172
|
+
auth_url = f"{issuer}/protocol/openid-connect/auth?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}"
|
|
173
|
+
# token exchange without code_verifier
|
|
174
|
+
token = exchange_code(code=code)
|
|
175
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-009\\b'
|
|
176
|
+
message: |-
|
|
177
|
+
RunSec Detection [AK-009]: FAPI 2.0 Security Profile; ГОСТ 57580.1 (IA); OAuth 2.1 Draft; OWASP ASVS v4.0.3
|
|
178
|
+
languages:
|
|
179
|
+
- python
|
|
180
|
+
severity: WARNING
|
|
181
|
+
- id: runsec.auth-keycloak.ak-010
|
|
182
|
+
metadata:
|
|
183
|
+
runsec_version: v1.0
|
|
184
|
+
confidence: |-
|
|
185
|
+
0.9
|
|
186
|
+
exploit_scenario: |-
|
|
187
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
188
|
+
fix_template: |-
|
|
189
|
+
def call_high_risk_api(access_token: str, dpop_proof: str): if not dpop_proof: raise ValueError("DPoP proof required") return client.post("/payments/transfer", headers={"Authorization": f"Bearer {access_token}", "DPoP": dpop_proof}) # DPoP обязателен для высокорисковых операций ЦБ, чтобы снизить риск кражи токенов
|
|
190
|
+
pattern-either:
|
|
191
|
+
- pattern: |-
|
|
192
|
+
def call_high_risk_api(access_token: str):
|
|
193
|
+
return client.post("/payments/transfer", headers={"Authorization": f"Bearer {access_token}"})
|
|
194
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-010\\b'
|
|
195
|
+
message: |-
|
|
196
|
+
RunSec Detection [AK-010]: FAPI 2.0 Security Profile; OAuth 2.1 Draft; OWASP ASVS v4.0.3
|
|
197
|
+
languages:
|
|
198
|
+
- python
|
|
199
|
+
severity: WARNING
|
|
200
|
+
- id: runsec.auth-keycloak.ak-011
|
|
201
|
+
metadata:
|
|
202
|
+
runsec_version: v1.0
|
|
203
|
+
confidence: |-
|
|
204
|
+
0.9
|
|
205
|
+
exploit_scenario: |-
|
|
206
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
207
|
+
fix_template: |-
|
|
208
|
+
payload = {"sub": user_id, "role": role, "scope": "api.read"} token = jwt.encode(payload, private_key, algorithm="RS256") # PII moved to userinfo endpoint or encrypted storage
|
|
209
|
+
pattern-either:
|
|
210
|
+
- pattern: |-
|
|
211
|
+
payload = {"sub": user_id, "email": email, "phone": phone, "name": full_name, "role": role}
|
|
212
|
+
token = jwt.encode(payload, private_key, algorithm="RS256")
|
|
213
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-011\\b'
|
|
214
|
+
message: |-
|
|
215
|
+
RunSec Detection [AK-011]: OAuth 2.1 Draft; OWASP ASVS v4.0.3
|
|
216
|
+
languages:
|
|
217
|
+
- python
|
|
218
|
+
severity: WARNING
|
|
219
|
+
- id: runsec.auth-keycloak.ak-012
|
|
220
|
+
metadata:
|
|
221
|
+
runsec_version: v1.0
|
|
222
|
+
confidence: |-
|
|
223
|
+
0.9
|
|
224
|
+
exploit_scenario: |-
|
|
225
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
226
|
+
fix_template: |-
|
|
227
|
+
def get_jwk_for_kid(kid: str): if kid in negative_kid_cache and not negative_kid_cache[kid].expired: raise ValueError("unknown kid cached") if not jwks_rate_limiter.allow("jwks_fetch"): raise RuntimeError("jwks rate limit exceeded") jwks = requests.get(f"{issuer}/.well-known/jwks.json", timeout=2).json() # cache keys and unknown kid misses return select_key_from_jwks(jwks, kid)
|
|
228
|
+
pattern-either:
|
|
229
|
+
- pattern: |-
|
|
230
|
+
def get_jwk_for_kid(kid: str):
|
|
231
|
+
# every unknown kid triggers upstream call
|
|
232
|
+
return requests.get(f"{issuer}/.well-known/jwks.json", timeout=2).json()
|
|
233
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-012\\b'
|
|
234
|
+
message: |-
|
|
235
|
+
RunSec Detection [AK-012]: OAuth 2.1 Draft; OWASP ASVS v4.0.3
|
|
236
|
+
languages:
|
|
237
|
+
- python
|
|
238
|
+
severity: WARNING
|
|
239
|
+
- id: runsec.auth-keycloak.ak-013
|
|
240
|
+
metadata:
|
|
241
|
+
runsec_version: v1.0
|
|
242
|
+
confidence: |-
|
|
243
|
+
0.9
|
|
244
|
+
exploit_scenario: |-
|
|
245
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
246
|
+
fix_template: |-
|
|
247
|
+
def exchange_token(user_jwt: str, audience: str) -> str: resp = requests.post(f"{issuer}/protocol/openid-connect/token", data={ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "subject_token": user_jwt, "subject_token_type": "urn:ietf:params:oauth:token-type:access_token", "requested_token_type": "urn:ietf:params:oauth:token-type:access_token", "audience": audience, }, auth=(client_id, client_secret), cert=(client_cert_path, client_key_path), timeout=5) resp.raise_for_status() return resp.json()["access_token"] def call_internal_service(user_jwt: str): svc_token = exchange_token(user_jwt, audience="orders-api") return requests.get("http://orders.internal/api/orders", headers={"Authorization": f"Bearer {svc_token}"}, timeout=5) # token exchange endpoint /token вызывать только по mTLS в профиле ФАПИ.ПАОК
|
|
248
|
+
pattern-either:
|
|
249
|
+
- pattern: |-
|
|
250
|
+
def call_internal_service(user_jwt: str):
|
|
251
|
+
return requests.get("http://orders.internal/api/orders", headers={"Authorization": f"Bearer {user_jwt}"})
|
|
252
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-013\\b'
|
|
253
|
+
message: |-
|
|
254
|
+
RunSec Detection [AK-013]: RFC 8693; FAPI 2.0 Security Profile
|
|
255
|
+
languages:
|
|
256
|
+
- python
|
|
257
|
+
severity: WARNING
|
|
258
|
+
- id: runsec.auth-keycloak.ak-014
|
|
259
|
+
metadata:
|
|
260
|
+
runsec_version: v1.0
|
|
261
|
+
confidence: |-
|
|
262
|
+
0.9
|
|
263
|
+
exploit_scenario: |-
|
|
264
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
265
|
+
fix_template: |-
|
|
266
|
+
token_req = { "grant_type": "authorization_code", "code": code, "redirect_uri": redirect_uri, "resource": "https://api.example.com/orders", } token = requests.post(token_url, data=token_req, auth=(client_id, client_secret), timeout=5) token.raise_for_status()
|
|
267
|
+
pattern-either:
|
|
268
|
+
- pattern: |-
|
|
269
|
+
token_req = {
|
|
270
|
+
"grant_type": "authorization_code",
|
|
271
|
+
"code": code,
|
|
272
|
+
"redirect_uri": redirect_uri,
|
|
273
|
+
}
|
|
274
|
+
token = requests.post(token_url, data=token_req, auth=(client_id, client_secret), timeout=5)
|
|
275
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-014\\b'
|
|
276
|
+
message: |-
|
|
277
|
+
RunSec Detection [AK-014]: RFC 8707; FAPI 2.0 Security Profile
|
|
278
|
+
languages:
|
|
279
|
+
- python
|
|
280
|
+
severity: WARNING
|
|
281
|
+
- id: runsec.auth-keycloak.ak-015
|
|
282
|
+
metadata:
|
|
283
|
+
runsec_version: v1.0
|
|
284
|
+
confidence: |-
|
|
285
|
+
0.9
|
|
286
|
+
exploit_scenario: |-
|
|
287
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
288
|
+
fix_template: |-
|
|
289
|
+
@app.get("/oidc/callback") async def callback(code: str, state: str, request: Request): expected = request.session.get("oidc_state") if not expected or state != expected: raise HTTPException(status_code=401, detail="invalid state") ... return await exchange_code(code)
|
|
290
|
+
pattern-either:
|
|
291
|
+
- pattern: |-
|
|
292
|
+
@app.get("/oidc/callback")
|
|
293
|
+
async def callback(code: str, state: str):
|
|
294
|
+
...
|
|
295
|
+
return await exchange_code(code)
|
|
296
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-015\\b'
|
|
297
|
+
message: |-
|
|
298
|
+
RunSec Detection [AK-015]: CWE-384
|
|
299
|
+
languages:
|
|
300
|
+
- python
|
|
301
|
+
severity: WARNING
|
|
302
|
+
- id: runsec.auth-keycloak.ak-016
|
|
303
|
+
metadata:
|
|
304
|
+
runsec_version: v1.0
|
|
305
|
+
confidence: |-
|
|
306
|
+
0.9
|
|
307
|
+
exploit_scenario: |-
|
|
308
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
309
|
+
fix_template: |-
|
|
310
|
+
id_claims = jwt.decode(id_token, jwk, algorithms=["RS256","ES256"], audience=client_id, issuer=issuer) expected_nonce = request.session.get("oidc_nonce") if not expected_nonce or id_claims.get("nonce") != expected_nonce: raise HTTPException(status_code=401, detail="invalid nonce") ... return id_claims
|
|
311
|
+
pattern-either:
|
|
312
|
+
- pattern: |-
|
|
313
|
+
id_claims = jwt.decode(id_token, jwk, algorithms=["RS256"], audience=client_id, issuer=issuer)
|
|
314
|
+
...
|
|
315
|
+
return id_claims
|
|
316
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-016\\b'
|
|
317
|
+
message: |-
|
|
318
|
+
RunSec Detection [AK-016]: CWE-346
|
|
319
|
+
languages:
|
|
320
|
+
- python
|
|
321
|
+
severity: WARNING
|
|
322
|
+
- id: runsec.auth-keycloak.ak-017
|
|
323
|
+
metadata:
|
|
324
|
+
runsec_version: v1.0
|
|
325
|
+
confidence: |-
|
|
326
|
+
0.9
|
|
327
|
+
exploit_scenario: |-
|
|
328
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
329
|
+
fix_template: |-
|
|
330
|
+
refresh_token_ttl = 86400 if refresh_token_ttl > 86400: raise ValueError("CB session limit exceeded") enable_backchannel_logout = True enable_frontchannel_logout = True revoke_refresh_token_on_logout = True
|
|
331
|
+
pattern-either:
|
|
332
|
+
- pattern: |-
|
|
333
|
+
refresh_token_ttl = 864000
|
|
334
|
+
# no back-channel/front-channel logout
|
|
335
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-017\\b'
|
|
336
|
+
message: |-
|
|
337
|
+
RunSec Detection [AK-017]: ГОСТ 57580.1 (IA); требования ЦБ по управлению сессиями
|
|
338
|
+
languages:
|
|
339
|
+
- python
|
|
340
|
+
severity: WARNING
|
|
341
|
+
- id: runsec.auth-keycloak.ak-018
|
|
342
|
+
metadata:
|
|
343
|
+
runsec_version: v1.0
|
|
344
|
+
confidence: |-
|
|
345
|
+
0.9
|
|
346
|
+
exploit_scenario: |-
|
|
347
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
348
|
+
fix_template: |-
|
|
349
|
+
Все межсервисные вызовы выполнять по mTLS (service identity, cert pinning, trust policy), не только token exchange endpoint.
|
|
350
|
+
pattern-either:
|
|
351
|
+
- pattern: |-
|
|
352
|
+
requests.get("http://orders.internal/api")
|
|
353
|
+
grpc.insecure_channel("billing.internal:50051")
|
|
354
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-018\\b'
|
|
355
|
+
message: |-
|
|
356
|
+
RunSec Detection [AK-018]: NIST SP 800-207 (Zero Trust)
|
|
357
|
+
languages:
|
|
358
|
+
- python
|
|
359
|
+
severity: WARNING
|
|
360
|
+
- id: runsec.auth-keycloak.ak-019
|
|
361
|
+
metadata:
|
|
362
|
+
runsec_version: v1.0
|
|
363
|
+
confidence: |-
|
|
364
|
+
0.9
|
|
365
|
+
exploit_scenario: |-
|
|
366
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
367
|
+
fix_template: |-
|
|
368
|
+
Для админ-учетных записей принудительная ротация клиентских секретов, короткий TTL сессий, step-up auth и немедленный revoke при logout/risk events.
|
|
369
|
+
pattern-either:
|
|
370
|
+
- pattern: |-
|
|
371
|
+
admin_session_ttl = 7*24*3600
|
|
372
|
+
admin_client_secret = "static-secret"
|
|
373
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-019\\b'
|
|
374
|
+
message: |-
|
|
375
|
+
RunSec Detection [AK-019]: OWASP ASVS v4.0 (L3), NIST 800-63
|
|
376
|
+
languages:
|
|
377
|
+
- python
|
|
378
|
+
severity: WARNING
|
|
379
|
+
- id: runsec.auth-keycloak.ak-020
|
|
380
|
+
metadata:
|
|
381
|
+
runsec_version: v1.0
|
|
382
|
+
confidence: |-
|
|
383
|
+
0.9
|
|
384
|
+
exploit_scenario: |-
|
|
385
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
386
|
+
fix_template: |-
|
|
387
|
+
Никогда не отключать проверку подписи; валидировать подпись JWT по JWKS и reject токены с invalid signature.
|
|
388
|
+
pattern-either:
|
|
389
|
+
- pattern: |-
|
|
390
|
+
jwt.decode(token, key, options={"verify_signature": False})
|
|
391
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-020\\b'
|
|
392
|
+
message: |-
|
|
393
|
+
RunSec Detection [AK-020]: CWE Final Certification
|
|
394
|
+
languages:
|
|
395
|
+
- python
|
|
396
|
+
severity: WARNING
|
|
397
|
+
- id: runsec.auth-keycloak.ak-021
|
|
398
|
+
metadata:
|
|
399
|
+
runsec_version: v1.0
|
|
400
|
+
confidence: |-
|
|
401
|
+
0.9
|
|
402
|
+
exploit_scenario: |-
|
|
403
|
+
Атакующий доставляет входные данные, соответствующие anti-pattern; реальный ущерб зависит от приёмника (sink), конфигурации и границ доверия.
|
|
404
|
+
fix_template: |-
|
|
405
|
+
Всегда указывать algorithms=["RS256"] (или строгий allowlist) и запрещать algorithm confusion/fallback.
|
|
406
|
+
pattern-either:
|
|
407
|
+
- pattern: |-
|
|
408
|
+
jwt.decode(token, key, audience=aud, issuer=iss)
|
|
409
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-021\\b'
|
|
410
|
+
message: |-
|
|
411
|
+
RunSec Detection [AK-021]: CWE Final Certification
|
|
412
|
+
languages:
|
|
413
|
+
- python
|
|
414
|
+
severity: WARNING
|
|
415
|
+
- id: runsec.auth-keycloak.ak-022
|
|
416
|
+
metadata:
|
|
417
|
+
runsec_version: v1.0
|
|
418
|
+
confidence: |-
|
|
419
|
+
0.9
|
|
420
|
+
exploit_scenario: |-
|
|
421
|
+
N/A
|
|
422
|
+
fix_template: |-
|
|
423
|
+
Rotate session identifiers after authentication.
|
|
424
|
+
pattern-either:
|
|
425
|
+
- pattern: |-
|
|
426
|
+
session.setAttribute("uid", uid)
|
|
427
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-022\\b'
|
|
428
|
+
message: |-
|
|
429
|
+
RunSec Detection [AK-022]: CWE-384
|
|
430
|
+
languages:
|
|
431
|
+
- python
|
|
432
|
+
severity: WARNING
|
|
433
|
+
- id: runsec.auth-keycloak.ak-023
|
|
434
|
+
metadata:
|
|
435
|
+
runsec_version: v1.0
|
|
436
|
+
confidence: |-
|
|
437
|
+
0.9
|
|
438
|
+
exploit_scenario: |-
|
|
439
|
+
N/A
|
|
440
|
+
fix_template: |-
|
|
441
|
+
Split pre-auth and post-auth cookie scopes.
|
|
442
|
+
pattern-either:
|
|
443
|
+
- pattern: |-
|
|
444
|
+
sid = request.cookies.get("AUTH_SESSION_ID")
|
|
445
|
+
response.set_cookie("AUTH_SESSION_ID", sid)
|
|
446
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-023\\b'
|
|
447
|
+
message: |-
|
|
448
|
+
RunSec Detection [AK-023]: CWE-384
|
|
449
|
+
languages:
|
|
450
|
+
- python
|
|
451
|
+
severity: WARNING
|
|
452
|
+
- id: runsec.auth-keycloak.ak-024
|
|
453
|
+
metadata:
|
|
454
|
+
runsec_version: v1.0
|
|
455
|
+
confidence: |-
|
|
456
|
+
0.9
|
|
457
|
+
exploit_scenario: |-
|
|
458
|
+
N/A
|
|
459
|
+
fix_template: |-
|
|
460
|
+
Enforce immediate refresh revocation.
|
|
461
|
+
pattern-either:
|
|
462
|
+
- pattern: |-
|
|
463
|
+
def logout(rt): pass # no revoke
|
|
464
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-024\\b'
|
|
465
|
+
message: |-
|
|
466
|
+
RunSec Detection [AK-024]: CWE-613
|
|
467
|
+
languages:
|
|
468
|
+
- python
|
|
469
|
+
severity: WARNING
|
|
470
|
+
- id: runsec.auth-keycloak.ak-025
|
|
471
|
+
metadata:
|
|
472
|
+
runsec_version: v1.0
|
|
473
|
+
confidence: |-
|
|
474
|
+
0.9
|
|
475
|
+
exploit_scenario: |-
|
|
476
|
+
N/A
|
|
477
|
+
fix_template: |-
|
|
478
|
+
Bind refresh lifecycle to one-time use.
|
|
479
|
+
pattern-either:
|
|
480
|
+
- pattern: |-
|
|
481
|
+
if validate(old_rt) or validate(new_rt): issue_token()
|
|
482
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-025\\b'
|
|
483
|
+
message: |-
|
|
484
|
+
RunSec Detection [AK-025]: CWE-294
|
|
485
|
+
languages:
|
|
486
|
+
- python
|
|
487
|
+
severity: WARNING
|
|
488
|
+
- id: runsec.auth-keycloak.ak-026
|
|
489
|
+
metadata:
|
|
490
|
+
runsec_version: v1.0
|
|
491
|
+
confidence: |-
|
|
492
|
+
0.9
|
|
493
|
+
exploit_scenario: |-
|
|
494
|
+
N/A
|
|
495
|
+
fix_template: |-
|
|
496
|
+
Add contextual token binding.
|
|
497
|
+
pattern-either:
|
|
498
|
+
- pattern: |-
|
|
499
|
+
token = sign({"u": username})
|
|
500
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-026\\b'
|
|
501
|
+
message: |-
|
|
502
|
+
RunSec Detection [AK-026]: CWE-384
|
|
503
|
+
languages:
|
|
504
|
+
- python
|
|
505
|
+
severity: WARNING
|
|
506
|
+
- id: runsec.auth-keycloak.ak-027
|
|
507
|
+
metadata:
|
|
508
|
+
runsec_version: v1.0
|
|
509
|
+
confidence: |-
|
|
510
|
+
0.9
|
|
511
|
+
exploit_scenario: |-
|
|
512
|
+
N/A
|
|
513
|
+
fix_template: |-
|
|
514
|
+
Cap absolute SSO session TTL.
|
|
515
|
+
pattern-either:
|
|
516
|
+
- pattern: |-
|
|
517
|
+
session.expires_at = now + idle_ttl # forever
|
|
518
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-027\\b'
|
|
519
|
+
message: |-
|
|
520
|
+
RunSec Detection [AK-027]: CWE-613
|
|
521
|
+
languages:
|
|
522
|
+
- python
|
|
523
|
+
severity: WARNING
|
|
524
|
+
- id: runsec.auth-keycloak.ak-028
|
|
525
|
+
metadata:
|
|
526
|
+
runsec_version: v1.0
|
|
527
|
+
confidence: |-
|
|
528
|
+
0.9
|
|
529
|
+
exploit_scenario: |-
|
|
530
|
+
N/A
|
|
531
|
+
fix_template: |-
|
|
532
|
+
Server controls all session identifiers.
|
|
533
|
+
pattern-either:
|
|
534
|
+
- pattern: |-
|
|
535
|
+
sid = request.cookies.get("JSESSIONID")
|
|
536
|
+
login_with_session(sid)
|
|
537
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-028\\b'
|
|
538
|
+
message: |-
|
|
539
|
+
RunSec Detection [AK-028]: CWE-384
|
|
540
|
+
languages:
|
|
541
|
+
- python
|
|
542
|
+
severity: WARNING
|
|
543
|
+
- id: runsec.auth-keycloak.ak-029
|
|
544
|
+
metadata:
|
|
545
|
+
runsec_version: v1.0
|
|
546
|
+
confidence: |-
|
|
547
|
+
0.9
|
|
548
|
+
exploit_scenario: |-
|
|
549
|
+
N/A
|
|
550
|
+
fix_template: |-
|
|
551
|
+
Scope refreshed tokens per resource.
|
|
552
|
+
pattern-either:
|
|
553
|
+
- pattern: |-
|
|
554
|
+
token = refresh(rt) # no aud check
|
|
555
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-029\\b'
|
|
556
|
+
message: |-
|
|
557
|
+
RunSec Detection [AK-029]: CWE-345
|
|
558
|
+
languages:
|
|
559
|
+
- python
|
|
560
|
+
severity: WARNING
|
|
561
|
+
- id: runsec.auth-keycloak.ak-030
|
|
562
|
+
metadata:
|
|
563
|
+
runsec_version: v1.0
|
|
564
|
+
confidence: |-
|
|
565
|
+
0.9
|
|
566
|
+
exploit_scenario: |-
|
|
567
|
+
N/A
|
|
568
|
+
fix_template: |-
|
|
569
|
+
Enforce single-session policy for privileged users.
|
|
570
|
+
pattern-either:
|
|
571
|
+
- pattern: |-
|
|
572
|
+
create_new_session(user)
|
|
573
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-030\\b'
|
|
574
|
+
message: |-
|
|
575
|
+
RunSec Detection [AK-030]: CWE-613
|
|
576
|
+
languages:
|
|
577
|
+
- python
|
|
578
|
+
severity: WARNING
|
|
579
|
+
- id: runsec.auth-keycloak.ak-031
|
|
580
|
+
metadata:
|
|
581
|
+
runsec_version: v1.0
|
|
582
|
+
confidence: |-
|
|
583
|
+
0.9
|
|
584
|
+
exploit_scenario: |-
|
|
585
|
+
N/A
|
|
586
|
+
fix_template: |-
|
|
587
|
+
Bind refresh tokens to originating client.
|
|
588
|
+
pattern-either:
|
|
589
|
+
- pattern: |-
|
|
590
|
+
refresh(rt, client_id=req.client_id)
|
|
591
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-031\\b'
|
|
592
|
+
message: |-
|
|
593
|
+
RunSec Detection [AK-031]: CWE-290
|
|
594
|
+
languages:
|
|
595
|
+
- python
|
|
596
|
+
severity: WARNING
|
|
597
|
+
- id: runsec.auth-keycloak.ak-032
|
|
598
|
+
metadata:
|
|
599
|
+
runsec_version: v1.0
|
|
600
|
+
confidence: |-
|
|
601
|
+
0.9
|
|
602
|
+
exploit_scenario: |-
|
|
603
|
+
N/A
|
|
604
|
+
fix_template: |-
|
|
605
|
+
Harden session cookies in all realms.
|
|
606
|
+
pattern-either:
|
|
607
|
+
- pattern: |-
|
|
608
|
+
set_cookie("SSO", sid)
|
|
609
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-032\\b'
|
|
610
|
+
message: |-
|
|
611
|
+
RunSec Detection [AK-032]: CWE-614
|
|
612
|
+
languages:
|
|
613
|
+
- python
|
|
614
|
+
severity: WARNING
|
|
615
|
+
- id: runsec.auth-keycloak.ak-033
|
|
616
|
+
metadata:
|
|
617
|
+
runsec_version: v1.0
|
|
618
|
+
confidence: |-
|
|
619
|
+
0.9
|
|
620
|
+
exploit_scenario: |-
|
|
621
|
+
N/A
|
|
622
|
+
fix_template: |-
|
|
623
|
+
Reject replayed token identifiers.
|
|
624
|
+
pattern-either:
|
|
625
|
+
- pattern: |-
|
|
626
|
+
if validate(rt): issue_access()
|
|
627
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-033\\b'
|
|
628
|
+
message: |-
|
|
629
|
+
RunSec Detection [AK-033]: CWE-294
|
|
630
|
+
languages:
|
|
631
|
+
- python
|
|
632
|
+
severity: WARNING
|
|
633
|
+
- id: runsec.auth-keycloak.ak-034
|
|
634
|
+
metadata:
|
|
635
|
+
runsec_version: v1.0
|
|
636
|
+
confidence: |-
|
|
637
|
+
0.9
|
|
638
|
+
exploit_scenario: |-
|
|
639
|
+
N/A
|
|
640
|
+
fix_template: |-
|
|
641
|
+
Isolate browser tab auth context.
|
|
642
|
+
pattern-either:
|
|
643
|
+
- pattern: |-
|
|
644
|
+
session["state"]=state
|
|
645
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-034\\b'
|
|
646
|
+
message: |-
|
|
647
|
+
RunSec Detection [AK-034]: CWE-384
|
|
648
|
+
languages:
|
|
649
|
+
- python
|
|
650
|
+
severity: WARNING
|
|
651
|
+
- id: runsec.auth-keycloak.ak-035
|
|
652
|
+
metadata:
|
|
653
|
+
runsec_version: v1.0
|
|
654
|
+
confidence: |-
|
|
655
|
+
0.9
|
|
656
|
+
exploit_scenario: |-
|
|
657
|
+
N/A
|
|
658
|
+
fix_template: |-
|
|
659
|
+
Force re-authentication after password updates.
|
|
660
|
+
pattern-either:
|
|
661
|
+
- pattern: |-
|
|
662
|
+
change_password(user, pwd)
|
|
663
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-035\\b'
|
|
664
|
+
message: |-
|
|
665
|
+
RunSec Detection [AK-035]: CWE-613
|
|
666
|
+
languages:
|
|
667
|
+
- python
|
|
668
|
+
severity: WARNING
|
|
669
|
+
- id: runsec.auth-keycloak.ak-036
|
|
670
|
+
metadata:
|
|
671
|
+
runsec_version: v1.0
|
|
672
|
+
confidence: |-
|
|
673
|
+
0.9
|
|
674
|
+
exploit_scenario: |-
|
|
675
|
+
N/A
|
|
676
|
+
fix_template: |-
|
|
677
|
+
Regenerate server session in broker flow.
|
|
678
|
+
pattern-either:
|
|
679
|
+
- pattern: |-
|
|
680
|
+
broker_callback(); login_success()
|
|
681
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-036\\b'
|
|
682
|
+
message: |-
|
|
683
|
+
RunSec Detection [AK-036]: CWE-384
|
|
684
|
+
languages:
|
|
685
|
+
- python
|
|
686
|
+
severity: WARNING
|
|
687
|
+
- id: runsec.auth-keycloak.ak-037
|
|
688
|
+
metadata:
|
|
689
|
+
runsec_version: v1.0
|
|
690
|
+
confidence: |-
|
|
691
|
+
0.9
|
|
692
|
+
exploit_scenario: |-
|
|
693
|
+
N/A
|
|
694
|
+
fix_template: |-
|
|
695
|
+
Policy-gate offline token issuance.
|
|
696
|
+
pattern-either:
|
|
697
|
+
- pattern: |-
|
|
698
|
+
issue_offline_token(client)
|
|
699
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-037\\b'
|
|
700
|
+
message: |-
|
|
701
|
+
RunSec Detection [AK-037]: CWE-250
|
|
702
|
+
languages:
|
|
703
|
+
- python
|
|
704
|
+
severity: WARNING
|
|
705
|
+
- id: runsec.auth-keycloak.ak-038
|
|
706
|
+
metadata:
|
|
707
|
+
runsec_version: v1.0
|
|
708
|
+
confidence: |-
|
|
709
|
+
0.9
|
|
710
|
+
exploit_scenario: |-
|
|
711
|
+
N/A
|
|
712
|
+
fix_template: |-
|
|
713
|
+
Normalize error and context behavior.
|
|
714
|
+
pattern-either:
|
|
715
|
+
- pattern: |-
|
|
716
|
+
return "user_not_found"
|
|
717
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-038\\b'
|
|
718
|
+
message: |-
|
|
719
|
+
RunSec Detection [AK-038]: CWE-203
|
|
720
|
+
languages:
|
|
721
|
+
- python
|
|
722
|
+
severity: WARNING
|
|
723
|
+
- id: runsec.auth-keycloak.ak-039
|
|
724
|
+
metadata:
|
|
725
|
+
runsec_version: v1.0
|
|
726
|
+
confidence: |-
|
|
727
|
+
0.9
|
|
728
|
+
exploit_scenario: |-
|
|
729
|
+
N/A
|
|
730
|
+
fix_template: |-
|
|
731
|
+
Add proof-of-possession for renewal.
|
|
732
|
+
pattern-either:
|
|
733
|
+
- pattern: |-
|
|
734
|
+
refresh(rt)
|
|
735
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-039\\b'
|
|
736
|
+
message: |-
|
|
737
|
+
RunSec Detection [AK-039]: CWE-287
|
|
738
|
+
languages:
|
|
739
|
+
- python
|
|
740
|
+
severity: WARNING
|
|
741
|
+
- id: runsec.auth-keycloak.ak-040
|
|
742
|
+
metadata:
|
|
743
|
+
runsec_version: v1.0
|
|
744
|
+
confidence: |-
|
|
745
|
+
0.9
|
|
746
|
+
exploit_scenario: |-
|
|
747
|
+
N/A
|
|
748
|
+
fix_template: |-
|
|
749
|
+
Re-authenticate before high-risk operations.
|
|
750
|
+
pattern-either:
|
|
751
|
+
- pattern: |-
|
|
752
|
+
perform_admin_action()
|
|
753
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-040\\b'
|
|
754
|
+
message: |-
|
|
755
|
+
RunSec Detection [AK-040]: CWE-306
|
|
756
|
+
languages:
|
|
757
|
+
- python
|
|
758
|
+
severity: WARNING
|
|
759
|
+
- id: runsec.auth-keycloak.ak-041
|
|
760
|
+
metadata:
|
|
761
|
+
runsec_version: v1.0
|
|
762
|
+
confidence: |-
|
|
763
|
+
0.9
|
|
764
|
+
exploit_scenario: |-
|
|
765
|
+
N/A
|
|
766
|
+
fix_template: |-
|
|
767
|
+
Enforce temporal validation window.
|
|
768
|
+
pattern-either:
|
|
769
|
+
- pattern: |-
|
|
770
|
+
if validate_sig(token): accept()
|
|
771
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-041\\b'
|
|
772
|
+
message: |-
|
|
773
|
+
RunSec Detection [AK-041]: CWE-345
|
|
774
|
+
languages:
|
|
775
|
+
- python
|
|
776
|
+
severity: WARNING
|
|
777
|
+
- id: runsec.auth-keycloak.ak-042
|
|
778
|
+
metadata:
|
|
779
|
+
runsec_version: v1.0
|
|
780
|
+
confidence: |-
|
|
781
|
+
0.9
|
|
782
|
+
exploit_scenario: |-
|
|
783
|
+
N/A
|
|
784
|
+
fix_template: |-
|
|
785
|
+
Rotate SID after external auth callback.
|
|
786
|
+
pattern-either:
|
|
787
|
+
- pattern: |-
|
|
788
|
+
handle_callback(); establish_session(old_sid)
|
|
789
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-042\\b'
|
|
790
|
+
message: |-
|
|
791
|
+
RunSec Detection [AK-042]: CWE-384
|
|
792
|
+
languages:
|
|
793
|
+
- python
|
|
794
|
+
severity: WARNING
|
|
795
|
+
- id: runsec.auth-keycloak.ak-043
|
|
796
|
+
metadata:
|
|
797
|
+
runsec_version: v1.0
|
|
798
|
+
confidence: |-
|
|
799
|
+
0.9
|
|
800
|
+
exploit_scenario: |-
|
|
801
|
+
N/A
|
|
802
|
+
fix_template: |-
|
|
803
|
+
Revoke refresh family on risk events.
|
|
804
|
+
pattern-either:
|
|
805
|
+
- pattern: |-
|
|
806
|
+
ctx = fingerprint(request)
|
|
807
|
+
refresh(rt, ctx)
|
|
808
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-043\\b'
|
|
809
|
+
message: |-
|
|
810
|
+
RunSec Detection [AK-043]: CWE-613
|
|
811
|
+
languages:
|
|
812
|
+
- python
|
|
813
|
+
severity: WARNING
|
|
814
|
+
- id: runsec.auth-keycloak.ak-044
|
|
815
|
+
metadata:
|
|
816
|
+
runsec_version: v1.0
|
|
817
|
+
confidence: |-
|
|
818
|
+
0.9
|
|
819
|
+
exploit_scenario: |-
|
|
820
|
+
N/A
|
|
821
|
+
fix_template: |-
|
|
822
|
+
Enforce replay-safe refresh identifiers.
|
|
823
|
+
pattern-either:
|
|
824
|
+
- pattern: |-
|
|
825
|
+
if validate_sig(rt): issue_new()
|
|
826
|
+
- pattern-regex: 'Vulnerable:\\s*AK\\-044\\b'
|
|
827
|
+
message: |-
|
|
828
|
+
RunSec Detection [AK-044]: CWE-345
|
|
829
|
+
languages:
|
|
830
|
+
- python
|
|
831
|
+
severity: WARNING
|