Metadata-Version: 2.4
Name: lasa
Version: 0.9.0
Summary: Lambda Attack Surface Analyzer — risk analysis for AWS Lambda packages. Zero pip dependencies.
Author-email: Lane Thompson <lane@apilify.com>
License: MIT
Project-URL: Homepage, https://github.com/Apilify/lasa
Project-URL: Methodology, https://github.com/Apilify/lasa/blob/main/docs/METHODOLOGY.md
Keywords: aws,lambda,supply-chain,security,risk,audit,sigv4
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Dynamic: license-file

# lasa — risk analysis for AWS Lambda packages

Analyze a Lambda's deployed bytes for supply-chain risk: third-party
dependencies, distinct PyPI maintainer accounts your code trusts, KEV-
listed CVEs in installed versions, and the declared AWS API surface
your handler actually calls.

Outputs a 0-100 score, a `catalog.conf`-shaped attack-surface listing,
and a punchy human-readable report.

```
$ lasa risk --aws-lambda my-handler --region us-east-1

Lambda: my_handler.handler  (semcom score: 94/100)
==================================================
Third-party code:  1.98 MB  (100% of deployed package)
First-party code:  6.5 KB  (111 LOC)

Top contributors:
  urllib3                    724.6 KB  1.26.15 · transitive · 2 maintainers
  idna                       464.8 KB  3.4 · transitive · 1 maintainers
  requests                   335.5 KB  2.28.1 · transitive · 2 maintainers
  certifi                    280.7 KB  2022.12.7 · transitive · 2 maintainers
  charset-normalizer         221.1 KB  2.1.1 · transitive · 1 maintainers

Reachable maintainers: 8 distinct PyPI accounts
KEV-listed affected:   0 installed versions (0 CVEs)
Declared AWS surface:  (none detected)

Score breakdown:
  Third-party bytes:   -2.0 points  (1.98 MB)
  Maintainers:         -4.0 points  (8 accounts)
  KEV CVEs:            -0.0 points  (0 affected)
  AWS API surface:     -0.0 points  (0 distinct)
                        --------
  Total penalty:       -6.0 points
  Score:                94 / 100
```

## What it analyzes

| Input | What it does |
|---|---|
| `path/to/lambda.zip` | Read the zip; analyze contents in-memory |
| `path/to/source/` | Walk the directory; same analysis as for a zip |
| `--aws-lambda <name>` | Fetch the deployed zip via boto3, then analyze |

## What the score means

The score combines four penalty axes (each capped at the value in
parens, total possible penalty = 100):

- **Third-party bytes** (cap 40) — every megabyte of vendored code is
  a megabyte you didn't audit.
- **Maintainers** (cap 20) — every distinct PyPI account that can push
  to a dependency is an account whose laptop, if compromised, ships
  to your prod.
- **KEV CVEs** (cap 20) — CVEs in CISA's [Known Exploited
  Vulnerabilities](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
  catalog. We surface only KEV-listed (not all advisories) — the floor
  below which "this is fine" stops being defensible.
- **AWS API surface** (cap 20) — every distinct (service, method) pair
  your code can reach is an action your IAM role must permit. Smaller
  surface ⇒ smaller blast radius if creds are compromised.

Full methodology: `docs/lasa/METHODOLOGY.md`.

## Subcommands

```
lasa analyze   <input>                emit raw analysis JSON
lasa catalog   <input> [--out FILE]   emit catalog.conf-shaped text
lasa risk      <input> [--json|--score-only]
lasa verify    <input> <catalog>      check source still implies catalog
lasa batch     [--region X]           leaderboard across an account
lasa ratchet   <new> --against <baseline>   CI gate: PR can't lower score
lasa version
```

## CI ratchet (GitHub Action)

Drop this in a PR workflow to make sure no one merges a regression:

```yaml
- uses: lanethompson/lasa@v0.7
  with:
    new: dist/lambda.zip
    baseline: baseline/lambda.zip   # checkout from main
    max-drop: 5                     # allow up to 5 pts of slip
    comment-on-pr: true             # posts the breakdown as a PR comment
```

The action exits non-zero (failing the PR check) when the new score
falls below the baseline minus `max-drop`, and posts a markdown
table comparing baseline vs new scores per axis. See
`.github/workflows/example-ratchet.yml` for a complete example.

`<input>` is one of: a path to a `.zip`, a path to a source directory,
or `--aws-lambda <name> [--region <region>] [--profile <profile>]`.

## Install

Requires Python 3.10+. **Zero pip dependencies** — stdlib only,
including SigV4 signing for the AWS Lambda API.

```bash
pip install lasa
lasa version
```

Or from source:

```bash
git clone https://github.com/Apilify/lasa
cd lasa
make install            # creates .venv, installs the package
.venv/bin/lasa version
```

The supply-chain claim we make about other people's Lambdas applies
to ourselves first: lasa has no third-party transitive dependencies
to be hijacked by the next worm. `pip install lasa` adds nothing to
your Python environment beyond lasa itself.

## Why catalog.conf

The catalog is **informational** — it describes what the code does
(detected from source), not what it's structurally constrained to do.
The catalog file is not enforced by the runtime; nothing prevents the
Lambda from doing things outside this list at runtime.

Catalog-disciplined deployments — where the catalog IS structurally
enforced by the linker / runtime — are a separate product. lasa
analyzes existing Python Lambdas; it does not transform them.

## Caching

PyPI maintainer counts and OSV vulnerability lookups are cached to
`~/.cache/semcom/` for 7 days. Override with `--no-cache` or
`--cache-ttl SECONDS`.

## Versioning

This is **v0.1**. The Python implementation is the *oracle* — it
defines the score and catalog format. v1 is Forth + dlsym; v2 is
verified IR caps. Field names and types in the JSON output are the
public ABI both later versions must match.

`lasa version` prints the implementation version + the methodology
version; the methodology version bumps whenever weights or rules
change.

## License

MIT.
