Skip to content

Commit daf03c4

Browse files
koxonclaude
andcommitted
docs(CLAUDE.md): add AI audit findings — security, monitoring, performance
Captures command injection risk, hardcoded account ID, FFmpeg 4.2 EOL, missing rate limiting/monitoring/temp encryption, sequential bottleneck. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent aed5f7f commit daf03c4

1 file changed

Lines changed: 55 additions & 8 deletions

File tree

CLAUDE.md

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ CloudTranscode is bFAN's distributed media transcoding pipeline. It's a set of P
88

99
- **Language**: PHP 7+ (legacy codebase, but clean)
1010
- **Container**: Docker (ECS deployment)
11-
- **FFmpeg**: 4.2 (video/image processing)
11+
- **FFmpeg**: 4.2 (video/image processing)**EOL, from 2019. See Security Findings.**
1212
- **ImageMagick**: convert commands for image transcoding
1313
- **AWS Services**: Step Functions (SFN), S3, ECS, EC2, IAM
14+
- **Orchestration**: AWS Step Functions state machines (see `state_machines/`)
1415
- **SDK**: CloudProcessingEngine-SDK (bFAN fork) for activity polling and lifecycle
1516
- **Dependencies**: AWS SDK for PHP 3.x, JSON Schema validation
17+
- **Monitoring**: None configured — no CloudWatch alarms, dashboards, or custom metrics. See Security Findings.
1618

1719
## Quick Start
1820

@@ -81,11 +83,12 @@ Pass custom client class to activity workers via `-C <client class path>` option
8183

8284
## Key Patterns
8385

86+
- **Step Functions orchestration**: Workflow is defined in `state_machines/` JSON. SFN distributes tasks to activity workers, handles retries and failure routing. This is the control plane — workers are the data plane.
8487
- **Activity polling**: Workers use long-polling to fetch tasks from AWS SFN
85-
- **Sequential output processing**: One TranscodeAssetActivity worker processes all outputs in the `output_assets` array sequentially, not in parallel. To parallelize, split the workflow.
88+
- **Sequential output processing**: One TranscodeAssetActivity worker processes all outputs in the `output_assets` array sequentially, not in parallel. This is a **performance bottleneck** — a 10-output job ties up one worker for the full duration. To parallelize, split the workflow into separate SFN executions or use Map states.
8689
- **Stateless workers**: Workers are horizontally scalable Docker containers. State lives in S3 and SFN.
8790
- **Preset-based transcoding**: FFmpeg commands can be templated using presets (e.g., `360p-4.3-generic`)
88-
- **Custom FFmpeg commands**: JSON input supports raw FFmpeg command strings for advanced use cases
91+
- **Custom FFmpeg commands**: JSON input supports raw FFmpeg command strings for advanced use cases. **WARNING: command injection risk — see Security Findings.**
8992
- **Watermarking**: Overlay images on video with custom position, opacity, size
9093
- **HTTP input**: Workers can pull source files from HTTP/S URLs instead of S3
9194

@@ -107,9 +110,10 @@ Pass custom client class to activity workers via `-C <client class path>` option
107110
## Deployment
108111

109112
**Current setup:**
110-
- Docker image built from `Dockerfile` and pushed to ECR: `501431420968.dkr.ecr.eu-west-1.amazonaws.com/sportarc/cloudtranscode:4.2`
113+
- Docker image built from `Dockerfile` and pushed to ECR (eu-west-1)
111114
- ECS cluster runs workers as tasks
112115
- Each worker polls a specific SFN activity ARN
116+
- **Note**: AWS account ID `501431420968` is hardcoded in the Dockerfile/configs. Use an environment variable or SSM parameter instead.
113117

114118
**Deployment steps:**
115119
1. Build Docker image: `docker build -t <ecr-repo>:tag .`
@@ -129,16 +133,59 @@ Pass custom client class to activity workers via `-C <client class path>` option
129133
- Check S3 output buckets for transcoded files
130134
- Review CloudWatch Logs for worker output
131135

136+
## Security Findings
137+
138+
> AI audit — 2026-02-17. These findings should be tracked as issues and resolved.
139+
140+
### CRITICAL — Command Injection via FFmpeg/ImageMagick
141+
142+
The transcoder code passes user-supplied JSON parameters (codec, size, preset names, custom command strings) into FFmpeg and ImageMagick shell commands **without escaping or sanitization**. A crafted `output_assets` payload could inject arbitrary shell commands.
143+
144+
**Affected files**: `src/activities/transcoders/` — anywhere parameters are interpolated into shell commands.
145+
146+
**Fix**: Use `escapeshellarg()` on every user-supplied parameter before interpolation. Better: build argument arrays and use `proc_open()` instead of `exec()`/`shell_exec()` with string concatenation. Validate inputs against an allowlist of known codecs, presets, and sizes.
147+
148+
### HIGH — No Rate Limiting
149+
150+
There is no throttling on Step Functions task submission. A misconfigured client or runaway automation can flood the pipeline with jobs, exhausting ECS capacity and S3 write throughput.
151+
152+
**Fix**: Add SFN execution concurrency limits, or use an SQS queue with a controlled consumer rate in front of the pipeline.
153+
154+
### MEDIUM — Hardcoded AWS Account ID
155+
156+
AWS account ID `501431420968` appears in ECR URIs and potentially in SFN ARNs throughout the codebase. This leaks infrastructure details and makes multi-account deployment impossible.
157+
158+
**Fix**: Replace with environment variables, SSM parameters, or CDK/CloudFormation references.
159+
160+
### MEDIUM — FFmpeg 4.2 (2019) — End of Life
161+
162+
FFmpeg 4.2 is from August 2019 and no longer receives security patches. Known CVEs in older FFmpeg versions include heap overflows in demuxers and decoders that can be triggered by malformed input media.
163+
164+
**Fix**: Upgrade the `sportarc/ffmpeg` and `sportarc/cloudtranscode-base` Docker images to FFmpeg 6.x or 7.x. Test transcoding presets for compatibility.
165+
166+
### MEDIUM — No Temp File Encryption
167+
168+
Transcoding temp files (downloaded source, intermediate outputs) are stored on local ECS disk unencrypted. If the disk is an EBS volume, data at rest is exposed unless the volume itself has encryption enabled.
169+
170+
**Fix**: Ensure ECS instances use encrypted EBS volumes. For sensitive media, consider encrypting temp files at the application level or using instance store with dm-crypt.
171+
172+
### LOW — No CloudWatch Monitoring
173+
174+
No CloudWatch alarms, custom metrics, or dashboards are configured. Worker failures, SFN execution errors, and S3 throughput issues are invisible without manual console checks.
175+
176+
**Fix**: Add CloudWatch alarms for SFN execution failures, ECS task stopped events, and worker heartbeat gaps. Publish custom metrics for transcode duration, queue depth, and error rates.
177+
132178
## Gotchas
133179

134-
- **Sequential processing**: TranscodeAssetActivity processes all outputs sequentially. For parallel transcoding of multiple outputs, you must split the workflow or run multiple workers with separate SFN tasks.
180+
- **Sequential processing bottleneck**: TranscodeAssetActivity processes all outputs sequentially. A single job with many outputs blocks the worker. Split into parallel SFN branches or use Map states.
135181
- **Docker base image dependency**: This repo depends on two SportArchive Docker images (`sportarc/ffmpeg`, `sportarc/cloudtranscode-base`). If those images are updated, rebuild this image.
136-
- **FFmpeg version**: Locked to 4.2. Upgrading FFmpeg requires updating the base image.
182+
- **FFmpeg version**: Locked to 4.2 (2019, EOL). Upgrading FFmpeg requires updating the base image and retesting all presets.
137183
- **Client interface requirement**: For production use, you MUST implement a custom client interface class and extend the Dockerfile to include it. Without it, workers run but don't notify client apps of progress/completion.
138184
- **AWS SFN long polling**: Workers block on GetActivityTask calls (long polling). If AWS SFN is unavailable, workers will hang until timeout.
139-
- **Temp disk space**: Transcoding uses local disk for temporary files. Ensure ECS instances or Docker volumes have sufficient space for large video files.
185+
- **Temp disk space**: Transcoding uses local disk for temporary files. Ensure ECS instances or Docker volumes have sufficient space for large video files. Temp files are **not encrypted** at the application level.
140186
- **Presets location**: The `presets/` directory in this repo may be deprecated. Check if CloudTranscode-FFMpeg-presets is the canonical source.
187+
- **Hardcoded account ID**: `501431420968` is baked into ECR URIs and possibly SFN ARNs. Must be parameterized for multi-account use.
141188

142189
<!-- Ask: What happens if a worker crashes mid-transcode? Does SFN retry, or is the task lost? Are there heartbeat intervals configured? -->
143190
<!-- Ask: How are FFmpeg presets loaded — from this repo's presets/ dir, or from CloudTranscode-FFMpeg-presets? -->
144-
<!-- Ask: What's the relationship between this repo and CloudTranscode-Lambda? When is Lambda used vs ECS workers? -->
191+
<!-- Ask: What's the relationship between this repo and CloudTranscode-Lambda? When is Lambda used vs ECS workers? -->

0 commit comments

Comments
 (0)