Skip to content
Merged
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
16 changes: 8 additions & 8 deletions SECURITY_DEFER.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Description: The current Argon2id memory cost is set to 64MB (m_cost=65536). Sec
Why not fixed: no-touch zone
Suggested fix: Update Argon2id Params in derive_key and derive_key_v3 to use m_cost=262144.
First detected: 2026-05-09
Last attempted: 2026-05-23
Attempt count: 2
Last attempted: 2026-06-06
Attempt count: 3
---
[UNEXPECTED_PANICS] - Unhandled unwrap() calls in crypto-adjacent paths
Severity: Medium
Expand All @@ -15,8 +15,8 @@ Description: Multiple uses of .unwrap() or .unwrap_or_else() on locks/IO results
Why not fixed: no-touch zone
Suggested fix: Replace .unwrap() with proper error handling using CryptoError or .expect() with descriptive panic messages.
First detected: 2026-05-09
Last attempted: 2026-05-23
Attempt count: 2
Last attempted: 2026-06-06
Attempt count: 3
---
[RUSTSEC-2024-0436] - Unmaintained dependency: paste
Severity: Medium
Expand All @@ -25,8 +25,8 @@ Description: The `paste` crate is no longer maintained. While it's a macro-utili
Why not fixed: no-touch zone (Cargo.lock modification restricted)
Suggested fix: Replace `paste` with `pastey` or `with_builtin_macros`.
First detected: 2026-05-09
Last attempted: 2026-05-23
Attempt count: 2
Last attempted: 2026-06-06
Attempt count: 3
---
[TMP_PATH_FALLBACK] - Unsafe fallback in tmp_path for paths without filenames
Severity: Medium
Expand All @@ -35,6 +35,6 @@ Description: In `tmp_path`, if the destination path lacks a filename (e.g., root
Why not fixed: no-touch zone
Suggested fix: Provide a safe fallback filename like "output" or "file" when `file_name()` is None.
First detected: 2026-05-23
Last attempted: 2026-05-23
Attempt count: 1
Last attempted: 2026-06-06
Attempt count: 2
---
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import com.neuronencrypt.app.ui.theme.*
@Composable
fun HomeScreen(
onEncryptDecrypt: () -> Unit,
onBatch: () -> Unit
onBatch: () -> Unit,
onAbout: () -> Unit
) {
var showAbout by remember { mutableStateOf(false) }

Expand Down Expand Up @@ -104,7 +105,10 @@ fun HomeScreen(

Spacer(modifier = Modifier.height(32.dp))

TextButton(onClick = { showAbout = true }) {
TextButton(onClick = {
onAbout()
showAbout = true
}) {
Text(
text = "About",
style = MaterialTheme.typography.bodySmall,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.material3.*
import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand Down
20 changes: 14 additions & 6 deletions android/neuron-encrypt-jni/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::fs::File;
use std::io::{self, Read, Seek};
use std::os::fd::{FromRawFd, RawFd};
use std::panic::{self, AssertUnwindSafe};
use std::sync::Arc;

use jni::JNIEnv;
use jni::objects::{GlobalRef, JByteArray, JClass, JObject};
Expand All @@ -20,7 +21,7 @@ const CANCELLED_IO_MESSAGE: &str = "operation cancelled";
struct CancelableReader {
inner: File,
cancel: GlobalRef,
vm: JavaVM,
vm: Arc<JavaVM>,
}

impl CancelableReader {
Expand Down Expand Up @@ -62,7 +63,7 @@ impl Seek for CancelableReader {

struct JniReporter {
listener: GlobalRef,
vm: JavaVM,
vm: Arc<JavaVM>,
}

impl ProgressReporter for JniReporter {
Expand Down Expand Up @@ -101,9 +102,14 @@ fn map_error(env: &mut JNIEnv, err: CryptoError) -> jint {
| CryptoError::InvalidDestination(_)
| CryptoError::SourceAndDestinationSame(_)
| CryptoError::NotAFile(_)
| CryptoError::InvalidSaltLength { .. }
| CryptoError::InvalidNonceLength { .. }
| CryptoError::FileTooLarge { .. } => (2, "Invalid input or output file.".to_owned()),

CryptoError::Io(_) => (1, "Storage I/O failed.".to_owned()),
CryptoError::LegacyFileTooLarge => {
(1, "Legacy file too large for this operation.".to_owned())
}
CryptoError::Argon2Failed(_)
| CryptoError::HkdfFailed(_)
| CryptoError::EncryptionFailed(_) => (1, "Cryptographic operation failed.".to_owned()),
Expand Down Expand Up @@ -174,15 +180,16 @@ fn native_encrypt_impl(
let input_file = unsafe { File::from_raw_fd(input_fd as RawFd) };
let mut output_file = unsafe { File::from_raw_fd(output_fd as RawFd) };

let vm = Arc::new(vm);
let mut reader = CancelableReader {
inner: input_file,
cancel: cancel_ref,
vm: vm.clone(),
vm: Arc::clone(&vm),
};

let reporter = JniReporter {
listener: listener_ref,
vm,
vm: Arc::clone(&vm),
};
let throttled = ThrottledReporter::new(&reporter);

Expand Down Expand Up @@ -249,15 +256,16 @@ fn native_decrypt_impl(
let input_file = unsafe { File::from_raw_fd(input_fd as RawFd) };
let mut output_file = unsafe { File::from_raw_fd(output_fd as RawFd) };

let vm = Arc::new(vm);
let mut reader = CancelableReader {
inner: input_file,
cancel: cancel_ref,
vm: vm.clone(),
vm: Arc::clone(&vm),
};

let reporter = JniReporter {
listener: listener_ref,
vm,
vm: Arc::clone(&vm),
};
let throttled = ThrottledReporter::new(&reporter);

Expand Down
2 changes: 1 addition & 1 deletion audit_output.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"database":{"advisory-count":1098,"last-commit":"130152155e1184c441b0e6924d21d7cbfb23f297","last-updated":"2026-05-22T12:09:18+02:00"},"lockfile":{"dependency-count":537},"settings":{"target_arch":[],"target_os":[],"severity":null,"ignore":[],"informational_warnings":["unmaintained","unsound","notice"]},"vulnerabilities":{"found":false,"count":0,"list":[]},"warnings":{"unmaintained":[{"kind":"unmaintained","package":{"name":"paste","version":"1.0.15","source":"registry+https://github.com/rust-lang/crates.io-index","checksum":"57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a","replace":null},"advisory":{"id":"RUSTSEC-2024-0436","package":"paste","title":"paste - no longer maintained","description":"The creator of the crate `paste` has stated in the [`README.md`](https://github.com/dtolnay/paste/blob/master/README.md) \nthat this project is not longer maintained as well as archived the repository\n\n## Possible Alternative(s)\n\n- [`pastey`]: a fork of paste and is aimed to be a drop-in replacement with additional features for paste crate\n- [`with_builtin_macros`]: crate providing a [superset of `paste`'s functionality including general `macro_rules!` eager expansions](https://docs.rs/with_builtin_macros/0.1.0/with_builtin_macros/macro.with_eager_expansions.html) and `concat!`/`concat_idents!` macros\n\n[`pastey`]: https://crates.io/crates/pastey\n[`with_builtin_macros`]: https://crates.io/crates/with_builtin_macros","date":"2024-10-07","aliases":[],"related":[],"collection":"crates","categories":[],"keywords":[],"cvss":null,"informational":"unmaintained","references":[],"source":null,"url":"https://github.com/dtolnay/paste","withdrawn":null,"license":"CC0-1.0","expect-deleted":false},"affected":null,"versions":{"patched":[],"unaffected":[]}}]}}
{"database":{"advisory-count":1121,"last-commit":"8fe151aab7c88bcc98f809982cc84ee7b0ba39a6","last-updated":"2026-06-06T16:44:53+02:00"},"lockfile":{"dependency-count":531},"settings":{"target_arch":[],"target_os":[],"severity":null,"ignore":[],"informational_warnings":["unmaintained","unsound","notice"]},"vulnerabilities":{"found":false,"count":0,"list":[]},"warnings":{"unmaintained":[{"kind":"unmaintained","package":{"name":"paste","version":"1.0.15","source":"registry+https://github.com/rust-lang/crates.io-index","checksum":"57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a","replace":null},"advisory":{"id":"RUSTSEC-2024-0436","package":"paste","title":"paste - no longer maintained","description":"The creator of the crate `paste` has stated in the [`README.md`](https://github.com/dtolnay/paste/blob/master/README.md) \nthat this project is not longer maintained as well as archived the repository\n\n## Possible Alternative(s)\n\n- [`pastey`]: a fork of paste and is aimed to be a drop-in replacement with additional features for paste crate\n- [`with_builtin_macros`]: crate providing a [superset of `paste`'s functionality including general `macro_rules!` eager expansions](https://docs.rs/with_builtin_macros/0.1.0/with_builtin_macros/macro.with_eager_expansions.html) and `concat!`/`concat_idents!` macros\n\n[`pastey`]: https://crates.io/crates/pastey\n[`with_builtin_macros`]: https://crates.io/crates/with_builtin_macros","date":"2024-10-07","aliases":[],"related":[],"collection":"crates","categories":[],"keywords":[],"cvss":null,"informational":"unmaintained","references":[],"source":null,"url":"https://github.com/dtolnay/paste","withdrawn":null,"license":"CC0-1.0","expect-deleted":false},"affected":null,"versions":{"patched":[],"unaffected":[]}}]}}
14 changes: 10 additions & 4 deletions neuron-encrypt/src/bin/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,17 @@ enum Command {

fn read_password(password_file: &Option<PathBuf>) -> Zeroizing<String> {
if let Some(path) = password_file {
let pw = fs::read_to_string(path).unwrap_or_else(|e| {
let bytes = fs::read(path).unwrap_or_else(|e| {
eprintln!("Error: Cannot read password file: {e}");
std::process::exit(ExitCode::BadInput as i32);
});
return Zeroizing::new(pw.trim_end_matches(&['\r', '\n'][..]).to_owned());
let mut pw = Zeroizing::new(String::from_utf8(bytes).unwrap_or_else(|e| {
eprintln!("Error: Password file contains invalid UTF-8: {e}");
std::process::exit(ExitCode::BadInput as i32);
}));
let trimmed_len = pw.trim_end_matches(&['\r', '\n'][..]).len();
pw.truncate(trimmed_len);
return pw;
}

if let Ok(pw) = std::env::var("NEURON_PASSWORD") {
Expand Down Expand Up @@ -397,9 +403,9 @@ fn emit_json(result: &JsonResult) {
fn compute_sha256(path: &Path) -> Result<String, String> {
let mut file = fs::File::open(path).map_err(|e| e.to_string())?;
let mut hasher = Sha256::new();
let mut buf = [0u8; 65536];
let mut buf = Zeroizing::new([0u8; 65536]);
loop {
let n = file.read(&mut buf).map_err(|e| e.to_string())?;
let n = file.read(&mut *buf).map_err(|e| e.to_string())?;
if n == 0 {
break;
}
Expand Down
4 changes: 2 additions & 2 deletions neuron-encrypt/src/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ use zeroize::Zeroizing;
fn compute_sha256(path: &Path) -> Option<String> {
let mut file = fs::File::open(path).ok()?;
let mut hasher = Sha256::new();
let mut buf = [0u8; 65536];
let mut buf = Zeroizing::new([0u8; 65536]);
loop {
let n = file.read(&mut buf).ok()?;
let n = file.read(&mut *buf).ok()?;
if n == 0 {
break;
}
Expand Down
Loading