# Security Hardening Config And Integrity Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Add secure-by-default HTTP policy controls, enforce AppImageHub HTTPS and checksum handling, sanitize desktop entries, harden stable-ID path usage, and document the remaining AppImageHub trust issue. **Architecture:** Extend the existing runtime `CliConfig` with `allow_http`, thread that config into dispatch and add/install planning, keep provider-returned AppImageHub URLs on a stricter HTTPS-only path, add a provider-specific MD5 integrity check distinct from the existing trusted checksum mechanism, and tighten install-time path and desktop-entry generation at the boundary where files are written. **Tech Stack:** Rust workspace, Cargo tests, TOML config loading, existing install pipeline, fixture-backed provider tests. --- ### Task 1: Record the approved security shape in repo docs **Files:** - Create: `.architecture/security-issues.md` - Modify: `README.md` - Reference: `.audits/2026-03-21T20-08-04Z-post-appimagehub-security-audit.md` **Step 1: Write the security issues note** Create `.architecture/security-issues.md` with: - a short description of the AppImageHub host-trust gap - current mitigation: AppImageHub downloads must be HTTPS - deferred work: domain allowlist / provider trust policy - status label such as `open` **Step 2: Update the README security/config section** Document: - `allow_http = false` default - `allow_http = true` only affects user-supplied HTTP sources - provider-returned AppImageHub URLs remain HTTPS-only **Step 3: Verify docs exist and read clearly** Run: `rg -n "allow_http|AppImageHub|security" README.md .architecture/security-issues.md` Expected: matching lines in both files **Step 4: Commit** ```bash git add .architecture/security-issues.md README.md git commit -m "docs: record download security policy" ``` ### Task 2: Add `allow_http` to runtime config and thread it into dispatch **Files:** - Modify: `crates/aim-cli/src/config.rs` - Modify: `crates/aim-cli/src/main.rs` - Modify: `crates/aim-cli/src/lib.rs` - Test: `crates/aim-cli/tests/config_loading.rs` **Step 1: Write the failing config tests** Add tests covering: - default config has `allow_http == false` - config file with `allow_http = true` parses and loads correctly **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-cli --test config_loading` Expected: FAIL because `allow_http` does not exist yet **Step 3: Add the config field** Update `CliConfig` with: - `allow_http: bool` - `#[serde(default)]` - default value `false` **Step 4: Thread config into dispatch** Refactor the dispatch entrypoints so the already-loaded runtime config is available during query resolution and install planning. Preferred shape: - add `dispatch_with_reporter_and_config(...)` - keep existing `dispatch_with_reporter(...)` delegating to default config if needed for compatibility - update `main.rs` to call the config-aware path **Step 5: Run the focused tests to verify pass** Run: `cargo test --package aim-cli --test config_loading` Expected: PASS **Step 6: Commit** ```bash git add crates/aim-cli/src/config.rs crates/aim-cli/src/main.rs crates/aim-cli/src/lib.rs crates/aim-cli/tests/config_loading.rs git commit -m "feat: add allow_http runtime config" ``` ### Task 3: Enforce HTTP policy for user-supplied sources only **Files:** - Modify: `crates/aim-core/src/source/input.rs` - Modify: `crates/aim-core/src/app/add.rs` - Modify: `crates/aim-cli/src/lib.rs` - Test: `crates/aim-core/tests/query_resolution.rs` - Test: `crates/aim-cli/tests/end_to_end_cli.rs` **Step 1: Write the failing behavior tests** Add tests covering: - direct `http://example.com/app.AppImage` fails by default - the same input succeeds when `allow_http = true` - explicit SourceForge `http://...` inputs follow the same rule **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-cli --test end_to_end_cli` Expected: FAIL because HTTP is currently accepted unconditionally **Step 3: Add an explicit HTTP policy check** Implement a narrow policy helper that is evaluated only for user-supplied source inputs before add/install proceeds. Requirements: - reject insecure HTTP when config disallows it - preserve HTTPS behavior unchanged - do not let this config affect provider-returned URLs **Step 4: Surface a clear security error** Ensure the user sees a message equivalent to: - `insecure HTTP sources are disabled; set allow_http = true to permit them` **Step 5: Run the focused tests to verify pass** Run: `cargo test --package aim-cli --test end_to_end_cli` Expected: PASS with both rejection and opt-in cases covered **Step 6: Commit** ```bash git add crates/aim-core/src/source/input.rs crates/aim-core/src/app/add.rs crates/aim-cli/src/lib.rs crates/aim-core/tests/query_resolution.rs crates/aim-cli/tests/end_to_end_cli.rs git commit -m "feat: enforce user http policy" ``` ### Task 4: Enforce HTTPS for AppImageHub provider-returned downloads **Files:** - Modify: `crates/aim-core/src/source/appimagehub.rs` - Modify: `crates/aim-core/src/adapters/appimagehub.rs` - Modify: `crates/aim-core/src/app/add.rs` - Test: `crates/aim-core/tests/adapter_contract.rs` - Test: `crates/aim-cli/tests/end_to_end_cli.rs` **Step 1: Write the failing AppImageHub tests** Add a fixture-backed case where AppImageHub returns an `http://` download URL. Expected result: - install planning or resolution fails with a provider-specific security error - this remains true even when `allow_http = true` **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test adapter_contract` Expected: FAIL because AppImageHub URLs are currently accepted verbatim **Step 3: Add AppImageHub URL validation** Validate provider-returned AppImageHub download URLs for: - HTTPS scheme required - clear provider-specific error path Do not add the broader host allowlist in this task. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test adapter_contract && cargo test --package aim-cli --test end_to_end_cli` Expected: PASS **Step 5: Commit** ```bash git add crates/aim-core/src/source/appimagehub.rs crates/aim-core/src/adapters/appimagehub.rs crates/aim-core/src/app/add.rs crates/aim-core/tests/adapter_contract.rs crates/aim-cli/tests/end_to_end_cli.rs git commit -m "fix: require https for appimagehub downloads" ``` ### Task 5: Sanitize desktop entry display names **Files:** - Modify: `crates/aim-core/src/app/add.rs` - Test: `crates/aim-core/tests/install_integration.rs` - Test: `crates/aim-cli/tests/end_to_end_cli.rs` **Step 1: Write the failing desktop-entry tests** Add tests covering: - display name containing `\nExec=evil` does not inject a second field - display name containing control characters renders safely - normal display names still render as expected **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test install_integration` Expected: FAIL because desktop entry output currently interpolates raw display names **Step 3: Implement minimal sanitation** Add a helper near desktop entry rendering that: - strips `\r` and `\n` - replaces other control characters with spaces or removes them - preserves ordinary printable text Use the sanitized value only for desktop-entry rendering, not for mutating the stored app record. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test install_integration` Expected: PASS **Step 5: Commit** ```bash git add crates/aim-core/src/app/add.rs crates/aim-core/tests/install_integration.rs crates/aim-cli/tests/end_to_end_cli.rs git commit -m "fix: sanitize desktop entry names" ``` ### Task 6: Enforce AppImageHub MD5 integrity checks **Files:** - Modify: `Cargo.toml` - Modify: `crates/aim-core/Cargo.toml` - Modify: `crates/aim-core/src/domain/artifact.rs` or the existing artifact type definition file - Modify: `crates/aim-core/src/app/add.rs` - Modify: `crates/aim-core/src/integration/install.rs` - Test: `crates/aim-core/tests/checksum_verification.rs` - Test: `crates/aim-cli/tests/end_to_end_cli.rs` **Step 1: Identify the artifact checksum type location** Before editing, confirm where `ArtifactCandidate` is defined and where a provider-specific MD5 field should live. **Step 2: Write the failing integrity tests** Add tests covering: - AppImageHub install succeeds with matching MD5 fixture data - AppImageHub install fails before commit on MD5 mismatch - AppImageHub install still succeeds when no MD5 exists **Step 3: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test checksum_verification` Expected: FAIL because AppImageHub MD5 is currently ignored **Step 4: Add a separate weak-integrity field/path** Implement a provider-specific integrity path distinct from `trusted_checksum`. Requirements: - store the provider MD5 on the artifact candidate or equivalent install request - verify it after staging and before commit - do not overload the existing trusted SHA-512 semantics **Step 5: Add any needed dependency explicitly** If an MD5 crate is required, add it at the workspace and crate level. **Step 6: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test checksum_verification && cargo test --package aim-cli --test end_to_end_cli` Expected: PASS **Step 7: Commit** ```bash git add Cargo.toml crates/aim-core/Cargo.toml crates/aim-core/src/app/add.rs crates/aim-core/src/integration/install.rs crates/aim-core/tests/checksum_verification.rs crates/aim-cli/tests/end_to_end_cli.rs git commit -m "feat: verify appimagehub md5 integrity" ``` ### Task 7: Harden stable IDs and managed path containment **Files:** - Modify: `crates/aim-core/src/app/identity.rs` - Modify: `crates/aim-core/src/app/add.rs` - Test: `crates/aim-core/tests/identity_resolution.rs` - Test: `crates/aim-core/tests/install_paths.rs` **Step 1: Write the failing hardening tests** Add tests covering: - identifiers normalizing to `..` are rejected - managed install paths do not escape managed roots **Step 2: Run the focused tests to verify failure** Run: `cargo test --package aim-core --test identity_resolution --test install_paths` Expected: FAIL because `..` currently survives normalization and there is no explicit containment check **Step 3: Implement identity and path validation** Add: - explicit normalized-ID rejection for `..` - path containment validation before install proceeds Keep the implementation minimal and deterministic. **Step 4: Run the focused tests to verify pass** Run: `cargo test --package aim-core --test identity_resolution --test install_paths` Expected: PASS **Step 5: Commit** ```bash git add crates/aim-core/src/app/identity.rs crates/aim-core/src/app/add.rs crates/aim-core/tests/identity_resolution.rs crates/aim-core/tests/install_paths.rs git commit -m "fix: harden stable id paths" ``` ### Task 8: Add external helper audit logging and adversarial regression coverage **Files:** - Modify: `crates/aim-core/src/integration/refresh.rs` - Modify: `crates/aim-core/src/source/appimagehub.rs` - Test: `crates/aim-core/tests/adapter_contract.rs` - Test: `crates/aim-core/tests/install_integration.rs` - Test: `crates/aim-cli/tests/end_to_end_cli.rs` **Step 1: Write the failing or missing regression tests** Add adversarial cases for: - malformed AppImageHub XML or missing fields handled cleanly - malicious display names in fixture-backed install flows - helper execution paths producing expected warnings/loggable branches **Step 2: Implement minimal logging** Add debug-level logging around helper execution in `refresh.rs`. **Step 3: Run focused tests** Run: `cargo test --package aim-core --test adapter_contract --test install_integration && cargo test --package aim-cli --test end_to_end_cli` Expected: PASS **Step 4: Commit** ```bash git add crates/aim-core/src/integration/refresh.rs crates/aim-core/src/source/appimagehub.rs crates/aim-core/tests/adapter_contract.rs crates/aim-core/tests/install_integration.rs crates/aim-cli/tests/end_to_end_cli.rs git commit -m "test: cover security edge cases" ``` ### Task 9: Full verification and final docs pass **Files:** - Modify: `.plans/012-security-hardening-config-and-integrity/2026-03-21-security-hardening-config-and-integrity-design.md` if implementation drifted - Modify: `.plans/012-security-hardening-config-and-integrity/2026-03-21-security-hardening-config-and-integrity-implementation-plan.md` if task wording drifted - Modify: `.architecture/security-issues.md` if final wording needs adjustment **Step 1: Run formatting and full verification** Run: ```bash cargo fmt --all cargo test --workspace cargo clippy --workspace --all-targets --all-features -- -D warnings ``` Expected: all commands succeed. **Step 2: Re-read the security docs** Confirm the final README and `.architecture/security-issues.md` text still matches the implementation. **Step 3: Commit** ```bash git add .plans/012-security-hardening-config-and-integrity .architecture/security-issues.md README.md git commit -m "docs: record security hardening plan" ```