cfn-lint-cfn-handler
A cfn-lint rule plugin for
projects using cfn-handler custom
resource handlers.
It catches misconfigurations specific to cfn-handler-based custom
resources — the kind of issues cfn-lint cannot know about generically
because they depend on knowing the consumer ships cfn-handler semantics.
0.x is pre-1.0; the rule set is still expanding. See the rule
catalogue below for what currently ships.
Install
pip install cfn-lint cfn-lint-cfn-handler
# or with uv
uv add cfn-lint-cfn-handler
Use
cfn-lint v1+ does not auto-discover plugins. Opt in explicitly via the
-a/--append-rules flag. Put the template path before -a, otherwise
argparse greedily absorbs it as another rule path:
cfn-lint template.yaml -a cfn_lint_cfn_handler.rules
Or in .cfnlintrc:
append_rules:
- cfn_lint_cfn_handler.rules
Rule catalogue
| ID | Severity | Description | Status |
|---|---|---|---|
E9101 |
Error | Custom resource references a Lambda whose Timeout is < 30 s (cfn-handler safety margin) |
shipping |
E9106 |
Error | Lambda Timeout exceeds custom resource ServiceTimeout — CFN gives up before Lambda finishes |
shipping |
E9108 |
Error | ServiceTimeout absent or > 900 s (Lambda's hard ceiling). Opt out per-resource for polling handlers. |
shipping |
E9102 |
Error | Polling-using handler has ServiceTimeout below a sensible polling minimum |
planned |
E9103 |
Error | Lambda lacks IAM permissions for events:* / lambda:*Permission when polling |
planned |
W9104 |
Warning | ServiceToken does not look like a Lambda Function ARN |
planned |
W9105 |
Warning | cfn-handler Layer ARN doesn't match the region the stack is being deployed to |
planned |
Severity is encoded by the first letter of the rule ID, per cfn-lint
convention (E* → error, W* → warning, I* → informational).
Configuring rules
Standard cfn-lint mechanisms work as expected. Mute a rule entirely via
.cfnlintrc:
ignore_checks:
- E9108
Or per-resource via the Metadata block (universal escape hatch — works
for any rule):
Resources:
MyCustomResource:
Type: Custom::LongRunningJob
Metadata:
cfn-lint:
config:
ignore_checks: [E9108]
Properties:
ServiceToken: !GetAtt Handler.Arn
ServiceTimeout: 3600
E9108 polling opt-in (recommended for polling handlers)
E9108 fires by default when ServiceTimeout is unset or above Lambda's
900 s ceiling. For polling-based custom resource handlers (which legitimately
need wall-clock windows beyond a single Lambda invocation), add the
polling: true marker per-resource:
Resources:
MyLongRunningResource:
Type: Custom::Provisioner
Metadata:
cfn-lint:
config:
configure_rules:
E9108:
polling: true
Properties:
ServiceToken: !GetAtt Handler.Arn
ServiceTimeout: 3600
For multiple polling resources, the template-level form is concise:
Metadata:
cfn-lint:
config:
configure_rules:
E9108:
polling_resources: [MyResource1, MyResource2]
The polling: true marker conveys intent — once polling-aware detection
lands (alongside E9102/E9103), the rule will validate the claim against
the Lambda's IAM perms.
To override a rule's severity, see cfn-lint's per-rule config.
Compatibility
- Python: 3.10+
- cfn-lint: 1.43+
Contributing
See CONTRIBUTING.md. Larger changes go through
the OpenSpec workflow in openspec/.
License
Metadata
Release files for cfn-lint-cfn-handler 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| cfn_lint_cfn_handler-0.2.0.tar.gz | 13.9 kB | With provenance | Details for cfn_lint_cfn_handler-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| cfn_lint_cfn_handler-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for cfn_lint_cfn_handler-0.2.0-py3-none-any.whl |
Total release size: 27.4 kB
Release files / cfn_lint_cfn_handler-0.2.0.tar.gz
| Download URL | cfn_lint_cfn_handler-0.2.0.tar.gz |
|---|---|
| Size | 13.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
11cf6606535300ceaae37e7c3a34ac8047bb1f2ce0511bda7598124c3a2c890c
|
|
BLAKE2b-256 checksum How to use checksums |
b9960af47944dc3ef1a7c6d08e7c23649fdb288f632bdb41693e3cc08fdffb0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 25, 2026.
Transparency logRelease files / cfn_lint_cfn_handler-0.2.0-py3-none-any.whl
| Download URL | cfn_lint_cfn_handler-0.2.0-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
40c68423cf44d2ca32ac7c58a71ea6f65759a9345f540acc70b91876fd274724
|
|
BLAKE2b-256 checksum How to use checksums |
d137a34dd9de615a668067abcfa4bc92a3d00cf2a3c8bc7e5cc27ee023cab3a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 25, 2026.
Transparency logSecurity for cfn-lint-cfn-handler 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for cfn_lint_cfn_handler-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 25, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.