Skip to main content

SCP Linter

A command-line tool for validating AWS Service Control Policies (SCPs) to ensure correctness, security, and best practices.

Installation

pip install scp-lint

Or install from source:

git clone https://github.com/OnticX/scp-lint.git
cd scp-lint
pip install -e .

Usage

Lint a single SCP file:

scp-lint policy.json

Lint all JSON files in a directory:

scp-lint ./policies/

Example Output

============================================================
File: ./my-scp.json
Status: PASSED with warnings
============================================================

  WARNINGS (2):
    [W042] Unknown action: 's3:GetObjet'
           Location: Statement[0].Action[0]
           Suggestion: Did you mean: s3:GetObject?
    [W070] Invalid IP address or CIDR format: '999.999.999.999'
           Location: Statement[1].Condition.IpAddress.aws:SourceIp
           Suggestion: Use valid IPv4 (192.0.2.0/24) or IPv6 (2001:db8::/32) format

  INFO (1):
    [I031] Statement has no Sid (identifier)
           Location: Statement[0]
           Suggestion: Add a Sid for easier debugging and management

============================================================
SUMMARY
============================================================
  SCPs linted:    1
  Passed:         1
  Failed:         0
============================================================

Features

  • JSON Syntax Validation: Detects invalid JSON and file access errors
  • Policy Structure Checks: Flags missing Version/Statement fields, unknown top-level fields, and invalid Effect values
  • Size Limits: Errors for policies exceeding 5120 characters, warnings at 75% capacity
  • Statement Validation: Ensures required fields (Action, Effect) are present, rejects unsupported fields like Principal
  • Action Validation: Cross-references actions against an IAM reference database of 20,000+ actions, catching typos and providing "Did you mean?" suggestions
  • Condition Block Syntax: Validates operator structure, detects unknown operators, and flags empty conditions
  • Condition Key Validation: Verifies keys like aws:SourceIp exist, supports tag-based keys such as aws:RequestTag/*
  • Best Practices: Warns on blanket denies without conditions, service-wide denies, and Allow-only SCPs
  • Duplicate Detection: Identifies duplicate Sids and duplicate statements across your policy
  • IP Address Validation: Validates IPv4/IPv6 addresses and CIDR notation in IpAddress/NotIpAddress conditions
  • Date Format Validation: Validates date strings in DateEquals, DateLessThan, and other date condition operators
  • ARN Format Validation: Validates Resource ARN structure and partition values

Lint Rules

Errors (E-codes) - Invalid policies that will not work

Code Description
E001 File not found
E002 Cannot read file
E003 Invalid JSON syntax
E010 Policy exceeds 5120 character limit
E020 Missing Version field
E021 Missing Statement field
E022 Statement is not an object or array
E030 Statement is not an object
E031 Missing Effect field
E032 Invalid Effect value (must be Allow or Deny)
E033 Missing Action or NotAction field
E034 Principal/NotPrincipal not allowed in SCPs
E040 Action must be string or array
E041 Action array item is not a string
E050 Condition block must be an object
E051 Condition operator value must be an object
E052 Unknown condition operator

Warnings (W-codes) - Valid but potentially problematic

Code Description
W010 Policy is over 75% of size limit
W020 Unusual Version value
W021 Unknown top-level field
W030 Empty statements array
W031 More than 20 statements
W032 Unknown statement field
W040 Action missing service prefix
W041 Unknown service prefix
W042 Unknown action name (with suggestions)
W043 Unknown condition key
W044 Empty condition block
W045 Empty condition operator block
W046 Empty or null condition value
W050 Blanket Deny * without conditions
W051 Service-wide deny without conditions
W060 Duplicate Sid found in multiple statements
W061 Duplicate statements (identical Effect, Action, Resource, Condition)
W070 Invalid IP address or CIDR format
W071 Invalid date format
W080 Invalid ARN format

Info (I-codes) - Best practice suggestions

Code Description
I030 No Resource specified (defaults to *)
I031 No Sid specified
I050 Policy contains only Allow statements
W090 Statement uses NotAction (inverse logic)
W091 Statement uses NotResource (inverse logic)

GitHub Actions Integration

Add SCP linting to your CI/CD pipeline:

name: SCP Lint

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      - name: Install scp-lint
        run: pip install scp-lint
      - name: Lint SCPs
        run: scp-lint ./policies/

License

MIT - See LICENSE for details.

Metadata

Release files for scp-lint 0.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for scp-lint 0.2.3
File Size Uploaded Provenance
scp_lint-0.2.3.tar.gz 229.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for scp-lint 0.2.3
File Interpreter ABI Platform
scp_lint-0.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 457.5 kB

Release files / scp_lint-0.2.3.tar.gz

Download URL scp_lint-0.2.3.tar.gz
Size 229.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d0014ccac3fdeb9f6b573f2891cb2aeb033bb558a96aaf3dc8c11b0159c7af0b
BLAKE2b-256 checksum
How to use checksums
1320950871349487850d39cb945031c72be0841189d2f9444b29ce64262adbcc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Release files / scp_lint-0.2.3-py3-none-any.whl

Download URL scp_lint-0.2.3-py3-none-any.whl
Size 228.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
61e3c7b3b0e1a3f4e2c4031316439723ecb78894cc470f70df5c16cc7efdf8c6
BLAKE2b-256 checksum
How to use checksums
527ffe773e85c2d3c0cde50586a8e27a547e0f283f243cdeea04ce7512b9ce3f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.2

Security for scp-lint 0.2.3

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A 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.

Release history Release notifications | RSS feed

This release

0.2.3 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page