Skip to content

Casting plane adoption + injectrc seal wave (T07, T14)#1

Merged
Enginex0 merged 21 commits into
mainfrom
feat/casting-plane
Jun 18, 2026
Merged

Casting plane adoption + injectrc seal wave (T07, T14)#1
Enginex0 merged 21 commits into
mainfrom
feat/casting-plane

Conversation

@Enginex0

@Enginex0 Enginex0 commented Jun 18, 2026

Copy link
Copy Markdown
Owner

Summary

Brings feat/casting-plane to main: Casting-plane build/CI adoption plus the
first parallel wave of the resetprop-rs-injectrc-ports bucket. Two independent
threads on one branch.

Build / CI / toolchain (8 commits)

  • Adopt the Casting plane (settings.gradle.kts, scripts/comment-hygiene.py)
  • Pin Rust toolchain to 1.96.0; run the full Rust wall on PRs; drop cross targets from the toolchain pin
  • Workspace rustfmt pass; mark internal crates publish=false; drop decorative divider comments
  • refactor(propdetect): sort findings by severity key

injectrc seal wave — T07, T14

  • T07 feat: add --check dry-run to init hook install — a no-poke dry-run through install_init_hook (identity guard, attach, resolve symbol, locate scratch slot) that returns the resolved facts without writing into init, wired to a --check flag in the hand-rolled CLI parser. The no-write guarantee is statically grounded: the dry-run path and its transitive callees hold zero ptrace-write primitives.
  • T14 test: add per-arch ptrace smoke fixtures — x86_64/arm/x86 sibling test files (#![cfg(target_arch = ...)]) asserting per-arch trap/breakpoint encodings and the NT_PRSTATUS regset layout. The aarch64 fixture is unchanged.

Verification (host)

  • cargo test -p resetprop: green (151 lib + 3 native x86_64 fixtures + 2 doctests)
  • cargo clippy -p resetprop --all-targets -- -D warnings: clean
  • cargo fmt --check: clean

Acceptance edges CI cannot cover

  • T07's --check zero-AVC behavior needs a live aarch64 init (device-gated).
  • T14's Android-target test runs need an NDK linker plus an emulator; cargo check --tests type-checks and codegens clean on all three Android triples here.

Environmental gates, not regressions.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added --check flag support with seal mode for dry-run verification of hook initialization
  • Infrastructure

    • Enhanced build quality gates with automated dependency and license validation
    • Implemented pre-commit and pre-push verification hooks
    • Expanded testing coverage across multiple processor architectures
    • Standardized editor and development environment configuration

Enginex0 added 11 commits June 17, 2026 17:35
Generated by tools/cast.py: root settings + build-logic (law repo,
convention dep), root build (rust-gates + comment-hygiene + the
hand-authored dependencyGuard), gradle/libs.versions.toml, deny.toml,
detekt + license config, .editorconfig, .githooks, .mold version.
core.hooksPath is set to .githooks (pre-commit gatesFast, pre-push
gatesFull); both skip cleanly until a gradle wrapper exists.
Box-drawing and dash rules the comment-hygiene gate flags as
decorative banners; they carry no information the code does not.
Workspace path-dep consumers, not crates.io artifacts. cargo-deny's
wildcard-path ban applies to public crates; this exempts them.
Satisfies clippy unnecessary_sort_by under -D warnings. Severity is
Copy + Ord, so Reverse keeps the existing descending order.
Adopt the cargoFmtCheck gate. The tree diverged from rustfmt 1.96.0
defaults; this is the formatting-only pass, kept separate from the
substantive changes above.
Pins rustfmt and clippy so CI and local format identically; a newer
rustfmt can no longer reformat the tree out from under the gate.
Mirrors the Casting law's rust = 1.96.0 and lists the four Android
targets so the cross-builds resolve under the pin.
Replaces the library-only clippy check with the Casting wall: cargo
fmt --check, clippy --all-targets --all-features -D warnings, cargo
deny (offline supply line), and a comment-hygiene scan mirroring the
law's banner rule. Host check, tests, and cross-compile are unchanged.
CI gates natively (no JVM); the gradle wall stays the local definition.
Listing the Android targets in rust-toolchain.toml made every host
cargo command (clippy, fmt) try to download their std libs first,
which times out offline or on a slow link, and it broke the clippy
gate. Drop them from the pin; the cross-compile sites add the target
against the pinned toolchain instead (rustup target add), where the
network is both available and actually needed.
Add check_init_hook: resolve stage-A facts (maps + libc ELF + symbol)
and the scratch slot under one RemoteAttach window, then detach without
poking init. The path runs only the no-side-effect sub-ops of
install_init_hook -- no remote_syscall_via_poke, ptrace_poketext, or
write_remote -- so init's text and registers are left untouched and no
trampoline is installed. Results surface as CheckReport.

Wire a --check bool flag into the hand-rolled CLI parser. With --seal it
dry-runs the Tier B install and reports the resolved facts instead of
writing, letting an operator validate a device before the real poke.
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Enginex0, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 53 minutes and 10 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 50338b3e-f82e-436e-9456-24a7a7e35d56

📥 Commits

Reviewing files that changed from the base of the PR and between 6004ca2 and 277525d.

📒 Files selected for processing (16)
  • .gitignore
  • bucket/resetprop-rs-injectrc-ports/progress.yml
  • crates/resetprop-cli/src/main.rs
  • crates/resetprop/src/lib.rs
  • crates/resetprop/src/seal/arena.rs
  • crates/resetprop/src/seal/hook.rs
  • crates/resetprop/src/seal/kmsg_observer.rs
  • crates/resetprop/src/seal/mod.rs
  • crates/resetprop/src/seal/ptrace.rs
  • crates/resetprop/src/seal/ptrace/arch/aarch64.rs
  • crates/resetprop/src/seal/ptrace/arch/arm.rs
  • crates/resetprop/src/seal/ptrace/arch/riscv64.rs
  • crates/resetprop/src/seal/ptrace/arch/x86.rs
  • crates/resetprop/src/seal/ptrace/arch/x86_64.rs
  • crates/resetprop/src/seal/selinux.rs
  • crates/resetprop/tests/ptrace_core_smoke.rs
📝 Walkthrough

Walkthrough

This PR establishes a Gradle build-logic scaffold with version catalog, dependency-guard task, and quality-gate tooling (cargo-deny, detekt, comment-hygiene script, git hooks). CI and release workflows are updated to use rustup directly for toolchain/target management. A --check dry-run mode is added to the --seal CLI path via a new CheckReport/check_init_hook API. Architecture-gated ptrace ABI contract smoke tests are added for ARM, x86, and x86_64. A large Rust reformatting pass applies multi-line formatting across nearly all crate source files.

Changes

Build/CI/Quality-gate infrastructure

Layer / File(s) Summary
Gradle project scaffolding and version catalog
settings.gradle.kts, build-logic/settings.gradle.kts, build-logic/build.gradle.kts, gradle/libs.versions.toml, .mold/structure-version, .editorconfig
Root and build-logic Gradle settings wired with a local Maven repo, version catalog with pinned AGP/Kotlin versions, editorconfig rules, and mold structure-version bumped to 0.1.13.
Quality-gate tooling
rust-toolchain.toml, deny.toml, config/detekt/detekt.yml, config/license/allowed-licenses.json, scripts/comment-hygiene.py, .githooks/pre-commit, .githooks/pre-push
Pins Rust toolchain to 1.96.0, adds cargo-deny supply-chain policy, detekt rule config, JVM license allowlist, a Python comment-banner hygiene script, and git hook scripts that run Gradle gates.
CI workflow gates and dependencyGuard task
.github/workflows/ci.yml, .github/workflows/release.yml, build.gradle.kts, gradle/dependency-guard.config
CI check job gains fmt/clippy/cargo-deny/comment-hygiene steps; standalone clippy job removed. Both CI and release replace dtolnay/rust-toolchain with rustup show+rustup target add. Root build.gradle.kts adds the dependencyGuard task with DependencyMatrix parsing to enforce allowed project→project edges.
Cargo publish flags, progress, and gitignore
crates/*/Cargo.toml, bucket/.../progress.yml, .context/.gitignore
Sets publish = false on three workspace crates, advances T07 and T14 to done in the project tracker, and rewrites the experimental directory gitignore comment.

--check dry-run feature and ptrace ABI contract tests

Layer / File(s) Summary
CheckReport struct and check_init_hook dry-run API
crates/resetprop/src/seal/hook.rs
Adds pub struct CheckReport { libc_base, libc_end, target_fn, scratch_pc } and pub fn check_init_hook(pid) that performs a read-only ptrace attach to resolve stage-A hook facts and returns them without modifying the tracee. A unit test verifies the public fields are accessible.
CLI --check flag wiring
crates/resetprop-cli/src/main.rs
Adds --check argument parsing; when combined with --seal, invokes check_init_hook and prints resolved addresses, otherwise falls through to the existing install path. Help and options text updated.
Ptrace ABI contract smoke tests
crates/resetprop/tests/ptrace_core_smoke_arm.rs, ...x86.rs, ...x86_64.rs
Three new #[cfg(target_arch = "...")]-gated test files assert instruction encodings (TRAP_INSN/BRK_INSN), NT_PRSTATUS byte-size contracts, and syscall register wiring via set_syscall_args/get_syscall_return for AArch32, i386, and x86_64.

Rust code reformatting

Layer / File(s) Summary
resetprop crate reformatting
crates/resetprop/src/*.rs, crates/resetprop/src/persist/*.rs, crates/resetprop/src/seal/*.rs, crates/resetprop/tests/...
Multi-line struct literals, expanded unsafe blocks, multi-line function signatures, and comment-separator normalization across all resetprop source and test files. No behavioral changes except comment-only separator reformatting in seal/ files.
propdetect crates reformatting
crates/propdetect*/src/*.rs, crates/propdetect/tests/detect_manipulation.rs
Same formatting pass applied to propdetect and propdetect-bionic; includes a minor logic change: findings sorting switches from a custom comparator to sort_by_key with Reverse.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐇 A rabbit once scattered their build rules around,
Then gathered them neatly — how tidy the ground!
A --check flag was added, no side-effects stay,
The ptrace ABI signed contracts today.
With formatting swept to a clean multi-line,
The warren is structured, and everything's fine! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: adopting the Casting plane infrastructure and merging T07/T14 features for injectrc seal work.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/casting-plane

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
build.gradle.kts (1)

64-70: ⚡ Quick win

Reject duplicate source-tier rules during matrix parsing.

Using associate here silently keeps only the last duplicate tier. That can hide policy mistakes and make guard behavior non-obvious.

Suggested fix
-            val allowed = text.lineSequence()
+            val seen = mutableSetOf<String>()
+            val allowed = text.lineSequence()
                 .map { it.substringBefore('#').trim() }
                 .filter { it.isNotEmpty() }
                 .associate { line ->
                     require("->" in line) { "dependency-guard.config: rule has no '->': `$line`" }
                     val tier = line.substringBefore("->").trim()
+                    require(seen.add(tier)) {
+                        "dependency-guard.config: duplicate source tier: `$tier`"
+                    }
                     val specs = line.substringAfter("->").trim()
                         .split(Regex("\\s+")).filter { it.isNotEmpty() }.toSet()
                     tier to specs
                 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.gradle.kts` around lines 64 - 70, The associate function at line 64
silently keeps only the last duplicate tier when multiple rules have the same
source-tier, which can hide policy mistakes. Replace the associate call with
logic that builds the map while explicitly validating there are no duplicate
tiers - either by using toMap with a custom merging function that throws an
error on duplicates, or by collecting the tier-to-specs pairs into a map and
adding validation logic that checks for and rejects any duplicate tier keys
before returning the result. Ensure the error message clearly indicates which
tier rule is duplicated to aid policy debugging.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 26-29: The `gates` job in the GitHub Actions workflow is missing
explicit least-privilege permission declarations, which means it inherits
potentially overpermissive default token permissions. Add a `permissions`
section directly under the `gates` job definition (after the `runs-on` key) to
explicitly declare read-only scopes. Set `contents: read` as the minimum
required permission to allow the job to access repository contents without write
capabilities, ensuring the job operates with least-privilege access control.
- Line 30: The actions/checkout action on line 30 uses a mutable version tag
(`@v4`) instead of a pinned commit SHA, creating supply chain risk. Replace the
`@v4` version tag with the full-length commit SHA for that specific version of the
action. Additionally, add `persist-credentials: false` as a parameter to the
checkout action to prevent the GITHUB_TOKEN from being stored in Git
configuration. Apply the same fixes to the checkout action on line 42 which
currently uses `@v2`.

In `@build-logic/settings.gradle.kts`:
- Line 7: The maven repository URL on line 7 of settings.gradle.kts is
hard-coded to a machine-local mount path
`/mnt/companion/president/maven-casting`, making builds fail in environments
where this mount doesn't exist. Replace the hard-coded path with a Gradle
property or environment variable (e.g., using System.getenv() or Gradle
properties). Apply the same parameterization to line 6 to ensure both casting
and any other machine-specific paths are sourced from configuration rather than
hard-coded, making the build portable across CI and development environments.

In `@crates/resetprop-cli/src/main.rs`:
- Around line 265-284: The check flag validation is only enforced within the
seal branch (inside the if check block at line 265), which allows --check
without --seal to be silently ignored and execute normal mutation paths instead.
Move the check flag validation logic to an earlier point in the function
execution flow, before the normal mutation path begins, to enforce the contract
that --check should either require a specific context like --seal or should
reject conflicting positional arguments. Add validation that raises an error
when --check is passed without appropriate context or with mutation-related
arguments that would conflict with the dry-run expectation.

In `@scripts/comment-hygiene.py`:
- Line 56: The Path.read_text() call on line 56 can throw an OSError when a
tracked file is unreadable, which terminates the script with a traceback. Wrap
the file reading operation in a try-except block that catches OSError, and
instead of letting the exception propagate, implement a controlled failure path
such as skipping that file or logging a warning and continuing with the next
file. This ensures the script handles unreadable files gracefully without
crashing.

---

Nitpick comments:
In `@build.gradle.kts`:
- Around line 64-70: The associate function at line 64 silently keeps only the
last duplicate tier when multiple rules have the same source-tier, which can
hide policy mistakes. Replace the associate call with logic that builds the map
while explicitly validating there are no duplicate tiers - either by using toMap
with a custom merging function that throws an error on duplicates, or by
collecting the tier-to-specs pairs into a map and adding validation logic that
checks for and rejects any duplicate tier keys before returning the result.
Ensure the error message clearly indicates which tier rule is duplicated to aid
policy debugging.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 36636745-2b3b-44d6-b514-2339b703c1be

📥 Commits

Reviewing files that changed from the base of the PR and between df57a4b and 6004ca2.

📒 Files selected for processing (55)
  • .context/.gitignore
  • .context/experimental/.gitkeep
  • .editorconfig
  • .githooks/pre-commit
  • .githooks/pre-push
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • .mold/structure-version
  • bucket/resetprop-rs-injectrc-ports/progress.yml
  • build-logic/build.gradle.kts
  • build-logic/settings.gradle.kts
  • build.gradle.kts
  • config/detekt/detekt.yml
  • config/license/allowed-licenses.json
  • crates/propdetect-bionic/Cargo.toml
  • crates/propdetect-bionic/src/main.rs
  • crates/propdetect/Cargo.toml
  • crates/propdetect/src/heuristics.rs
  • crates/propdetect/src/main.rs
  • crates/propdetect/src/snapshot.rs
  • crates/propdetect/tests/detect_manipulation.rs
  • crates/resetprop-cli/Cargo.toml
  • crates/resetprop-cli/src/main.rs
  • crates/resetprop/src/area.rs
  • crates/resetprop/src/bionic.rs
  • crates/resetprop/src/compact.rs
  • crates/resetprop/src/context.rs
  • crates/resetprop/src/dict.rs
  • crates/resetprop/src/error.rs
  • crates/resetprop/src/harvest.rs
  • crates/resetprop/src/info.rs
  • crates/resetprop/src/inspect.rs
  • crates/resetprop/src/lib.rs
  • crates/resetprop/src/mock.rs
  • crates/resetprop/src/persist/io.rs
  • crates/resetprop/src/persist/mod.rs
  • crates/resetprop/src/persist/proto.rs
  • crates/resetprop/src/seal/arena.rs
  • crates/resetprop/src/seal/elf.rs
  • crates/resetprop/src/seal/hook.rs
  • crates/resetprop/src/seal/maps.rs
  • crates/resetprop/src/seal/ptrace.rs
  • crates/resetprop/src/trie.rs
  • crates/resetprop/tests/elf_fixture_smoke.rs
  • crates/resetprop/tests/ptrace_core_smoke.rs
  • crates/resetprop/tests/ptrace_core_smoke_arm.rs
  • crates/resetprop/tests/ptrace_core_smoke_x86.rs
  • crates/resetprop/tests/ptrace_core_smoke_x86_64.rs
  • crates/resetprop/tests/tier_a_child_smoke.rs
  • deny.toml
  • gradle/dependency-guard.config
  • gradle/libs.versions.toml
  • rust-toolchain.toml
  • scripts/comment-hygiene.py
  • settings.gradle.kts

Comment thread .github/workflows/ci.yml
Comment on lines +26 to +29
gates:
name: Casting wall (fmt, clippy, supply, comment-hygiene)
runs-on: ubuntu-latest
steps:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Set explicit least-privilege permissions for the new gates job.

The new job currently inherits default token permissions. Declare read-only scope explicitly to avoid accidental write-capable defaults.

Suggested fix
   gates:
     name: Casting wall (fmt, clippy, supply, comment-hygiene)
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     steps:
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
gates:
name: Casting wall (fmt, clippy, supply, comment-hygiene)
runs-on: ubuntu-latest
steps:
gates:
name: Casting wall (fmt, clippy, supply, comment-hygiene)
runs-on: ubuntu-latest
permissions:
contents: read
steps:
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 26-50: overly broad permissions (excessive-permissions): default permissions used due to no permissions: block

(excessive-permissions)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 26 - 29, The `gates` job in the GitHub
Actions workflow is missing explicit least-privilege permission declarations,
which means it inherits potentially overpermissive default token permissions.
Add a `permissions` section directly under the `gates` job definition (after the
`runs-on` key) to explicitly declare read-only scopes. Set `contents: read` as
the minimum required permission to allow the job to access repository contents
without write capabilities, ensuring the job operates with least-privilege
access control.

Source: Linters/SAST tools

Comment thread .github/workflows/ci.yml
name: Casting wall (fmt, clippy, supply, comment-hygiene)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n .github/workflows/ci.yml | head -50

Repository: Enginex0/resetprop-rs

Length of output: 1528


🌐 Web query:

GitHub Actions security best practices pin commit SHA persist-credentials

💡 Result:

Securing GitHub Actions workflows involves two critical best practices: pinning actions to immutable commit SHAs and properly managing credential persistence. Pinning Actions to Commit SHAs Using version tags (e.g., @v4) or branch names (e.g., @main) for GitHub Actions introduces significant supply chain risk because these references are mutable [1][2]. An attacker who compromises an action's repository can force-push malicious code to an existing tag or branch, causing all workflows that reference that tag to automatically execute the malicious code [1][3][4]. Pinning to a full-length commit SHA is the only way to treat an action as an immutable release [5][3]. Because a commit SHA cryptographically identifies a specific Git object, it cannot be redirected to different code [1][6]. - Implementation: Replace tag references with the full-length commit SHA [5][4]. To maintain readability, include the original version tag as a comment [7][4]. - Example: - uses: actions/checkout@11bd719 # v4.2.2 - Automation: Use tools like Renovate with presets (e.g., helpers:pinGitHubActionDigests) to automatically create pull requests that update SHA pins whenever the referenced tag moves, ensuring security without significant maintenance overhead [1][2][7]. - Enforcement: Organizations can enable policies to mandate commit SHA pinning across all repositories, causing any workflow using mutable tags to fail [5][6][7]. Managing Credential Persistence The actions/checkout action, by default, persists Git credentials (including the GITHUB_TOKEN) into the runner's local Git configuration [8][9][10]. If a workflow is compromised, a malicious step or third-party action can access these credentials to perform unauthorized operations, such as pushing commits or accessing other repository secrets [11][8][10]. - Implementation: Always set persist-credentials to false unless your workflow explicitly requires Git authentication to push changes back to the repository [8][10][12]. - Example: - uses: actions/checkout@11bd719 with: persist-credentials: false - Context: While newer versions of actions/checkout (v6+) store persisted credentials in a temporary runner path ($RUNNER_TEMP) rather than directly in.git/config, setting persist-credentials to false remains a critical best practice to prevent credential exposure [13][9]. - Alternative: If you need to push changes, prefer using the GITHUB_TOKEN with defined, minimum-required permissions rather than relying on persisted credentials [1][10][12].

Citations:


Pin third-party actions to commit SHAs and disable checkout credential persistence.

Lines 30 and 42 use mutable action version tags (@v4 and @v2), which expose the workflow to supply chain risk if those tags are force-pushed with malicious code. Pin both to full-length commit SHAs instead. Additionally, add persist-credentials: false to the checkout action to prevent the GITHUB_TOKEN from being stored in Git configuration, reducing token exposure if a workflow step is compromised.

Suggested fix
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+        with:
+          persist-credentials: false
-      - name: Install cargo-deny
-        uses: taiki-e/install-action@v2
+      - name: Install cargo-deny
+        uses: taiki-e/install-action@<commit-sha> # v2
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 30-30: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 30-30: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml at line 30, The actions/checkout action on line 30
uses a mutable version tag (`@v4`) instead of a pinned commit SHA, creating supply
chain risk. Replace the `@v4` version tag with the full-length commit SHA for that
specific version of the action. Additionally, add `persist-credentials: false`
as a parameter to the checkout action to prevent the GITHUB_TOKEN from being
stored in Git configuration. Apply the same fixes to the checkout action on line
42 which currently uses `@v2`.

Source: Linters/SAST tools

// gradle/libs.versions.toml is imported by path so the catalog stays one SSOT.
dependencyResolutionManagement {
repositories {
maven { url = uri("file:///mnt/companion/president/maven-casting") } // mold casting law repo

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Parameterize the Casting Maven repo path instead of hard-coding a machine-local mount.

Line 7 binds plugin resolution to /mnt/companion/president/maven-casting; environments without that mount will fail during settings evaluation. Please source this from a Gradle property/env var (and apply the same fix to settings.gradle.kts Line 6) to keep CI/dev setups portable.

Suggested direction
- maven { url = uri("file:///mnt/companion/president/maven-casting") }
+ val castingRepo = providers.gradleProperty("castingRepoUrl")
+     .orElse(System.getenv("CASTING_REPO_URL") ?: "")
+     .get()
+ require(castingRepo.isNotBlank()) { "Missing casting repo URL. Set -PcastingRepoUrl or CASTING_REPO_URL." }
+ maven { url = uri(castingRepo) }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build-logic/settings.gradle.kts` at line 7, The maven repository URL on line
7 of settings.gradle.kts is hard-coded to a machine-local mount path
`/mnt/companion/president/maven-casting`, making builds fail in environments
where this mount doesn't exist. Replace the hard-coded path with a Gradle
property or environment variable (e.g., using System.getenv() or Gradle
properties). Apply the same parameterization to line 6 to ensure both casting
and any other machine-specific paths are sourced from configuration rather than
hard-coded, making the build portable across CI and development environments.

Comment on lines +265 to +284
if check {
// Dry-run: resolve the Tier B facts in init without poking it. No
// value is written and no trampoline is installed, so VALUE is not
// required here. INIT_PID is `1` (crate-internal in resetprop).
return match resetprop::seal::hook::check_init_hook(1) {
Ok(r) => {
println!(
"check [{name}]: libc_base={:#x} libc_end={:#x} target_fn={:#x} scratch_pc={:#x}",
r.libc_base, r.libc_end, r.target_fn, r.scratch_pc
);
Ok(())
}
Err(
e @ (Error::HookInstallFailed(_)
| Error::ElfParse(_)
| Error::SymbolNotFound(_)),
) => Err(format!("Tier B dry-run failed: {e}")),
Err(e) => Err(format!("check failed: {e}")),
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Enforce --check contract strictly to avoid unintended writes.

Line 265 currently treats check only inside the --seal branch, so --check without --seal is silently ignored; and in the dry-run branch, extra positional args are ignored. This can mislead operators into expecting a no-write run while executing a normal mutation path.

💡 Suggested fix
@@
     if seal_flag_count > 1 {
@@
     }
+    if check && seal.is_none() {
+        return Err("--check requires --seal".to_string());
+    }

@@
     if let Some(ref name) = seal {
         if check {
+            if !positional.is_empty() {
+                return Err("--seal --check does not accept VALUE or positional args".to_string());
+            }
             // Dry-run: resolve the Tier B facts in init without poking it. No
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@crates/resetprop-cli/src/main.rs` around lines 265 - 284, The check flag
validation is only enforced within the seal branch (inside the if check block at
line 265), which allows --check without --seal to be silently ignored and
execute normal mutation paths instead. Move the check flag validation logic to
an earlier point in the function execution flow, before the normal mutation path
begins, to enforce the contract that --check should either require a specific
context like --seal or should reject conflicting positional arguments. Add
validation that raises an error when --check is passed without appropriate
context or with mutation-related arguments that would conflict with the dry-run
expectation.

return 2
violations = []
for rel in files:
text = Path(rel).read_text(encoding="utf-8", errors="replace")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle unreadable tracked files without crashing the gate.

Line 56 can throw OSError and terminate the script with a traceback. Return a controlled failure path instead.

Suggested fix
-        text = Path(rel).read_text(encoding="utf-8", errors="replace")
+        try:
+            text = Path(rel).read_text(encoding="utf-8", errors="replace")
+        except OSError as exc:
+            print(f"comment-hygiene: cannot read {rel}: {exc}", file=sys.stderr)
+            return 2
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/comment-hygiene.py` at line 56, The Path.read_text() call on line 56
can throw an OSError when a tracked file is unreadable, which terminates the
script with a traceback. Wrap the file reading operation in a try-except block
that catches OSError, and instead of letting the exception propagate, implement
a controlled failure path such as skipping that file or logging a warning and
continuing with the next file. This ensures the script handles unreadable files
gracefully without crashing.

Enginex0 added 10 commits June 18, 2026 05:22
A failed install retries on every seal() call while the hook slot is
empty, so a load that crashes init can bootloop it. Cap hard failures
per process: install_init_hook refuses with HookInstallFailed once a
module-static AtomicU32 hits MAX_INSTALL_HARD_FAILURES (5, mirroring
ReZygisk's MAX_RETRY_COUNT) before the M1 identity check or any ptrace
attach. The counter is module-static because the failures it counts
never produce a HookHandle.
arena and hook carried divergent libc.text predicates; only hook's was
hardened (exact r-xp + path ends_with /libc.so). Promote it to a shared
find_libc_text_row driving both the stage-A and Tier A remap finders,
deleting arena's looser r-x + libc.so.* match that could pick a shared
copy or a versioned sibling.

Also bind LOCK_LIST_CAPACITY < PATH_STAGE_OFFSET with a const-assert so
a future capacity bump fails the build instead of letting the in-init
walker read the staged path bytes, and clear doc-rot: the append
capacity rationale (the hook body moved off this page in 563e6a3), the
empty-list sentinel wording, arena's remote_syscall_via_poke flow doc,
and mod.rs's stale "deferred re-exports" note.
Replace the host-file hook-page dance (write under
/data/adb/resetprop-rs, remote openat, mmap, unlink) with injectrc's
memfd pattern: the tracee creates an anonymous memfd, this process
fills it through /proc/<pid>/fd/<memfd> and relabels it to the libc.so
SELinux context via setfilecon, then the tracee maps and closes its own
fd. The mapping survives the close via the fd's anonymous inode, so
nothing reaches disk: no hook-*.bin residue and no adb_data_file:file
execute denial to dodge.

The libselinux relabel is hand-rolled FFI (no selinux-sys crate). The
NDK ships no libselinux to link against, so the Android path resolves
getfilecon/setfilecon/freecon at runtime via dlopen rather than #[link];
the host build compiles a shim that reports the op unsupported.

The remote syscall sequence (memfd_create, mmap, close) runs behind a
closure seam so it is exercised off-device with mocked syscalls.

On-device acceptance (zero hook-*.bin residue, no new avc denial) needs
real aarch64 init and is not validated here.
Code + host acceptance complete; on-device residue/avc checks pending
hardware (see a98a5b7).
- Add observe-init: a whole-thread-group PTRACE_SYSCALL snoop of
  init's write(/dev/kmsg) traffic, with per-arch syscall_nr/arg
  accessors and GET_SYSCALL_INFO entry detection.
- Fold the staged-trap injector into one run_remote_payload
  skeleton shared by the syscall and ISB paths (arena, hook).
- Fold first-seal install + trampoline + first append under one
  thread-group stop; add install_and_seal_first / FirstSeal.
- Resolve target_fn against the ELF load bias, not the r-xp
  segment start, so the trampoline lands on __system_property_update
  instead of a neighbouring function.
- Make --seal repeatable in one run so a single process builds a
  multi-entry lock list under one shared hook handle, removing the
  one-seal-per-boot trap.
- Add --observe-init [--duration SECS] to dump init's /dev/kmsg
  writes via PropSystem::observe_init.
- Refresh usage and options text.
- .serena/ holds codeintel cache and project config, not source.
- T06 Tier B on-device gate, T10 kmsg snoop, and T17 injector
  consolidation now complete.
- rustfmt the observe-init/multi-seal additions and the pre-existing
  selinux row, so the CI fmt gate passes.
@Enginex0 Enginex0 merged commit 277525d into main Jun 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant