VBC Code Quality, Architecture, and Security Audit¶
Date: 2026-05-31
Scope: current /home/xai/DEV/vbc checkout. This audit covers the local
single-user desktop/terminal deployment model, plus the optional read-only web
dashboard that can expose compression progress on a LAN.
This report started as a report-only audit. The testing, CI, dependency, and workflow-hardening notes below have since been updated with follow-up remediation status from the same day.
Executive Summary¶
VBC is a mature local batch-processing tool with useful separation between domain models, pipeline orchestration, infrastructure adapters, and UI state. The most important security conclusion is that the default local threat model does not support critical remote findings. The meaningful risks are local data loss, long-running or resource-heavy media processing, disclosure of local filenames/paths, and LAN visibility when the optional web dashboard is enabled.
The prior operational finding that uv run pytest could run for an excessive
amount of time has been corrected for this checkout: the two GH7 real-file
compression tests now use GPU encoding, and a full local run completed in
132.46s. The suite still executes real compression jobs, so CI or hosts
without NVENC should continue to use explicit safe subsets or an opt-in
real-file job.
Follow-up remediation completed on 2026-05-31:
- Added CI coverage for unit tests, docs-sync, docs build, and the safe integration subset.
- Hardened documentation deploy so secrets are only available in the deploy job, after docs are built and uploaded as an artifact.
- Fixed the undeclared
jinja2runtime dependency for--web. - Made the lockfile workflow consistent with
uv sync --frozen. - Updated test docs to use path-based commands instead of nonexistent unit markers.
- Renamed private scratch FFmpeg scripts as explicit manual helpers.
Remaining high-priority remediation themes:
- Make web dashboard exposure explicit before binding to all interfaces.
- Keep real-file test runtime bounded and document GPU/CI assumptions.
- Reduce or better defend large orchestration/UI hotspots over time.
- Clarify docs where current implementation differs from Clean Architecture claims and testing reality.
Threat Model¶
Primary deployment:
- One user runs VBC locally with that user's OS privileges.
- The user provides input, output, and errors directories.
- VBC launches trusted local binaries:
ffmpeg,ffprobe,exiftool, and optionallynvtop. - The optional web dashboard is disabled by default, but can be enabled by CLI or config.
Realistic attackers and failure actors:
- A malicious or malformed video file processed by external media parsers.
- A local process/user able to write into scanned input, output, or config directories.
- A same-LAN user when
--weborweb_server.enabledexposes the dashboard. - Another local OS user who can read world-readable logs or cwd artifacts.
Security invariants that matter:
- User media must not be moved, deleted, overwritten, or repaired unexpectedly.
- Local config files must not become code execution or shell injection.
- LAN observers should not see local filenames, errors, queue contents, or GPU telemetry unless the user intentionally exposes them.
- External tool failures must be visible and bounded.
conf/vbc.yamlmust remain untracked; it was verified untracked and ignored.
Security Findings¶
SEC-1: Web Dashboard Binds All Interfaces Without Auth When Enabled¶
Severity: Low by default, Medium when enabled on an untrusted LAN.
Affected code:
vbc/main.py:105exposes--web.vbc/config/models.py:400hasweb_server.enabled = False.vbc/config/models.py:402defaultsweb_server.hostto0.0.0.0.vbc/infrastructure/web_server.py:564routes plainGETrequests without authentication.vbc/infrastructure/web/templates/active_jobs.html:13,activity.html:25,queue.html:11, andgpu.html:7render filenames, errors, queue state, and GPU telemetry.
Validation:
- The endpoint is opt-in, so this is not internet-exposed in the default configuration.
- When enabled with the default host, the dashboard listens on all interfaces.
- No auth token, cookie, session, origin, or host check was found.
- Response headers are minimal: content type, content length, and no-cache.
- Static path traversal is guarded and Jinja autoescape is enabled, so this is not currently a path traversal or template XSS finding.
Impact:
- Same-LAN users can observe local filenames, active work, error text, queue metadata, and GPU telemetry.
- No state-changing API was found, so this is information disclosure and local-observability exposure, not remote code execution.
Recommended remediation:
- Prefer
127.0.0.1as the default bind address. - If LAN access is intended, require an explicit config value and print a clear exposure warning.
- Consider optional token auth for LAN use.
- Add basic hardening headers and either vendor dashboard assets or use CSP/SRI for CDN assets.
SEC-2: Local VBC.YAML Can Influence FFmpeg Encoder Arguments¶
Severity: Low in trusted single-user folders. Medium operational risk in shared or synced input trees.
Affected code:
vbc/config/local_registry.py:105scans input roots for local config.vbc/config/local_registry.py:130recognizesVBC.YAML.vbc/config/overrides.py:136usesyaml.safe_load.vbc/config/overrides.py:17allowsgpu_encoderandcpu_encoder.vbc/config/overrides.py:241passes allowed encoder sections into overrides.vbc/infrastructure/ffmpeg.py:33tokenizes configured args withshlex.split.vbc/infrastructure/ffmpeg.py:319inserts encoder tokens into the FFmpeg argv list.
Validation:
- YAML object execution is not present because
safe_loadis used. - Shell injection is not supported by the current command shape because FFmpeg
is invoked with argv lists, not
shell=True. - The remaining trust issue is semantic: a local config file in a scanned tree can alter FFmpeg flags and processing decisions.
Impact:
- In a normal owner-controlled media folder this is expected behavior.
- In a shared folder, a local writer could alter output format, codec flags, or processing behavior for files below that directory.
Recommended remediation:
- Document local
VBC.YAMLas trusted input. - For untrusted/shared folders, add an opt-in flag before honoring local encoder argument overrides.
- Consider restricting local overrides to quality/rate/filter decisions and excluding raw encoder args by default.
SEC-3: Logs May Disclose Local Filenames, Paths, and Debug Commands¶
Severity: Low.
Affected code:
vbc/config/models.py:242defaults the log path to/tmp/vbc/compression.log.vbc/infrastructure/logging.py:31creates aFileHandlerwithout explicit restrictive chmod.vbc/main.py:388logs input folders.vbc/infrastructure/ffmpeg.py:427logs full FFmpeg command lines in debug.vbc/pipeline/orchestrator.py:1006logs ExifTool stderr/stdout on failures.vbc/main.py:815appends fatal tracebacks toerror.log.
Validation:
- No application secrets were found in the app code path.
- The primary exposure is local metadata: paths, filenames, external-tool errors, and possibly command-line details.
Impact:
- Low for a single-user workstation.
- More relevant on shared Unix machines, synced project directories, or when log files are collected externally.
Recommended remediation:
- Document logs as sensitive local artifacts.
- Prefer a user-private log directory or explicitly set file mode for the default log path.
- Keep debug command logging opt-in.
Suppressed Security Candidates¶
The following candidates were checked and are not reportable security findings for the stated threat model:
- Shell injection: no
shell=Trueoros.systemwas found invbcorscripts; external tools use argv lists. - YAML object execution: global and local YAML loading uses
yaml.safe_load. - Static file traversal: the web server resolves requested static paths and checks containment before reading.
- Template XSS: Jinja autoescape is enabled and no
|safe/Markupbypass was found in the dashboard templates. - File move/delete/temp cleanup as remote security issues: these are local CLI side effects rooted in configured input/output/error directories. They remain important data-loss risks, but not remote vulnerabilities in the single-user model.
Architecture and Code Quality Findings¶
ARCH-1: Clean Architecture Claims Are Stronger Than Current Boundaries¶
Severity: Medium.
Evidence:
docs/architecture/overview.md:7claims Clean Architecture.vbc/pipeline/orchestrator.py:42imports concrete infrastructure adapters.vbc/config/overrides.py:10imports fromvbc.infrastructure.ffmpeg.vbc/infrastructure/gpu_monitor.py:10imports and mutatesUIState.vbc/domain/events.py:156contains UI-specific Dirs-tab input events.tests/unit/test_architecture_boundaries.py:5only checks that pipeline does not import UI directly.
Impact:
- The current design is workable for a local app, but the docs overstate the enforcement level.
- Boundary drift makes future refactors harder because concrete dependencies cross layers outside the composition root.
Recommended remediation:
- Update architecture docs to describe the current pragmatic boundaries.
- Expand boundary tests if strict Clean Architecture remains a goal.
- Keep future feature work from adding more concrete cross-layer imports.
ARCH-2: Large Hotspots Concentrate Too Many Responsibilities¶
Severity: Medium.
Evidence:
vbc/pipeline/orchestrator.pyis 2071 LOC.vbc/ui/modern_overlays.pyis 1451 LOC.vbc/ui/dashboard.pyis 1430 LOC.vbc/main.pyis 822 LOC.docs/architecture/overview.md:84still describes the orchestrator as "792 LOC".vbc/pipeline/orchestrator.pyowns discovery, queueing, color fix remux, metadata copy, verification, error markers, file move/delete behavior, fallback, wait/restart, and refresh loops.
Impact:
- Changes to one behavior can accidentally affect unrelated processing paths.
- Review and test targeting are harder because one class owns many lifecycle concerns.
Recommended remediation:
- Prefer extraction only around real seams already visible in tests: verification/tagging, discovery/error-marker accounting, and completed-file move behavior.
- Do not start with a broad rewrite. Add narrow tests before each extraction.
ARCH-3: EventBus Was Fragile Under Threaded Publishers¶
Status: Remediated on 2026-05-31.
Evidence:
vbc/infrastructure/event_bus.pynow protects subscriber mutation with a lock.publish()snapshots matching subscribers before invoking callbacks.publish()isolates subscriber exceptions and logs them instead of propagating them into publishers.vbc/infrastructure/ffmpeg.py:523publishes progress from processing paths.tests/unit/test_event_bus.pynow covers handler exceptions and subscriber mutation during publish.docs/architecture/events.md:629already recommends try/except around publish handlers.
Impact:
- The bus remains intentionally synchronous, so a slow handler can still delay its publisher.
- Handler exceptions no longer interrupt pipeline or subprocess control flow.
- Subscriber mutation during publish no longer affects the in-flight event dispatch.
Recommended remediation:
- Complete for the identified fragility.
- Consider an asynchronous or queued EventBus only if slow handlers become a measured runtime problem.
ARCH-4: CPU Fallback Could Drop a Job From Active UI State¶
Status: Remediated on 2026-05-31.
Evidence:
vbc/infrastructure/ffmpeg.py:551publishesHardwareCapabilityExceeded.vbc/ui/manager.py:285removes that job from active jobs.vbc/pipeline/orchestrator.py:1571enters CPU fallback retry.vbc/pipeline/orchestrator.pynow publishes a freshJobStartedbefore the CPU retry.tests/unit/test_orchestrator_processing.pyverifies that a hardware-cap fallback emits twoJobStartedevents for the same job and then completes.
Impact:
- When GPU fallback happens, the UI gets a new active-job start signal before the CPU retry begins.
- This preserves runtime observability during the recovery path.
Recommended remediation:
- Complete.
Testing, CI, and Documentation Findings¶
TEST-1: Full uv run pytest Was Previously Too Slow¶
Status: Remediated locally on 2026-05-31. Residual portability risk remains for non-GPU hosts and CI.
Evidence:
pyproject.toml:38setstestpaths = ["tests"].pyproject.toml:50registersslowbut does not exclude it by default.tests/conftest.py:162definesreal_test_videos.tests/conftest.py:209modifies copied fixtures withexiftool.tests/conftest.py:223only moves real-file tests to the end of collection.tests/integration/test_real_files_compression.py:17is marked slow and integration, then runs the real compression path.- This checkout contains
tests/dataat 632M andtests/data_outat 60M. tests/integration/test_real_files_dynamic_quality.pyandtests/integration/test_real_files_metadata.pynow usegpu=True, avoiding the long CPU/SVT-AV1 path for the GH7 real-file tests on this machine.uv run pytest -q --durations=20completed successfully with321 passed in 132.46s (0:02:12).
Impact:
- Before remediation, a routine full test command could run real video compression for a long time.
- After remediation, the current local checkout completes the full suite in about two minutes on the available GPU-capable machine.
- The suite still depends on real media fixtures and hardware-dependent encoder behavior, so a non-GPU machine may not see the same runtime.
Recommended remediation:
- Completed locally: switch the slow GH7 real-file tests from CPU to GPU.
- Keep documenting safe commands prominently for CI and machines without NVENC.
- Consider moving real-file tests behind a separate tox/nox/CI job or script if the project needs predictable cross-machine CI timing.
TEST-2: CI Only Protected Documentation Sync and Build¶
Status: Remediated on 2026-05-31.
Evidence:
- Before remediation,
.github/workflows/deploy.ymlonly rantests/test_docs_sync.pyandmkdocs build. .github/workflows/ci.ymlnow runs on pull requests and selected pushes.- The CI workflow runs docs sync, unit tests, a safe integration subset, and
mkdocs build. - Both workflow files set
permissions: contents: read. - Documentation deploy is split into a no-secret
build-docsjob and a separatedeployjob that downloads the builtsite/artifact. - Third-party actions are pinned to full commit SHA references.
Impact:
- Runtime, pipeline, UI, config, safe integration, and docs regressions now have basic GitHub Actions coverage.
- Deployment secrets are no longer present while repository code is checked out, dependencies are installed, or docs are built.
Recommended remediation:
- Complete.
- Optional future hardening: require manual approval for the
productionenvironment in GitHub settings, if this is not already configured.
TEST-3: --web Had an Undeclared Runtime Dependency¶
Status: Remediated on 2026-05-31.
Evidence:
vbc/main.py:105exposes--web.vbc/main.py:624imports/startsVBCWebServerwhen enabled.vbc/infrastructure/web_server.py:25importsjinja2.pyproject.tomlnow declaresjinja2as a runtime dependency.uv.lockis updated to reflect the runtime dependency.vbc/infrastructure/web_server.pyno longer claims the dashboard has no new dependencies.
Impact:
- A lean install that only installs runtime dependencies should now include
Jinja2 for
--web.
Recommended remediation:
- Complete.
TEST-4: Lockfile and Reproducibility Docs Drifted¶
Status: Remediated on 2026-05-31.
Evidence:
README.md:320anddocs/getting-started/installation.md:46recommenduv sync --frozen..gitignorenow explicitly allowsuv.lock.uv.lockis included in the remediation change set..github/workflows/deploy.ymland.github/workflows/ci.ymluseuv sync --frozen --extra docs --extra dev.
Impact:
- Installation docs, lockfile tracking, and workflow install commands now agree on frozen lockfile use.
Recommended remediation:
- Complete.
TEST-5: Test Marker Documentation Did Not Match Current Tests¶
Status: Remediated on 2026-05-31.
Evidence:
docs/development/testing.mdnow documents path-based unit and safe integration commands.- The marker section now reserves markers for cross-cutting properties and
explicitly says not to use
uv run pytest -m unit.
Impact:
- Developers are pointed at commands that select real tests in the current suite layout.
Recommended remediation:
- Complete.
TEST-6: Scratch Scripts Named test1.sh / test2.sh Were Tracked¶
Status: Remediated on 2026-05-31.
Evidence:
- The scripts were renamed to
scripts/manual_proxy_cpu.shandscripts/manual_proxy_gpu.sh. - Both scripts now require an explicit input file argument and no longer embed a
private
/arch03/V/...movpath. docs/development/testing.mddocuments them as manual media experiments, not automated tests.
Impact:
- The scripts are no longer presented as generic tests and cannot silently use a private hard-coded input path.
Recommended remediation:
- Complete.
Verified Strengths¶
conf/vbc.yamlis not tracked and is ignored by.gitignore.- External command execution in
vbcand tracked scripts uses argv lists; noshell=True/os.systemwas found. - YAML loading uses
yaml.safe_load. - Static serving has a path traversal containment check.
- Jinja autoescape is enabled for dashboard templates.
- Pydantic config validation covers many dangerous user-input shapes.
- Pipeline does not directly import
vbc.ui, and there is a boundary test for that rule. - Submit-on-demand limits queued futures instead of submitting every discovered file at once.
- The focused unit and safe integration suites are fast enough for routine use.
Verification Evidence¶
Commands run during this audit:
git status --short
git ls-files conf/vbc.yaml
git check-ignore -v conf/vbc.yaml
uv run pytest tests/test_docs_sync.py -q
uv run pytest tests/unit/test_event_bus.py -q
uv run pytest tests/unit/test_orchestrator_processing.py::test_process_file_cpu_fallback_on_hw_cap -q
uv run pytest tests/unit/ -q
uv run pytest tests/integration/test_metadata_copy.py tests/integration/test_skipping.py tests/integration/test_orchestrator.py tests/integration/test_hw_cap.py tests/integration/test_error_markers.py tests/integration/test_concurrency.py tests/integration/test_color_fix.py tests/integration/test_advanced_errors.py -q
uv run mkdocs build
uv run pytest tests/integration/test_real_files_dynamic_quality.py::test_real_file_dynamic_quality -q
uv run pytest tests/integration/test_real_files_metadata.py::test_real_file_metadata_preservation -q
uv run pytest -q --durations=20
uv run python -c "import yaml; [yaml.safe_load(open(path, encoding='utf-8')) for path in ('.github/workflows/deploy.yml', '.github/workflows/ci.yml')]; print('workflow yaml ok')"
git diff --check
uv sync --frozen --extra docs --extra dev
Observed results before this report was written:
git status --short: clean.git ls-files conf/vbc.yaml: no output.git check-ignore -v conf/vbc.yaml:.gitignore:21:conf/vbc.yaml.uv run pytest tests/test_docs_sync.py -q:10 passed in 0.01s.uv run pytest tests/unit/test_event_bus.py -q:5 passed in 0.01safter the EventBus hardening.uv run pytest tests/unit/test_orchestrator_processing.py::test_process_file_cpu_fallback_on_hw_cap -q:1 passed in 0.03safter the CPU fallback active-job remediation.uv run pytest tests/unit/ -q:283 passed in 1.43safter the remediation updates.- Safe selected integration subset:
26 passed in 22.62safter the remediation updates. uv run mkdocs build: completed; it reported existing nav omissions forDOCUMENTATION_CHANGELOG.mdanddevelopment/config_vs_cli_analysis.md, plus mkdocstrings/griffe warnings unrelated to this report.uv run pytest tests/integration/test_real_files_dynamic_quality.py::test_real_file_dynamic_quality -q:1 passed in 33.77safter switching the test to GPU.uv run pytest tests/integration/test_real_files_metadata.py::test_real_file_metadata_preservation -q:1 passed in 33.60safter switching the test to GPU.uv run pytest -q --durations=20:321 passed in 132.46s (0:02:12); the slowest tests were metadata preservation (32.77s), dynamic quality (31.81s), Sony compression (29.58s), and autorotation (10.35s).- Workflow YAML parse check:
workflow yaml ok. git diff --check: no output.uv sync --frozen --extra docs --extra dev:Checked 51 packages in 7ms.
Commands intentionally not run:
uv run pytest tests/integration/test_real_files*.py
uv run pytest --cov=vbc --cov-report=term-missing
Reason: the aggregate test_real_files*.py and coverage run still execute real
compression and were not needed after the full suite timing run above.
Prioritized Remediation Backlog¶
- Change web dashboard default host to
127.0.0.1, or add an explicit LAN exposure warning and optional token auth. - Update architecture docs to describe the current pragmatic boundaries and current file sizes.
- Plan narrow extractions from
Orchestratoronly where tests can pin current behavior first.