lasa 0.9.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. lasa-0.9.0/LICENSE +21 -0
  2. lasa-0.9.0/PKG-INFO +184 -0
  3. lasa-0.9.0/README.md +155 -0
  4. lasa-0.9.0/lasa/__init__.py +11 -0
  5. lasa-0.9.0/lasa/__main__.py +9 -0
  6. lasa-0.9.0/lasa/aws.py +354 -0
  7. lasa-0.9.0/lasa/batch.py +237 -0
  8. lasa-0.9.0/lasa/cache.py +48 -0
  9. lasa-0.9.0/lasa/catalog.py +82 -0
  10. lasa-0.9.0/lasa/cli.py +312 -0
  11. lasa-0.9.0/lasa/enrich/__init__.py +0 -0
  12. lasa-0.9.0/lasa/enrich/kev.py +29 -0
  13. lasa-0.9.0/lasa/enrich/npm.py +109 -0
  14. lasa-0.9.0/lasa/enrich/observations.py +168 -0
  15. lasa-0.9.0/lasa/enrich/osv.py +79 -0
  16. lasa-0.9.0/lasa/enrich/pypi.py +138 -0
  17. lasa-0.9.0/lasa/enrich/runtime_eol.py +88 -0
  18. lasa-0.9.0/lasa/extract/__init__.py +0 -0
  19. lasa-0.9.0/lasa/extract/aws_calls.py +301 -0
  20. lasa-0.9.0/lasa/extract/aws_calls_node.py +166 -0
  21. lasa-0.9.0/lasa/extract/aws_input.py +64 -0
  22. lasa-0.9.0/lasa/extract/capabilities.py +346 -0
  23. lasa-0.9.0/lasa/extract/deps.py +207 -0
  24. lasa-0.9.0/lasa/extract/dir_input.py +39 -0
  25. lasa-0.9.0/lasa/extract/imports.py +46 -0
  26. lasa-0.9.0/lasa/extract/node_deps.py +131 -0
  27. lasa-0.9.0/lasa/extract/zip_input.py +27 -0
  28. lasa-0.9.0/lasa/fixtures/__init__.py +0 -0
  29. lasa-0.9.0/lasa/fixtures/kev_known_exploited.json +15 -0
  30. lasa-0.9.0/lasa/fixtures/modular_alternatives.json +43 -0
  31. lasa-0.9.0/lasa/fixtures/refresh_kev.py +29 -0
  32. lasa-0.9.0/lasa/identity.py +62 -0
  33. lasa-0.9.0/lasa/models.py +76 -0
  34. lasa-0.9.0/lasa/net.py +63 -0
  35. lasa-0.9.0/lasa/pipeline.py +321 -0
  36. lasa-0.9.0/lasa/ratchet.py +149 -0
  37. lasa-0.9.0/lasa/report.py +247 -0
  38. lasa-0.9.0/lasa/score.py +88 -0
  39. lasa-0.9.0/lasa/tests/__init__.py +0 -0
  40. lasa-0.9.0/lasa/tests/fixtures/__init__.py +0 -0
  41. lasa-0.9.0/lasa/tests/fixtures/build_fixtures.py +161 -0
  42. lasa-0.9.0/lasa/tests/fixtures/typical_node_lambda.zip +0 -0
  43. lasa-0.9.0/lasa/tests/fixtures/typical_python_lambda.zip +0 -0
  44. lasa-0.9.0/lasa/tests/fixtures/verified_reference_lambda.zip +0 -0
  45. lasa-0.9.0/lasa/tests/test_aws.py +184 -0
  46. lasa-0.9.0/lasa/tests/test_aws_calls.py +271 -0
  47. lasa-0.9.0/lasa/tests/test_aws_calls_node.py +115 -0
  48. lasa-0.9.0/lasa/tests/test_batch.py +81 -0
  49. lasa-0.9.0/lasa/tests/test_capabilities.py +232 -0
  50. lasa-0.9.0/lasa/tests/test_cli.py +120 -0
  51. lasa-0.9.0/lasa/tests/test_deps.py +131 -0
  52. lasa-0.9.0/lasa/tests/test_enrich_offline.py +116 -0
  53. lasa-0.9.0/lasa/tests/test_integration_zip.py +134 -0
  54. lasa-0.9.0/lasa/tests/test_layers.py +137 -0
  55. lasa-0.9.0/lasa/tests/test_node_deps.py +96 -0
  56. lasa-0.9.0/lasa/tests/test_observations.py +133 -0
  57. lasa-0.9.0/lasa/tests/test_ratchet.py +144 -0
  58. lasa-0.9.0/lasa/tests/test_score.py +184 -0
  59. lasa-0.9.0/lasa.egg-info/PKG-INFO +184 -0
  60. lasa-0.9.0/lasa.egg-info/SOURCES.txt +64 -0
  61. lasa-0.9.0/lasa.egg-info/dependency_links.txt +1 -0
  62. lasa-0.9.0/lasa.egg-info/entry_points.txt +2 -0
  63. lasa-0.9.0/lasa.egg-info/requires.txt +3 -0
  64. lasa-0.9.0/lasa.egg-info/top_level.txt +1 -0
  65. lasa-0.9.0/pyproject.toml +50 -0
  66. lasa-0.9.0/setup.cfg +4 -0
lasa-0.9.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 apilify
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
lasa-0.9.0/PKG-INFO ADDED
@@ -0,0 +1,184 @@
1
+ Metadata-Version: 2.4
2
+ Name: lasa
3
+ Version: 0.9.0
4
+ Summary: Lambda Attack Surface Analyzer — risk analysis for AWS Lambda packages. Zero pip dependencies.
5
+ Author-email: Lane Thompson <lane@apilify.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Apilify/lasa
8
+ Project-URL: Methodology, https://github.com/Apilify/lasa/blob/main/docs/METHODOLOGY.md
9
+ Keywords: aws,lambda,supply-chain,security,risk,audit,sigv4
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Dynamic: license-file
29
+
30
+ # lasa — risk analysis for AWS Lambda packages
31
+
32
+ Analyze a Lambda's deployed bytes for supply-chain risk: third-party
33
+ dependencies, distinct PyPI maintainer accounts your code trusts, KEV-
34
+ listed CVEs in installed versions, and the declared AWS API surface
35
+ your handler actually calls.
36
+
37
+ Outputs a 0-100 score, a `catalog.conf`-shaped attack-surface listing,
38
+ and a punchy human-readable report.
39
+
40
+ ```
41
+ $ lasa risk --aws-lambda my-handler --region us-east-1
42
+
43
+ Lambda: my_handler.handler (semcom score: 94/100)
44
+ ==================================================
45
+ Third-party code: 1.98 MB (100% of deployed package)
46
+ First-party code: 6.5 KB (111 LOC)
47
+
48
+ Top contributors:
49
+ urllib3 724.6 KB 1.26.15 · transitive · 2 maintainers
50
+ idna 464.8 KB 3.4 · transitive · 1 maintainers
51
+ requests 335.5 KB 2.28.1 · transitive · 2 maintainers
52
+ certifi 280.7 KB 2022.12.7 · transitive · 2 maintainers
53
+ charset-normalizer 221.1 KB 2.1.1 · transitive · 1 maintainers
54
+
55
+ Reachable maintainers: 8 distinct PyPI accounts
56
+ KEV-listed affected: 0 installed versions (0 CVEs)
57
+ Declared AWS surface: (none detected)
58
+
59
+ Score breakdown:
60
+ Third-party bytes: -2.0 points (1.98 MB)
61
+ Maintainers: -4.0 points (8 accounts)
62
+ KEV CVEs: -0.0 points (0 affected)
63
+ AWS API surface: -0.0 points (0 distinct)
64
+ --------
65
+ Total penalty: -6.0 points
66
+ Score: 94 / 100
67
+ ```
68
+
69
+ ## What it analyzes
70
+
71
+ | Input | What it does |
72
+ |---|---|
73
+ | `path/to/lambda.zip` | Read the zip; analyze contents in-memory |
74
+ | `path/to/source/` | Walk the directory; same analysis as for a zip |
75
+ | `--aws-lambda <name>` | Fetch the deployed zip via boto3, then analyze |
76
+
77
+ ## What the score means
78
+
79
+ The score combines four penalty axes (each capped at the value in
80
+ parens, total possible penalty = 100):
81
+
82
+ - **Third-party bytes** (cap 40) — every megabyte of vendored code is
83
+ a megabyte you didn't audit.
84
+ - **Maintainers** (cap 20) — every distinct PyPI account that can push
85
+ to a dependency is an account whose laptop, if compromised, ships
86
+ to your prod.
87
+ - **KEV CVEs** (cap 20) — CVEs in CISA's [Known Exploited
88
+ Vulnerabilities](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
89
+ catalog. We surface only KEV-listed (not all advisories) — the floor
90
+ below which "this is fine" stops being defensible.
91
+ - **AWS API surface** (cap 20) — every distinct (service, method) pair
92
+ your code can reach is an action your IAM role must permit. Smaller
93
+ surface ⇒ smaller blast radius if creds are compromised.
94
+
95
+ Full methodology: `docs/lasa/METHODOLOGY.md`.
96
+
97
+ ## Subcommands
98
+
99
+ ```
100
+ lasa analyze <input> emit raw analysis JSON
101
+ lasa catalog <input> [--out FILE] emit catalog.conf-shaped text
102
+ lasa risk <input> [--json|--score-only]
103
+ lasa verify <input> <catalog> check source still implies catalog
104
+ lasa batch [--region X] leaderboard across an account
105
+ lasa ratchet <new> --against <baseline> CI gate: PR can't lower score
106
+ lasa version
107
+ ```
108
+
109
+ ## CI ratchet (GitHub Action)
110
+
111
+ Drop this in a PR workflow to make sure no one merges a regression:
112
+
113
+ ```yaml
114
+ - uses: lanethompson/lasa@v0.7
115
+ with:
116
+ new: dist/lambda.zip
117
+ baseline: baseline/lambda.zip # checkout from main
118
+ max-drop: 5 # allow up to 5 pts of slip
119
+ comment-on-pr: true # posts the breakdown as a PR comment
120
+ ```
121
+
122
+ The action exits non-zero (failing the PR check) when the new score
123
+ falls below the baseline minus `max-drop`, and posts a markdown
124
+ table comparing baseline vs new scores per axis. See
125
+ `.github/workflows/example-ratchet.yml` for a complete example.
126
+
127
+ `<input>` is one of: a path to a `.zip`, a path to a source directory,
128
+ or `--aws-lambda <name> [--region <region>] [--profile <profile>]`.
129
+
130
+ ## Install
131
+
132
+ Requires Python 3.10+. **Zero pip dependencies** — stdlib only,
133
+ including SigV4 signing for the AWS Lambda API.
134
+
135
+ ```bash
136
+ pip install lasa
137
+ lasa version
138
+ ```
139
+
140
+ Or from source:
141
+
142
+ ```bash
143
+ git clone https://github.com/Apilify/lasa
144
+ cd lasa
145
+ make install # creates .venv, installs the package
146
+ .venv/bin/lasa version
147
+ ```
148
+
149
+ The supply-chain claim we make about other people's Lambdas applies
150
+ to ourselves first: lasa has no third-party transitive dependencies
151
+ to be hijacked by the next worm. `pip install lasa` adds nothing to
152
+ your Python environment beyond lasa itself.
153
+
154
+ ## Why catalog.conf
155
+
156
+ The catalog is **informational** — it describes what the code does
157
+ (detected from source), not what it's structurally constrained to do.
158
+ The catalog file is not enforced by the runtime; nothing prevents the
159
+ Lambda from doing things outside this list at runtime.
160
+
161
+ Catalog-disciplined deployments — where the catalog IS structurally
162
+ enforced by the linker / runtime — are a separate product. lasa
163
+ analyzes existing Python Lambdas; it does not transform them.
164
+
165
+ ## Caching
166
+
167
+ PyPI maintainer counts and OSV vulnerability lookups are cached to
168
+ `~/.cache/semcom/` for 7 days. Override with `--no-cache` or
169
+ `--cache-ttl SECONDS`.
170
+
171
+ ## Versioning
172
+
173
+ This is **v0.1**. The Python implementation is the *oracle* — it
174
+ defines the score and catalog format. v1 is Forth + dlsym; v2 is
175
+ verified IR caps. Field names and types in the JSON output are the
176
+ public ABI both later versions must match.
177
+
178
+ `lasa version` prints the implementation version + the methodology
179
+ version; the methodology version bumps whenever weights or rules
180
+ change.
181
+
182
+ ## License
183
+
184
+ MIT.
lasa-0.9.0/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # lasa — risk analysis for AWS Lambda packages
2
+
3
+ Analyze a Lambda's deployed bytes for supply-chain risk: third-party
4
+ dependencies, distinct PyPI maintainer accounts your code trusts, KEV-
5
+ listed CVEs in installed versions, and the declared AWS API surface
6
+ your handler actually calls.
7
+
8
+ Outputs a 0-100 score, a `catalog.conf`-shaped attack-surface listing,
9
+ and a punchy human-readable report.
10
+
11
+ ```
12
+ $ lasa risk --aws-lambda my-handler --region us-east-1
13
+
14
+ Lambda: my_handler.handler (semcom score: 94/100)
15
+ ==================================================
16
+ Third-party code: 1.98 MB (100% of deployed package)
17
+ First-party code: 6.5 KB (111 LOC)
18
+
19
+ Top contributors:
20
+ urllib3 724.6 KB 1.26.15 · transitive · 2 maintainers
21
+ idna 464.8 KB 3.4 · transitive · 1 maintainers
22
+ requests 335.5 KB 2.28.1 · transitive · 2 maintainers
23
+ certifi 280.7 KB 2022.12.7 · transitive · 2 maintainers
24
+ charset-normalizer 221.1 KB 2.1.1 · transitive · 1 maintainers
25
+
26
+ Reachable maintainers: 8 distinct PyPI accounts
27
+ KEV-listed affected: 0 installed versions (0 CVEs)
28
+ Declared AWS surface: (none detected)
29
+
30
+ Score breakdown:
31
+ Third-party bytes: -2.0 points (1.98 MB)
32
+ Maintainers: -4.0 points (8 accounts)
33
+ KEV CVEs: -0.0 points (0 affected)
34
+ AWS API surface: -0.0 points (0 distinct)
35
+ --------
36
+ Total penalty: -6.0 points
37
+ Score: 94 / 100
38
+ ```
39
+
40
+ ## What it analyzes
41
+
42
+ | Input | What it does |
43
+ |---|---|
44
+ | `path/to/lambda.zip` | Read the zip; analyze contents in-memory |
45
+ | `path/to/source/` | Walk the directory; same analysis as for a zip |
46
+ | `--aws-lambda <name>` | Fetch the deployed zip via boto3, then analyze |
47
+
48
+ ## What the score means
49
+
50
+ The score combines four penalty axes (each capped at the value in
51
+ parens, total possible penalty = 100):
52
+
53
+ - **Third-party bytes** (cap 40) — every megabyte of vendored code is
54
+ a megabyte you didn't audit.
55
+ - **Maintainers** (cap 20) — every distinct PyPI account that can push
56
+ to a dependency is an account whose laptop, if compromised, ships
57
+ to your prod.
58
+ - **KEV CVEs** (cap 20) — CVEs in CISA's [Known Exploited
59
+ Vulnerabilities](https://www.cisa.gov/known-exploited-vulnerabilities-catalog)
60
+ catalog. We surface only KEV-listed (not all advisories) — the floor
61
+ below which "this is fine" stops being defensible.
62
+ - **AWS API surface** (cap 20) — every distinct (service, method) pair
63
+ your code can reach is an action your IAM role must permit. Smaller
64
+ surface ⇒ smaller blast radius if creds are compromised.
65
+
66
+ Full methodology: `docs/lasa/METHODOLOGY.md`.
67
+
68
+ ## Subcommands
69
+
70
+ ```
71
+ lasa analyze <input> emit raw analysis JSON
72
+ lasa catalog <input> [--out FILE] emit catalog.conf-shaped text
73
+ lasa risk <input> [--json|--score-only]
74
+ lasa verify <input> <catalog> check source still implies catalog
75
+ lasa batch [--region X] leaderboard across an account
76
+ lasa ratchet <new> --against <baseline> CI gate: PR can't lower score
77
+ lasa version
78
+ ```
79
+
80
+ ## CI ratchet (GitHub Action)
81
+
82
+ Drop this in a PR workflow to make sure no one merges a regression:
83
+
84
+ ```yaml
85
+ - uses: lanethompson/lasa@v0.7
86
+ with:
87
+ new: dist/lambda.zip
88
+ baseline: baseline/lambda.zip # checkout from main
89
+ max-drop: 5 # allow up to 5 pts of slip
90
+ comment-on-pr: true # posts the breakdown as a PR comment
91
+ ```
92
+
93
+ The action exits non-zero (failing the PR check) when the new score
94
+ falls below the baseline minus `max-drop`, and posts a markdown
95
+ table comparing baseline vs new scores per axis. See
96
+ `.github/workflows/example-ratchet.yml` for a complete example.
97
+
98
+ `<input>` is one of: a path to a `.zip`, a path to a source directory,
99
+ or `--aws-lambda <name> [--region <region>] [--profile <profile>]`.
100
+
101
+ ## Install
102
+
103
+ Requires Python 3.10+. **Zero pip dependencies** — stdlib only,
104
+ including SigV4 signing for the AWS Lambda API.
105
+
106
+ ```bash
107
+ pip install lasa
108
+ lasa version
109
+ ```
110
+
111
+ Or from source:
112
+
113
+ ```bash
114
+ git clone https://github.com/Apilify/lasa
115
+ cd lasa
116
+ make install # creates .venv, installs the package
117
+ .venv/bin/lasa version
118
+ ```
119
+
120
+ The supply-chain claim we make about other people's Lambdas applies
121
+ to ourselves first: lasa has no third-party transitive dependencies
122
+ to be hijacked by the next worm. `pip install lasa` adds nothing to
123
+ your Python environment beyond lasa itself.
124
+
125
+ ## Why catalog.conf
126
+
127
+ The catalog is **informational** — it describes what the code does
128
+ (detected from source), not what it's structurally constrained to do.
129
+ The catalog file is not enforced by the runtime; nothing prevents the
130
+ Lambda from doing things outside this list at runtime.
131
+
132
+ Catalog-disciplined deployments — where the catalog IS structurally
133
+ enforced by the linker / runtime — are a separate product. lasa
134
+ analyzes existing Python Lambdas; it does not transform them.
135
+
136
+ ## Caching
137
+
138
+ PyPI maintainer counts and OSV vulnerability lookups are cached to
139
+ `~/.cache/semcom/` for 7 days. Override with `--no-cache` or
140
+ `--cache-ttl SECONDS`.
141
+
142
+ ## Versioning
143
+
144
+ This is **v0.1**. The Python implementation is the *oracle* — it
145
+ defines the score and catalog format. v1 is Forth + dlsym; v2 is
146
+ verified IR caps. Field names and types in the JSON output are the
147
+ public ABI both later versions must match.
148
+
149
+ `lasa version` prints the implementation version + the methodology
150
+ version; the methodology version bumps whenever weights or rules
151
+ change.
152
+
153
+ ## License
154
+
155
+ MIT.
@@ -0,0 +1,11 @@
1
+ """semcom CLI — risk analysis for AWS Lambdas.
2
+
3
+ v0 — Python stdlib oracle. The shipped version (v1) is Forth + dlsym;
4
+ this implementation establishes the reference behavior every later
5
+ version must match.
6
+
7
+ See docs/METHODOLOGY.md for what the score means.
8
+ See docs/PYTHON_SPEC.md for the implementation plan.
9
+ """
10
+ __version__ = "0.9.0"
11
+ METHODOLOGY_VERSION = "0.5.0-draft"
@@ -0,0 +1,9 @@
1
+ """`python -m semcom_cli` entrypoint."""
2
+ from __future__ import annotations
3
+
4
+ import sys
5
+
6
+ from lasa.cli import main
7
+
8
+ if __name__ == "__main__":
9
+ sys.exit(main())