vendcurl
vendcurl is a tiny curl-ish command for setup scripts and CI bootstrap code. It downloads a URL, validates the resulting file, writes a content-addressed blob into an S3-compatible object store, writes a URL manifest, and prefers that vendored blob on later runs.
It is deliberately boring: SHA-256 does the identity work; archive validators only check structure and obvious archive-path nastiness.
Install with uv
From this source tree:
uv tool install .
From a git repository once you have committed it somewhere:
uv tool install git+https://github.com/you/vendcurl
For local hacking without installing:
uv run vendcurl --help
S3-compatible configuration
You can pass options each time:
vendcurl \
--bucket my-vendor-cache \
--endpoint-url https://s3.eu-west-2.amazonaws.com \
--prefix sandbox-artifacts \
--sha256 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef \
https://example.test/releases/tool-1.2.3.tar.gz \
vendor/tool-1.2.3.tar.gz
Or use environment variables:
export VENDCURL_BUCKET=my-vendor-cache
export VENDCURL_PREFIX=sandbox-artifacts
export VENDCURL_ENDPOINT_URL=https://s3.eu-west-2.amazonaws.com
export AWS_PROFILE=dev
vendcurl https://example.test/releases/tool-1.2.3.zip vendor/tool.zip
The supported environment variables are:
VENDCURL_BUCKETorS3_BUCKETVENDCURL_PREFIXVENDCURL_ENDPOINT_URL,AWS_ENDPOINT_URL_S3, orS3_ENDPOINT_URLVENDCURL_REGION,AWS_REGION, orAWS_DEFAULT_REGIONVENDCURL_PROFILEorAWS_PROFILEVENDCURL_RETRIESVENDCURL_TIMEOUTVENDCURL_USER_AGENT
Credentials are whatever boto3 can already find: environment variables, profiles, instance metadata, OIDC-derived credentials, and so on.
Behaviour
On the first run, vendcurl:
- Downloads the origin URL.
- Computes SHA-256 while writing the file.
- Checks
--sha256if you supplied it. - Chooses a validator from the filename/content type unless you set
--validator. - Uploads the blob to
s3://$bucket/$prefix/blobs/sha256/<first-two-hex>/<sha256>. - Writes a URL manifest to
s3://$bucket/$prefix/manifests/by-url/<sha256(url)>.json. - Atomically moves the validated file into your requested output path.
On later runs, it reads the URL manifest first, downloads the content-addressed blob from S3, re-checks SHA-256 locally, validates the file again, and only goes back to the origin if the cache entry is missing or stale.
Validators
--validator auto recognizes:
- tar archives:
.tar,.tar.gz,.tgz,.tar.xz,.txz,.tar.bz2,.tbz,.tbz2 - zip archives:
.zip,.whl,.jar - single compressed streams:
.gz,.xz,.bz2
You can force a validator with --validator tar, --validator zip, --validator gzip, --validator xz, --validator bz2, or disable structural checks with --validator none.
By default, tar and zip validation rejects archive member names that look dangerous for later extraction, such as absolute paths, Windows drive paths, and .. traversal. Use --allow-unsafe-archive-paths only for fossilized upstreams that you have inspected and deliberately trust.
Useful modes
Force origin refresh and update the manifest:
vendcurl --refresh https://example.test/tool.tar.gz vendor/tool.tar.gz
Use only the vendored copy, never the origin:
vendcurl --no-origin --sha256 "$digest" https://example.test/tool.tar.gz vendor/tool.tar.gz
Smoke-test a URL without S3:
vendcurl --no-store --validator zip https://example.test/file.zip ./file.zip
Emit machine-readable output:
vendcurl --json https://example.test/file.zip ./file.zip
Development
The unit tests are stdlib-only:
PYTHONPATH=src python -m unittest discover -s tests
If you have uv available:
uv run python -m unittest discover -s tests
Metadata
Release files for vendcurl 0.1.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 |
|---|---|---|---|---|
| vendcurl-0.1.0.tar.gz | 11.7 kB | Without provenance | Details for vendcurl-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| vendcurl-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for vendcurl-0.1.0-py3-none-any.whl |
Total release size: 24.8 kB
Release files / vendcurl-0.1.0.tar.gz
| Download URL | vendcurl-0.1.0.tar.gz |
|---|---|
| Size | 11.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97fb724797c6e46b7894a165975ea7b4306db5ea6bb3dfc6e68e298922e8a778
|
|
BLAKE2b-256 checksum How to use checksums |
2a79017eec86057ee26668a9c4338578234945b92d4fd0e983d58d66d7f51ba0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"43","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / vendcurl-0.1.0-py3-none-any.whl
| Download URL | vendcurl-0.1.0-py3-none-any.whl |
|---|---|
| Size | 13.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0b66a3beace1395a8a624309825ab37455138c8d733f3789e52206ed9b6d6116
|
|
BLAKE2b-256 checksum How to use checksums |
1d6c720067b738972bffec885650be5ee2337ad7b27e51c5b8cf6afece5f9550
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.21 {"installer":{"name":"uv","version":"0.9.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"43","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for vendcurl 0.1.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.
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.
To learn more about protecting yourself from malicious actors, visit our package security documentation.