diff --git a/README.md b/README.md index 50d8cd1..66d2b04 100644 --- a/README.md +++ b/README.md @@ -61,4 +61,4 @@ Because secrets in the Secure Enclave are not exportable, they are not able to b ## Security -If you discover any vulnerabilities in this project, please notify [max.goedjen@gmail.com](mailto:max.goedjen@gmail.com) with the subject containing "SECRETIVE SECURITY." +Secretive's security policy is detailed in [SECURITY.md](SECURITY.md). To report security issues, please use [GitHub's private reporting feature.](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) diff --git a/SECURITY.md b/SECURITY.md index 94d1da3..63412c6 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -24,4 +24,4 @@ The latest version on the [Releases page](https://github.com/maxgoedjen/secretiv ## Reporting a Vulnerability -If you discover any vulnerabilities in this project, please notify max.goedjen@gmail.com with the subject containing "SECRETIVE SECURITY." +To report security issues, please use [GitHub's private reporting feature.](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) diff --git a/Sources/Packages/Sources/SecretAgentKit/Agent.swift b/Sources/Packages/Sources/SecretAgentKit/Agent.swift index cd5bfa1..8851127 100644 --- a/Sources/Packages/Sources/SecretAgentKit/Agent.swift +++ b/Sources/Packages/Sources/SecretAgentKit/Agent.swift @@ -89,9 +89,8 @@ extension Agent { for secret in secrets { let keyBlob = publicKeyWriter.data(secret: secret) - let curveData = publicKeyWriter.openSSHIdentifier(for: secret.keyType) keyData.append(keyBlob.lengthAndData) - keyData.append(curveData.lengthAndData) + keyData.append(publicKeyWriter.comment(secret: secret).lengthAndData) count += 1 if let (certificateData, name) = try? await certificateHandler.keyBlobAndName(for: secret) { diff --git a/Sources/Packages/Sources/SecretAgentKit/SocketController.swift b/Sources/Packages/Sources/SecretAgentKit/SocketController.swift index 0f592a0..19b040a 100644 --- a/Sources/Packages/Sources/SecretAgentKit/SocketController.swift +++ b/Sources/Packages/Sources/SecretAgentKit/SocketController.swift @@ -78,7 +78,6 @@ extension SocketController { provenance = SigningRequestTracer().provenance(from: fileHandle) (messages, messagesContinuation) = AsyncStream.makeStream() Task { [messagesContinuation, logger] in - await fileHandle.waitForDataInBackgroundAndNotifyOnMainActor() for await _ in NotificationCenter.default.notifications(named: .NSFileHandleDataAvailable, object: fileHandle) { let data = fileHandle.availableData guard !data.isEmpty else { @@ -91,6 +90,9 @@ extension SocketController { logger.debug("Socket controller yielded data.") } } + Task { + await fileHandle.waitForDataInBackgroundAndNotifyOnMainActor() + } } /// Writes new data to the socket. diff --git a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift index 2c7f446..99713e0 100644 --- a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift +++ b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift @@ -31,18 +31,7 @@ public struct OpenSSHPublicKeyWriter: Sendable { /// Generates an OpenSSH string representation of the secret. /// - Returns: OpenSSH string representation of the secret. public func openSSHString(secret: SecretType) -> String { - let resolvedComment: String - if let comment = secret.publicKeyAttribution { - resolvedComment = comment - } else { - let dashedKeyName = secret.name.replacingOccurrences(of: " ", with: "-") - let dashedHostName = ["secretive", Host.current().localizedName, "local"] - .compactMap { $0 } - .joined(separator: ".") - .replacingOccurrences(of: " ", with: "-") - resolvedComment = "\(dashedKeyName)@\(dashedHostName)" - } - return [openSSHIdentifier(for: secret.keyType), data(secret: secret).base64EncodedString(), resolvedComment] + return [openSSHIdentifier(for: secret.keyType), data(secret: secret).base64EncodedString(), comment(secret: secret)] .compactMap { $0 } .joined(separator: " ") } @@ -65,6 +54,19 @@ public struct OpenSSHPublicKeyWriter: Sendable { .joined(separator: ":") } + public func comment(secret: SecretType) -> String { + if let comment = secret.publicKeyAttribution { + return comment + } else { + let dashedKeyName = secret.name.replacingOccurrences(of: " ", with: "-") + let dashedHostName = ["secretive", Host.current().localizedName, "local"] + .compactMap { $0 } + .joined(separator: ".") + .replacingOccurrences(of: " ", with: "-") + return "\(dashedKeyName)@\(dashedHostName)" + } + + } } extension OpenSSHPublicKeyWriter { diff --git a/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift b/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift index 71bb426..49983d2 100644 --- a/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift +++ b/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift @@ -26,7 +26,8 @@ public final class PublicKeyFileStoreController: Sendable { let untracked = Set(fullPathContents) .subtracting(validPaths) for path in untracked { - try? FileManager.default.removeItem(at: URL(fileURLWithPath: path)) + // string instead of fileURLWithPath since we're already using fileURL format. + try? FileManager.default.removeItem(at: URL(string: path)!) } } try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: false, attributes: nil) diff --git a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift index c57b712..433759d 100644 --- a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift +++ b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift @@ -26,7 +26,7 @@ extension SecureEnclave { for await note in DistributedNotificationCenter.default().notifications(named: .secretStoreUpdated) { guard Constants.notificationToken != (note.object as? String) else { // Don't reload if we're the ones triggering this by reloading. - return + continue } reloadSecrets() } @@ -112,7 +112,7 @@ extension SecureEnclave { var accessError: SecurityError? let flags: SecAccessControlCreateFlags = switch attributes.authentication { case .notRequired: - [] + [.privateKeyUsage] case .presenceRequired: [.userPresence, .privateKeyUsage] case .biometryCurrent: diff --git a/Sources/Secretive/Views/Secrets/EditSecretView.swift b/Sources/Secretive/Views/Secrets/EditSecretView.swift index 0b2a6fc..80f5af0 100644 --- a/Sources/Secretive/Views/Secrets/EditSecretView.swift +++ b/Sources/Secretive/Views/Secrets/EditSecretView.swift @@ -54,9 +54,7 @@ struct EditSecretView: View { func rename() { var attributes = secret.attributes - if !publicKeyAttribution.isEmpty { - attributes.publicKeyAttribution = publicKeyAttribution - } + attributes.publicKeyAttribution = publicKeyAttribution.isEmpty ? nil : publicKeyAttribution Task { do { try await store.update(secret: secret, name: name, attributes: attributes)