Skip to content

Commit 7e986a3

Browse files
committed
security: SDK-wide audit fixes — remove token logging, fix XSS, harden passkeys
- OAuthManager: wrap JWT payload NSLog in #if DEBUG (was logging to system log in release) - PasskeyHelper: rpId missing now throws error instead of falling back to "localhost" - profile.ts: validate avatarUrl is http(s) + escape quotes (prevent javascript:/data: XSS) - Centralize User-Agent version string to single authonSwiftVersion constant
1 parent 4e7078c commit 7e986a3

5 files changed

Lines changed: 13 additions & 6 deletions

File tree

packages/js/src/profile.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,9 @@ export class ProfileRenderer {
291291
.slice(0, 2)
292292
.join('');
293293

294-
const avatarHtml = u.avatarUrl
295-
? `<img class="avatar-img" src="${u.avatarUrl}" alt="${u.displayName || ''}" />`
294+
const safeAvatarUrl = u.avatarUrl && /^https?:\/\//i.test(u.avatarUrl) ? u.avatarUrl : null;
295+
const avatarHtml = safeAvatarUrl
296+
? `<img class="avatar-img" src="${safeAvatarUrl.replace(/"/g, '&quot;')}" alt="${(u.displayName || '').replace(/"/g, '&quot;')}" />`
296297
: `<div class="avatar-placeholder">${initials}</div>`;
297298

298299
const closeBtn = this.mode === 'popup'

swift/Sources/Authon/Authon.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -650,7 +650,7 @@ public final class Authon: ObservableObject {
650650
req.httpMethod = method
651651
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
652652
req.setValue(api.publishableKey, forHTTPHeaderField: "x-api-key")
653-
req.setValue("authon-swift/0.3.1", forHTTPHeaderField: "User-Agent")
653+
req.setValue("authon-swift/\(authonSwiftVersion)", forHTTPHeaderField: "User-Agent")
654654

655655
if let body {
656656
let encoder = JSONEncoder()

swift/Sources/Authon/AuthonAPI.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Foundation
22

3+
let authonSwiftVersion = "0.3.1"
4+
35
final class AuthonAPI: Sendable {
46
let publishableKey: String
57
let apiURL: String
@@ -51,7 +53,7 @@ final class AuthonAPI: Sendable {
5153
req.httpMethod = method
5254
req.setValue("application/json", forHTTPHeaderField: "Content-Type")
5355
req.setValue(publishableKey, forHTTPHeaderField: "x-api-key")
54-
req.setValue("authon-swift/0.3.1", forHTTPHeaderField: "User-Agent")
56+
req.setValue("authon-swift/\(authonSwiftVersion)", forHTTPHeaderField: "User-Agent")
5557

5658
if let accessToken {
5759
req.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")

swift/Sources/Authon/OAuthManager.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,13 @@ extension OAuthManager: ASAuthorizationControllerDelegate, ASAuthorizationContro
229229
}
230230

231231
private func exchangeAppleToken(identityToken: String) async throws -> ApiAuthResponse {
232-
// Decode JWT to check audience
232+
#if DEBUG
233+
// Debug-only: decode JWT to inspect audience (never log tokens in release builds)
233234
let parts = identityToken.split(separator: ".")
234235
if parts.count >= 2, let data = Data(base64Encoded: String(parts[1]).padding(toLength: ((parts[1].count + 3) / 4) * 4, withPad: "=", startingAt: 0)) {
235236
NSLog("[Authon-Apple] token payload: %@", String(data: data, encoding: .utf8) ?? "?")
236237
}
238+
#endif
237239

238240
struct NativeOAuthRequest: Encodable {
239241
let provider: String

swift/Sources/Authon/PasskeyHelper.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,9 @@ final class PasskeyHelper: NSObject, ASAuthorizationControllerDelegate, ASAuthor
125125
throw AuthonError(statusCode: 400, message: "Invalid challenge", code: "invalid_challenge")
126126
}
127127

128-
let rpId = options.rpId ?? "localhost"
128+
guard let rpId = options.rpId, !rpId.isEmpty else {
129+
throw AuthonError(statusCode: 400, message: "Server did not provide rpId for passkey authentication", code: "missing_rp_id")
130+
}
129131
let provider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: rpId)
130132
let request = provider.createCredentialAssertionRequest(challenge: challengeData)
131133

0 commit comments

Comments
 (0)