Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
489 changes: 130 additions & 359 deletions WHAT_IS_WORKING_AND_NOT_WORKING.md

Large diffs are not rendered by default.

37 changes: 37 additions & 0 deletions src/ai/orchestrator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,40 @@ impl AgentCommunication for SimpleAgentCommunication {
self.messages.push((from, 0, msg_array));
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DeviceTarget {
CPU,
GPU,
TPU,
}

#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrchestratorError {
Success = 0,
AgentNotFound = 1,
ExecutionFailed = 2,
Timeout = 3,
InvalidTask = 4,
}

pub struct LocalLlmOrchestrator {
pub name: String,
pub target: DeviceTarget,
pub active_agents: Vec<AgentID>,
}

impl LocalLlmOrchestrator {
pub fn new(name: &str, target: DeviceTarget) -> Self {
LocalLlmOrchestrator {
name: name.to_string(),
target,
active_agents: Vec::new(),
}
}

pub fn execute_workflow(&self, prompt: &str) -> Result<String, OrchestratorError> {
Ok(format!("Executed workflow on {:?}: {}", self.target, prompt))
}
Comment on lines +332 to +334

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 '\bLocalLlmOrchestrator\b|\bOrchestratorError\b' src || true
rg -n -C 8 'LocalLlmOrchestrator::execute_workflow|\.execute_workflow\s*\(' src --glob '*.rs' || true

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 5492


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== repository files matching orchestrator/local llm =="
fd -i 'orchestrator|llm|local_l|ai' . | sed 's#^\./##' | head -200

echo
echo "== Rust files containing execute_workflow =="
rg -n -C 10 'execute_workflow|LocalLlmOrchestrator|active_agents|agent' --glob '*.rs' . || true

echo
echo "== source file outline =="
ast-grep outline src/ai/orchestrator.rs --view expanded || true

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 50385


Implement execute_workflow instead of returning Ok unconditionally.

LocalLlmOrchestrator::execute_workflow does not validate self.active_agents, select a device, dispatch to the local LLM, or inspect task output. Every call returns Ok, so callers cannot observe AgentNotFound, ExecutionFailed, Timeout, or InvalidTask. Return an explicit error until the backend exists, or wire the method into an actual execution path.

🤖 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 `@src/ai/orchestrator.rs` around lines 332 - 334, Replace the unconditional
success in LocalLlmOrchestrator::execute_workflow with an explicit
unsupported-execution error until the local LLM backend is implemented, or
connect it to the real execution path. Do not fabricate workflow output; ensure
callers can receive the appropriate OrchestratorError rather than always
returning Ok.

}
8 changes: 6 additions & 2 deletions src/ai/sai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -520,15 +520,19 @@ impl SovereignWorkflowEngine {
pub fn execute_workflow(&mut self) -> Result<usize, &'static str> {
let mut executed_count = 0;
let node_len = self.nodes.len();
let mut initially_executed = alloc::vec::Vec::new();
for node in &self.nodes {
initially_executed.push(node.state_executed);
}

for i in 0..node_len {
// Check if independent or its dependency was already executed
// Check if independent or its dependency was already executed before this call
let can_execute = match self.nodes[i].depends_on {
None => true,
Some(dep_id) => {
let mut dep_ok = false;
for j in 0..node_len {
if self.nodes[j].id == dep_id && self.nodes[j].state_executed {
if self.nodes[j].id == dep_id && initially_executed[j] {
dep_ok = true;
break;
}
Expand Down
8 changes: 0 additions & 8 deletions src/dashboard/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,10 @@

// SigmaOS Dashboard Module
pub mod accessibility_gamification;
pub mod accessibility_gamification;
pub mod control_center;
pub mod monitor;
pub mod process;
pub mod accessibility_gamification;

pub use accessibility_gamification::{
AccessibilityOverlay, ColorFilter, GamifiedProductivityTracker, Trophy,
};
pub use accessibility_gamification::{
AccessibilityOverlay, ColorFilter, GamifiedProductivityTracker, Trophy,
};
Expand All @@ -39,9 +34,6 @@ pub use control_center::{
pub use monitor::{
DashboardWidget, MetricData, MetricType, SystemMonitor, UnifiedDashboard, WidgetType,
};
pub use accessibility_gamification::{
ColorFilter, AccessibilityOverlay, Trophy, GamifiedProductivityTracker,
};
pub use process::{
ProcessAction, ProcessError, ProcessFilter, ProcessInfo, ProcessManager,
ProcessMonitorStrategy, ProcessPriority, ProcessState, SystemProcessMonitor,
Expand Down
29 changes: 28 additions & 1 deletion src/klib/hashset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use super::HashMap;
use super::hashmap::HashMapIter;

#[derive(Clone)]
pub struct HashSet<T>
where
T: Eq + core::hash::Hash + Clone,
Comment on lines +7 to 10

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate hashset =="
fd -a 'hashset\.rs$' . || true

echo "== file excerpt =="
if [ -f src/klib/hashset.rs ]; then
  wc -l src/klib/hashset.rs
  sed -n '1,220p' src/klib/hashset.rs
else
  echo "src/klib/hashset.rs not found"
fi

echo "== search for HashSet usages/definitions =="
rg -n "struct HashSet|impl .*HashSet|HashSet<|insert\\(|contains\\(|remove\\(" src -S || true

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 50385


Remove the type-wide Clone requirement.

HashSet<T> requires T: Eq + core::hash::Hash + Clone at the type boundary. insert, contains, and remove do not clone the key. A non-Clone key cannot use this collection.

Keep Clone only for HashSet::clone() and any operations that copy values.

🤖 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 `@src/klib/hashset.rs` around lines 7 - 10, Remove Clone from the type-wide
bound on HashSet<T>, retaining only Eq and core::hash::Hash. Add Clone bounds
only to the HashSet clone implementation and methods that actually copy keys or
values, while keeping insert, contains, and remove usable with non-Clone keys.

Expand Down Expand Up @@ -80,6 +81,32 @@ where
}
}

impl<T> core::fmt::Debug for HashSet<T>
where
T: Eq + core::hash::Hash + Clone + core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut set = f.debug_set();
for item in self.iter() {
set.entry(item);
}
set.finish()
}
}

impl<T> core::iter::FromIterator<T> for HashSet<T>
where
T: Eq + core::hash::Hash + Clone,
{
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let mut set = HashSet::new();
for item in iter {
set.insert(item);
}
set
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -112,4 +139,4 @@ mod tests {
let items: Vec<i32> = set.iter().cloned().collect();
assert_eq!(items.len(), 2);
}
}
}
8 changes: 5 additions & 3 deletions src/klib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ pub mod vec;
pub mod buddy_allocator;
pub mod paging;
pub mod uvm;
pub mod hash;
pub mod hashmap;
pub mod hashset;

pub use vec::Vec;

#[cfg(not(target_os = "none"))]
pub use std::collections::HashMap;
pub use hashmap::HashMap;
pub use hashset::HashSet;
Comment on lines +6 to +12

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^src/klib/|^src/.*\.rs$|WHAT_IS_WORKING_AND_NOT_WORKING\.md)$' | sed -n '1,120p'

echo "== klib outline/files =="
if [ -d src/klib ]; then
  find src/klib -maxdepth 2 -type f -print | sort
  for f in src/klib/mod.rs src/klib/hash.rs src/klib/hashmap.rs src/klib/hashset.rs src/klib/vec.rs; do
    if [ -f "$f" ]; then
      echo "--- $f ($(wc -l < "$f") lines) ---"
      ast-grep outline "$f" --view compact || true
    fi
  done
fi

echo "== relevant README section =="
sed -n '120,160p' WHAT_IS_WAITING_AND_NOT_WORKING.md 2>/dev/null || true
sed -n '130,155p' WHAT_IS_WORKING_AND_NOT_WORKING.md 2>/dev/null || true

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 6170


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== klib relevant source snippets =="
for f in src/klib/mod.rs src/klib/hashmap.rs src/klib/hashset.rs src/klib/vec.rs src/klib/hash.rs; do
  if [ -f "$f" ]; then
    echo "--- $f : first 260 lines ---"
    sed -n '1,260p' "$f" | cat -n
  fi
done

echo "== usages of klib collections in docs/tests/src (import/call patterns) =="
rg -n "crate::klib::(Vec|HashMap|HashSet)|use crate::klib::|klib::HashMap|klib::HashSet|klib::Vec|HashMap::|HashSet::|Vec::" -S -g '*.rs' -g '*.md' . | sed -n '1,240p'

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 44989


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== full klib HashMap entry/remove/other methods =="
sed -n '260,447p' src/klib/hashmap.rs | cat -n

echo "== full klib HashSet remaining implementations =="
sed -n '100,260p' src/klib/hashset.rs | cat -n

echo "== Hash trait implementation status for custom collections =="
rg -n "impl.*Hash for HashMap|impl.*Hash for HashSet|impl.*Hash for Vec|impl Entry|trait Entry|or_insert|remove\\(" src/klib src -g '*.rs' | sed -n '1,220p'

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 24083


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== exact HashMapEntry/occupied entries =="
rg -n "enum Entry|struct OccupiedEntry|struct VacantEntry|impl<'a, K, V> OccupiedEntry|impl<'a, K, V> VacantEntry|pub struct HashMapEntry|pub enum HashMapEntry|fn entry\\(&mut self, key: K\\) ->" src/klib/hashmap.rs
sed -n '1,120p' src/klib/hashmap.rs | cat -n

echo "== exact custom collection trait/status and remove values in source =="
python3 - <<'PY'
from pathlib import Path
p = Path("src/klib/hashmap.rs")
s = p.read_text()
checks = {
    "HashMap entry returns Entry": "pub fn entry(&mut self, key: K) -> Entry<'_, K, V>" in s,
    "HashMap OccupiedEntry has entry value as mutable reference": '_marker: core::marker::PhantomData<K>' in s and "value: &'a mut V" in s,
    "HashMap Entry or_insert_with returns mutable reference": "pub fn or_insert_with<F>(self, default: F) -> &'a mut V" in s,
    "HashMap remove returns value": "pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>" in s,
    "HashMapEntry trait not present": "Entry<'_, K, V> {" not in s,
    "OccupiedEntry replace/remove methods absent": all(m not in s for m in [
        "pub fn take(self) -> V",
        "pub fn remove(self) -> V",
        "pub fn replace(self, value: V) -> V",
        "pub fn replace_entry(self, value: V) -> V",
    ]),
    "Remove leaves Drop values": "let (_, value) = bucket.remove(i)" in s and "let value = bucket.remove(i)" not in s and "Value" not in s,
}
for name, ok in checks.items():
    print(f"{name}: {ok}")
PY

echo "== src/sigpkg/resolver imports and std HashMap/HashSet usage =="
sed -n '1,70p' src/sigpkg/resolver.rs | cat -n
rg -n "std::collections::HashMap|HashMap::new|HashSet::new|insert\\(|remove\\(" src/sigpkg/resolver.rs | sed -n '1,80p'

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 7525


Establish collection contract parity before the migration.

crate::klib::{Vec, HashMap, HashSet} is exported and documented as a std::collections replacement, but the APIs are not equivalent. In src/klib/hashmap.rs, remove returns the value while the current entry path only exposes an OccupiedEntry value reference and is missing methods such as OccupiedEntry::remove/replace; HashSet<T> also requires Clone instead of just Hash. Update src/klib/mod.rs and the migration steps in WHAT_IS_WORKING_AND_NOT_WORKING.md so the guide includes the missing compatibility guards/checks before replacing legacy imports.

📍 Affects 2 files
  • src/klib/mod.rs#L6-L12 (this comment)
  • WHAT_IS_WORKING_AND_NOT_WORKING.md#L136-L150
🤖 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 `@src/klib/mod.rs` around lines 6 - 12, Update src/klib/mod.rs (lines 6-12) and
the migration steps in WHAT_IS_WORKING_AND_NOT_WORKING.md (lines 136-150) to
establish collection API compatibility checks before replacing legacy imports:
verify HashMap::remove returns the removed value, add or account for
OccupiedEntry::remove and OccupiedEntry::replace, and ensure HashSet requires
only Hash rather than Clone. Keep the exported crate::klib::{Vec, HashMap,
HashSet} contract and document these guards in the migration guide.

8 changes: 8 additions & 0 deletions src/klib/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ impl<T> Vec<T> {
}
}
}
pub fn pop(&mut self) -> Option<T> {
if self.len == 0 {
None
} else {
self.len -= 1;
unsafe { Some(core::ptr::read(self.data.add(self.len))) }
}
}
Comment on lines +40 to +47

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)src/klib/vec\.rs$|Cargo\.toml$' || true

echo "== vec.rs outline =="
ast-grep outline src/klib/vec.rs --view compact || true

echo "== relevant vec.rs lines =="
cat -n src/klib/vec.rs | sed -n '1,150p'

echo "== rust availability/version =="
rustc --version || true

Repository: AaryanSinghChauhan09/SigmaOS

Length of output: 6217


🌐 Web query:

Rust core::ptr::read zero-sized type non-null aligned pointer validity documentation

💡 Result:

In Rust, calling core::ptr::read on a zero-sized type (ZST) is permitted even with a null pointer, provided certain conditions are met [1][2]. While historical versions of the documentation stated that even for ZSTs the pointer must be non-null and properly aligned [3], recent changes have clarified and refined these requirements [4][2]. According to the current official documentation for core::ptr::read, a null pointer is permitted if the total size of the access is zero (i.e., the type is a ZST) [5][1]. However, there is a strict requirement regarding alignment: even when the type is a ZST, the pointer must be properly aligned [5]. The documentation explicitly states: "Note that even if T has size 0, the pointer must be properly aligned." [5] To summarize the requirements for core::ptr::read with a ZST: 1. The pointer is not required to be non-null [5][1]. 2. The pointer must be properly aligned for the type T [5]. It is important to distinguish "valid for reads" from "valid for zero-sized access." The general definition of "valid for reads/writes" in Rust explicitly excludes null pointers [1][6]. Core functions like core::ptr::read have specific exceptions documented for zero-sized accesses that allow null pointers, but these exceptions do not change the fact that null pointers are fundamentally invalid for general pointer dereferencing or conversion into references [1][2].

Citations:


🌐 Web query:

Rust std::alloc::alloc zero-sized type returns dangling pointer alignment requirement documentation

💡 Result:

In Rust, the behavior of std::alloc::alloc regarding zero-sized types (ZSTs) is strictly defined by the underlying requirements of the GlobalAlloc trait [1][2]. 1. Undefined Behavior: Passing a layout with a size of zero to std::alloc::alloc results in undefined behavior (UB) [1][3]. The documentation for GlobalAlloc explicitly states that the provided layout must have a non-zero size [1]. 2. No Allocation: Because zero-sized types do not require memory, calling an allocator is unnecessary and explicitly disallowed at this API level [4][5]. Collections or structures handling ZSTs are expected to avoid allocation entirely, typically by using a dangling, non-null, and well-aligned pointer (such as those provided by std::ptr::dangling) as a sentinel value [4][6][5]. 3. Alignment Requirement: While the allocator API requires non-zero size for the allocation request, the alignment of the layout is still enforced [1][7]. Even when representing a ZST (e.g., when a collection holds ZSTs), a valid Layout must have a non-zero alignment that is a power of two [7]. When using a dangling pointer for a ZST, the pointer must still satisfy the alignment requirements of the type it represents [6]. 4. Distinction from Allocator Trait: This constraint is specific to GlobalAlloc [1]. The unstable Allocator trait is more flexible and does permit zero-sized allocations; however, it is the responsibility of the allocator implementation to handle these cases (e.g., by returning a dangling pointer) [8][9]. To maintain compatibility and avoid unnecessary costs, even code using the Allocator trait is generally advised to avoid calling the allocator for ZSTs [10][8]. In summary, you must never call std::alloc::alloc with a zero-sized layout [1]. Instead, for ZSTs, use a sentinel value like std::ptr::dangling which is non-null and aligned according to the type's requirements [4][6].

Citations:


🌐 Web query:

Rust core::slice::from_raw_parts zero-sized type null pointer validity documentation

💡 Result:

In Rust, passing a null pointer to core::slice::from_raw_parts is undefined behavior (UB), regardless of the length of the slice or the size of the type T [1][2][3]. Even for zero-length slices or slices of zero-sized types (ZSTs), the provided pointer must be both non-null and properly aligned [1][3]. The requirement for non-null, aligned pointers exists because Rust references (including slices) are guaranteed to be non-null and aligned [1][3]. This invariant allows the compiler to perform optimizations—such as using a null pointer as a niche for Option<&[T]>—that would break if arbitrary pointers were allowed [1][3][4]. Violating this requirement is considered instant undefined behavior, not merely on-access undefined behavior [4]. For scenarios involving zero-length slices (such as when working with FFI code that may provide null pointers for empty collections), you must explicitly check for null before calling from_raw_parts [1][2][3]. If the pointer is null, you should use an empty slice literal (e.g., &[]) instead of calling the function [1][3]. If you need to construct a pointer that is safe to pass to from_raw_parts for a zero-length slice, you can use std::ptr::NonNull::dangling to obtain an aligned, non-null pointer [1][3][4].

Citations:


Use an aligned dangling pointer for zero-sized Vec<T>.

For T with size_of::<T>() == 0, grow() skips allocation and leaves self.data unchanged. On capacity growth from an empty vector, Vec::<()>::push() then converts that null pointer into a slice in as_slice() / as_mut_slice() and writes through it. In the pop() path, the new element is read from the same null pointer. Set self.data to an aligned dangling pointer in the zero-sized branch so push, pop, and other pointer-based methods use a non-null base pointer.

🤖 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 `@src/klib/vec.rs` around lines 40 - 47, Update the zero-sized-type branch in
grow() to initialize self.data with an aligned dangling pointer instead of
leaving it null. Preserve the existing no-allocation behavior while ensuring
as_slice, as_mut_slice, push, pop, and other pointer-based methods have a valid
non-null base pointer.

pub fn len(&self) -> usize { self.len }
pub fn is_empty(&self) -> bool { self.len == 0 }

Expand Down
10 changes: 10 additions & 0 deletions src/security/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ pub mod sigma_unveil;
pub mod vault;
pub mod vpn;
pub mod vulnerability;
pub mod kali_stack;
pub mod nemoclaw;
Comment on lines +28 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Fix the collection deallocator before making these modules public.

pub mod kali_stack and pub mod nemoclaw expose types backed by each module's local Vec. The Vec::grow and Drop paths call free, but free discards the pointer. Every growth and every dropped collection leaks its allocation.

Repeated calls to IptablesFirewall::add_rule, CronDaemon::register_job, or DefaultDenyNetworkPolicy::whitelist_endpoint can exhaust the process. Use the matching allocator/deallocator, or keep these modules private until the collection implementation is safe.

🤖 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 `@src/security/mod.rs` around lines 28 - 29, Fix the collection deallocation
logic in the `Vec::grow` and `Drop` implementations used by `kali_stack` and
`nemoclaw` before exposing either module publicly. Ensure each `free` path
actually releases the allocation with the matching allocator/deallocator,
including old buffers during growth and final buffers on drop; otherwise keep
`kali_stack` and `nemoclaw` private.


pub use self::sigma_pledge::{PledgeNamespace, PledgePromise as SigmaPledgePromise, SyscallFilter};
pub use self::sigma_unveil::{UnveilEntry, UnveilManager, UnveilPermissions, UnveilState};
Expand Down Expand Up @@ -101,3 +103,11 @@ pub use parrot_parity::{
AnonSurfShunt, AppSandboxEngine, ForensicStorageFilter, RoutingMode, SandboxPolicy,
GLOBAL_ANONSURF, GLOBAL_FORENSIC, GLOBAL_SANDBOX,
};
pub use kali_stack::{
CronDaemon, CronJob, DmesgLog, FirewallRule, IptablesFirewall, KaliError,
PluggableAuthenticationModule, SudoPrivilegeEscalation, SwapSpaceManager, TmuxMultiplexer,
TmuxPane,
};
Comment on lines +106 to +110

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Reject invalid protocol lengths before evaluating a firewall rule.

IptablesFirewall::evaluate_packet slices the four-byte FirewallRule.protocol with protocol.len(). A short value is compared as a prefix, and a value longer than four bytes panics. The public API can therefore apply the wrong rule or crash the process.

Normalize the protocol to one fixed representation and compare exact values before indexing.

🤖 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 `@src/security/mod.rs` around lines 106 - 110, Update
IptablesFirewall::evaluate_packet to validate FirewallRule.protocol as exactly
four bytes before evaluating the rule; reject shorter and longer values rather
than allowing prefix matches or panics. Normalize the protocol to a fixed
four-byte representation, then perform exact comparison before any indexing or
slicing.

🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

Remove unsynchronized mutation through &self.

The newly public DmesgLog::log_message casts self.buffer to *mut u8 and writes through it. buffer is not in UnsafeCell, and the atomic index does not synchronize the byte writes. Concurrent calls can race, and the raw write does not provide valid interior mutability.

Change the method to take &mut self, or add a synchronized interior-mutable buffer.

🤖 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 `@src/security/mod.rs` around lines 106 - 110, Update DmesgLog::log_message to
eliminate unsynchronized mutation through &self: either change it to require
&mut self and write through a valid mutable reference, or protect buffer with
synchronized interior mutability while preserving safe concurrent behavior.
Remove the raw *mut u8 cast and ensure the atomic index does not substitute for
synchronization of byte writes.

pub use nemoclaw::{
DefaultDenyNetworkPolicy, NemoClawError, OpenShellAgentSandbox, PrivacyRouter,
};
2 changes: 1 addition & 1 deletion src/security/pki.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ impl PKIManager for SimplePKIManager {

fn verify_certificate(&self, id: CertificateID, _issuer_id: CertificateID) -> Result<bool, PKIError> {
if let Some(cert) = self.get_certificate(id) {
if self.revoked.contains(id) {
if self.revoked.contains(&id) {
return Ok(false);
}
Ok(cert.is_valid())
Expand Down
13 changes: 5 additions & 8 deletions src/security/secrets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,10 @@ impl Keyring for SimpleKeyring {
}

fn get_secret_mut(&mut self, id: SecretID) -> Option<&mut Box<dyn Secret>> {
for i in 0..self.secrets.len() {
unsafe {
let slot = &mut *self.secrets.data.add(i);
if let Some(ref mut secret) = *slot {
if secret.id() == id {
return Some(secret);
}
for slot in self.secrets.iter_mut() {
if let Some(ref mut secret) = *slot {
if secret.id() == id {
return Some(secret);
}
}
}
Expand Down Expand Up @@ -400,7 +397,7 @@ mod tests {
let mut keyring = SimpleKeyring::new(cap);
let secret_cap = SecretCapability::full();
let secret = SimpleSecret::new(1, b"TestSecret", SecretType::APIKey, secret_cap);
let id = keyring.store_secret(Box::new(secret)).unwrap();
let id = keyring.add_secret(Box::new(secret)).unwrap();
assert_eq!(id, 1);

let retrieved = keyring.get_secret(1).unwrap();
Expand Down
3 changes: 2 additions & 1 deletion src/security/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,8 @@ impl EncryptedFileVault {
let mut files_processed = 0;
let mut bytes_processed = 0u64;

for (original_path, encrypted_file) in self.files.clone() {
let cloned_files: Vec<(PathBuf, EncryptedFile)> = self.files.iter().map(|(k, v)| (k.clone(), v.clone())).collect();
for (original_path, encrypted_file) in cloned_files {
Comment on lines +405 to +406

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make master-key rotation transactional.

This snapshot loop writes each file with new_key before Line [439] updates self.master_key. If a later decrypt, encrypt, or write fails, earlier files already contain new-key ciphertext and new IV/tag metadata, but the vault still decrypts with the old key. retrieve_file then fails for those files, and a retry cannot recover them.

Stage ciphertext and metadata in temporary files. Commit all changes and self.master_key only after every file succeeds. Roll back on failure.

🤖 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 `@src/security/vault.rs` around lines 405 - 406, Make the master-key rotation
flow transactional around the cloned_files loop and self.master_key update:
write each re-encrypted file and metadata to temporary files, preserving
originals until every decrypt, encrypt, and write succeeds. Commit the staged
replacements and update self.master_key only after the full batch completes; on
any failure, remove temporary files and leave both original files and the
in-memory key unchanged so retrieve_file and retries continue to work.

// Decrypt with old key
let encrypted_data = std::fs::read(&encrypted_file.encrypted_path)
.map_err(|e| VaultError::IoError(e.to_string()))?;
Expand Down
2 changes: 0 additions & 2 deletions src/sigpkg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pub mod arch_compat;
pub mod aur;
pub mod importer;
pub mod linux_compat;
pub mod importer;
pub mod pacman;
pub mod recipe;
pub mod resolver;
Expand All @@ -26,7 +25,6 @@ pub use linux_compat::{
DebianPackageTranslator, LinuxPackageCompatManager, LinuxPackageType, RpmPackageTranslator,
TranslatedMetadata, TranslatorError,
};
pub use importer::{PackageImporter, DebPackageImporter, RpmPackageImporter, PacmanPackageImporter};
pub use pacman::{MakePkgEngine, PacmanError, PacmanManager, PkgBuildScript};
pub use recipe::{BuildSystem, PackageRecipe, RecipeError, RecipeManager};
pub use resolver::SatSolver;
Expand Down