aim/.plans/012-security-hardening-config-and-integrity/2026-03-21-security-hardening-config-and-integrity-implementation-plan.md

13 KiB

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

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

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

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

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

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

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

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

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:

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

git add .plans/012-security-hardening-config-and-integrity .architecture/security-issues.md README.md
git commit -m "docs: record security hardening plan"