Secure Ephemeral File Transfer in CI/CD Pipelines
In CI/CD pipelines, you often need to move files between stages. You may need to share artifacts with external systems or upload build outputs to a third party. Setting up S3 buckets or NFS shares for temporary file transfer is overkill. Ephemeral CLI-based file sharing fills the gap.
The Problem Space
%%{ init: { 'look': 'handDrawn' } }%%
graph LR
A[CI Runner<br/>Build complete] -->|1. Package artifact| B[transfer.sh<br/>Generated link]
B -->|2. Share link<br/>via Slack/Email| C[Reviewer/Tester]
C -->|3. Download<br/>within 14 days| D[Artifact deleted<br/>automatically]
In a typical pipeline, artifacts need to travel between:
- Build stage → Test stage → Deploy stage
- CI runner → External reviewer or QA team
- Pipeline run → Artifact storage (S3, GCS)
For temporary, one-off file sharing, setting up object storage is operational overhead. A CLI-based approach works in minutes.
Secure File Transfer with transfer.sh
# Upload a file (auto-generates a link)
curl --upload-file ./build.tar.gz https://transfer.sh/build.tar.gz
# Upload with encryption (AES-256)
curl --upload-file <(gzip -c build.tar.gz | openssl enc -aes-256-cbc -pbkdf2) \
https://transfer.sh/build.tar.gz.gpg
# Upload with auto-expiry (14 days max by default)
# The service handles retention automatically
The service scans for malware, supports Tor hidden service endpoints, and auto-deletes files after the retention period.
CI/CD Integration
# GitHub Actions example
- name: Upload build artifact
run: |
ARTIFACT_URL=$(curl --upload-file ./dist.tar.gz https://transfer.sh/dist.tar.gz)
echo "Artifact: $ARTIFACT_URL"
# Share via Slack/GitHub PR comment
echo "::notice file=artifact-url::$ARTIFACT_URL"
- name: Download and verify
run: |
curl -o dist.tar.gz https://transfer.sh/abc123/dist.tar.gz
sha256sum dist.tar.gz
When to Use This vs S3/GCS
| Scenario | Use transfer.sh | Use S3/GCS |
|---|---|---|
| Temporary sharing, < 14 days | ✅ | ❌ (overkill) |
| Public artifact, no auth needed | ✅ | ✅ |
| Sensitive data (credentials, keys) | ⚠️ encrypt first | ✅ (proper IAM) |
| Large files (> 5GB) | ❌ (service limits) | ✅ |
| Compliance/audit trail | ❌ | ✅ |
| Programmatic access from pipeline | ✅ | ✅ |
For sensitive files in CI, always encrypt before uploading:
# Encrypt with a shared secret
ENCRYPTION_KEY=$((head -c 32 /dev/urandom | base64))
echo $ENCRYPTION_KEY >> .encryption_key # Store in CI secret
tar -czf - ./dist | openssl enc -aes-256-cbc -pbkdf2 -pass pass:$ENCRYPTION_KEY \
-out dist.tar.gz.enc
curl --upload-file ./dist.tar.gz.enc https://transfer.sh/dist.tar.gz.enc
Decrypt on the receiving end with the same key.
Artifact Expiry in GitOps Context
%%{ init: { 'look': 'handDrawn' } }%%
graph LR
A[Artifact generated<br/>in CI] --> B[Upload to transfer.sh<br/>14-day expiry]
B --> C[Link shared in PR]
C --> D[Reviewer downloads]
D --> E{Approved?}
E -->|Yes| F[Artifact uploaded<br/>to S3 permanent storage]
E -->|No| G[Link expires<br/>artifact auto-deleted]
F --> H[Deploy to staging/prod]
For GitOps workflows, the ephemeral link serves as a temporary preview mechanism. Approved artifacts get promoted to permanent storage; rejected ones simply expire.
Security Considerations
- No authentication on the link — anyone with the URL can download
- Links are guessable but not enumerable — use long random IDs
- No audit log — you won’t know who downloaded what
- Encryption is your responsibility — encrypt sensitive files before upload
For anything involving credentials, PII, or compliance requirements, use object storage with proper IAM. For temporary build artifacts, test results, and non-sensitive logs shared during code review, ephemeral transfer is the right tool.