1
0
forked from GRIN/grim

goblin: mark deferred audit items (M5, M6, L2, L3, L4) with TODO tags

Comments only, no behavior change: tag the five deferred audit findings at the
code they refer to so they are findable later. M5 (widen display escaping to
category-based) and M6 (template echo vs re-serialization) in authuri; L2
(redact secrets from Debug) at NostrIdentity; L3 (carry secrets as ZeroingString
end-to-end) at get_nostr_nsec; L4 (reset AdvancedState on back) in the goblin
on_back handler.
This commit is contained in:
2ro
2026-07-06 08:02:12 -04:00
parent 729ee70f9f
commit 98cd32f15e
4 changed files with 9 additions and 0 deletions
+2
View File
@@ -664,6 +664,8 @@ impl GoblinWalletView {
if self.settings_page == SettingsPage::Identities {
self.identity_switch = IdentitySwitchState::default();
}
// TODO(audit L4): reset AdvancedState on back navigation too, so a
// revealed nsec/password does not survive leaving the Advanced page.
self.settings_page = SettingsPage::Main;
return false;
}
+4
View File
@@ -300,6 +300,8 @@ pub(crate) fn domain_bound(callback: &str, domain: &str) -> bool {
/// arrays of strings. A `delegation` tag is rejected outright (defense in depth,
/// even though delegation tokens are unreachable here). Any deviation rejects.
fn validate_template(raw: &str) -> Option<Template> {
// TODO(audit M6): consider byte-exact template echo vs structural
// re-serialization; needs magick server co-design.
// Percent-decode for parity with the other params (base64url never needs
// encoding, so this is a no-op on well-formed input), then enforce the
// strict unpadded-base64url charset ourselves.
@@ -478,6 +480,8 @@ pub fn content_preview(content: &str) -> (String, usize) {
/// passes through unchanged. Used on ALL requester-controlled strings (content,
/// tag values, titles) before they reach a label.
pub fn escape_for_display(s: &str) -> String {
// TODO(audit M5): widen escaping to category-based (all C0/C1, bidi controls)
// rather than the current explicit list.
let mut out = String::with_capacity(s.len());
for c in s.chars() {
let code = c as u32;
+1
View File
@@ -38,6 +38,7 @@ pub enum IdentitySource {
}
/// Identity file stored at `wallet_data/nostr/identity.json`.
// TODO(audit L2): redact secret material (the ncryptsec) from Debug output.
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NostrIdentity {
pub ver: u8,
+2
View File
@@ -588,6 +588,8 @@ impl Wallet {
/// wrong password can never leak the key. The value is derived on demand and
/// never persisted.
pub fn get_nostr_nsec(&self, password: String) -> Result<String, String> {
// TODO(audit L3): carry secrets (the password and the returned nsec) as
// ZeroingString end-to-end rather than plain String.
let svc = self
.nostr_service()
.ok_or_else(|| "nostr identity not ready".to_string())?;