GHSA-g7p5-89mh-248h: Medium severity pip/lemur vulnerability

Published Aug 18, 2026
·
Updated

Summary

Repo under test: https://github.com/Netflix/lemur

When ADMINONLYAUTHORITYCREATION=False (an explicitly supported and documented configuration), POST /api/1/authorities with type=subca never verifies that the caller holds AuthorityPermission on the supplied parent authority. The parent field is resolved by AssociatedAuthoritySchema via a raw fetchobjects(Authority, data) lookup, then passed straight through service.create → mint → cryptography-issuer.createauthority, which loads options["parent"].authoritycertificate.privatekey and signs a brand-new intermediate CA on the caller's behalf.

Any authenticated non-read-only user can therefore mint a sub-CA chained to any internal root whose private key Lemur holds — including roots they hold no role on — attach a role they already belong to, and immediately issue or offline-sign trusted leaf certificates for arbitrary names.

Affected route

POST /api/1/authorities (with type=subca)

Affected code

- lemur/authorities/views.py:231 — gates only on AuthorityCreatorPermission() + StrictRolePermission(); no AuthorityPermission on data['parent'] - lemur/authorities/schemas.py:58 — parent = fields.Nested(AssociatedAuthoritySchema); validatesubca only checks presence - lemur/schemas.py:107 — AssociatedAuthoritySchema.getobject → fetchobjects(Authority, data) resolves any authority by id/name with no permission check - lemur/plugins/lemurcryptography/plugin.py:40 — privatekey = options["authority"].authoritycertificate.privatekey (set from options["parent"]) signs the new intermediate - lemur/auth/permissions.py:62 — AuthorityCreatorPermission becomes always-allow when ADMINONLYAUTHORITYCREATION=False - lemur/certificates/views.py:538 — isprivateauthority (true for cryptography-issuer) skips USERDOMAINAUTHORIZATIONPROVIDER for subsequent leaf issuance

Impact

In deployments that set ADMINONLYAUTHORITYCREATION=False to enable self-service CA creation, any authenticated non-read-only user — with zero permission on a given internal root CA — can obtain a working intermediate CA chained to that root. They can then:

- Issue TLS certificates for arbitrary names trusted by every relying party that trusts the internal root, bypassing LEMURALLOWEDDOMAINS, sensitive-domain flags, and the per-user domain-authorization plugin. - Export the sub-CA private key and sign end-entity certificates entirely outside Lemur, defeating all in-product issuance controls.

This converts "can create a self-contained test CA" into "can mint trusted certs under any internal PKI root in the organisation". The ADMINONLYAUTHORITYCREATION documentation does not warn operators of this consequence.

Root cause

AuthoritiesList.post evaluates AuthorityCreatorPermission (a global "may create authorities" flag) and StrictRolePermission, but never evaluates AuthorityPermission(parent.id, parent.roles) against the caller-supplied parent. AssociatedAuthoritySchema is a pure lookup schema with no authz hook, and neither authorities.service.create nor mint re-check before invoking issuerplugin.createauthority(options). The bundled cryptography-issuer then uses the parent's stored private key directly.

Validated evidence

Static trace, confirmed by code inspection (validation status: CONFIRMED):

- parent is loaded via AssociatedAuthoritySchema (raw fetchobjects), passed unchecked through views.post → service.create → mint → plugin.createauthority → issuecertificate, where the parent authority's stored private key is read and used to sign the new intermediate. - No call to AuthorityPermission(parent.id, ...) exists anywhere on this path. - Precondition ADMINONLYAUTHORITYCREATION=False is an explicitly supported config (docs/administration.rst:517).

Proof of concept / reproducer

Status: reconstructed from source report (static control-flow trace; not executed against a live CA).

Preconditions: ADMINONLYAUTHORITYCREATION=False; attacker is an authenticated Lemur user holding any role other than read-only; <PARENTAUTHORITYID> is any internal cryptography-issuer root CA the attacker holds no role on; <ATTACKERROLE> is any role the attacker already belongs to.

bash curl -sS -X POST "<TARGETBASEURL>/api/1/authorities" \ -H "Authorization: Bearer <AUTHTOKEN>" \ -H "Content-Type: application/json" \ -d '{ "name": "attacker-subca", "owner": "attacker@example.com", "description": "poc", "type": "subca", "parent": {"id": <PARENTAUTHORITYID>}, "plugin": {"slug": "cryptography-issuer"}, "roles": [{"name": "<ATTACKERROLE>"}], "commonName": "attacker-intermediate", "validityYears": 1 }'

The response contains a new authority whose authoritycertificate is signed by <PARENTAUTHORITYID>'s private key. The caller is recorded as creator and holds <ATTACKERROLE> on it, so POST /api/1/certificates against the new authority succeeds (and skips allowedissuancefordomain because isprivateauthority is true).

Static-trace validation command from the source report:

bash grep -n 'parent' lemur/authorities/schemas.py lemur/authorities/views.py lemur/authorities/service.py \ && sed -n '37,55p' lemur/plugins/lemurcryptography/plugin.py

Source artifact: audit/harnesses/public-repo-threat-model-harness/results/netflix-lemur-100run-mythos-20260627T051129Z/findings.jsonl (run022, finding cluster lemur-subca-parent-authz, 5/100 runs).

Suggested fix

In AuthoritiesList.post (or authorities.service.create), when data.get('parent') is present, enforce AuthorityPermission(parent.id, [r.name for r in parent.roles]).can() before invoking the issuer plugin, regardless of ADMINONLYAUTHORITYCREATION. Additionally, update the ADMINONLYAUTHORITYCREATION documentation to state that disabling it currently grants every authenticated user the ability to chain sub-CAs off any internal root whose private key Lemur holds. Consider also requiring admin (or an explicit per-parent capability) for any type=subca creation independent of the global flag.

Affected Software

1 affected componentFixes available
pip/lemur<=1.9.2
1.9.3

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade pip/lemur to a version that resolves this vulnerability.

    Fixed in 1.9.3
  2. Configuration

    Do not run with ADMIN_ONLY_AUTHORITY_CREATION=False. The material states that when ADMIN_ONLY_AUTHORITY_CREATION=False, any authenticated non-read-only user can create a sub-CA chained to any internal root whose private key Lemur holds, bypassing parent authority authorization. Set ADMIN_ONLY_AUTHORITY_CREATION=True to prevent this behavior.

    Lemur configuration ADMIN_ONLY_AUTHORITY_CREATION = true
  3. Configuration

    In AuthoritiesList.post (or authorities.service.create), when data.get('parent') is present and creating an authority of type=subca, enforce AuthorityPermission(parent.id, [r.name for r in parent.roles]).can() before invoking the issuer plugin (cryptography-issuer) and before minting/signing the new intermediate.

    Lemur authorities authorization AuthorityPermission(parent.id, [r.name for r in parent.roles]).can() gate for type=subca creation = enforced
  4. Configuration

    Update docs/administration.rst (referenced at lines around 517) to explicitly warn that disabling ADMIN_ONLY_AUTHORITY_CREATION currently allows every authenticated non-read-only user to chain sub-CAs off any internal root whose private key Lemur holds, even if they have no role/permission on that root.

    Lemur documentation ADMIN_ONLY_AUTHORITY_CREATION documentation warning = updated

Event History

Aug 18, 2026
Advisory Published
via GitHub·08:51 PM
Data Sourced
via GitHub·08:51 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Which Lemur deployments are exposed?

Deployments are exposed when ADMIN_ONLY_AUTHORITY_CREATION is set to False. This is an explicitly supported configuration, and the affected behavior is limited to POST requests to /api/1/authorities that create an authority with type=subca.

2

What level of access does an attacker need?

An attacker needs an authenticated account that is not read-only and can satisfy the authority-creation and strict-role checks. They do not need AuthorityPermission on the parent authority they select.

3

What can an attacker do after exploiting this?

A successful request can create a new intermediate CA chained to an internal root whose private key is held by Lemur, including a root the caller has no role on. The caller can attach a role they already belong to and use the resulting sub-CA to issue or offline-sign trusted leaf certificates for arbitrary names.

4

How can we determine whether we may already be affected?

Review whether ADMIN_ONLY_AUTHORITY_CREATION is False and whether non-read-only users can submit POST /api/1/authorities requests with type=subca. Also review created sub-CAs for parent authorities where the creator lacked AuthorityPermission, especially where the creator was assigned a role on the new authority.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203