Unofficial Draft
Copyright © 2025 the document editors/authors. Text is available under the Creative Commons Attribution 4.0 International Public License; additional terms may apply.
The objective of this API is to enable smart card (PC/SC) applications to move to the Web Platform. It gives them access to the PC/SC implementation (and card reader drivers) available in the host OS. There is also a companion explainer document.
This document is a draft of a potential specification. It has no official standing of any kind and does not represent the support or consensus of any standards organization.
WebIDL[Exposed=(DedicatedWorker, SharedWorker, Window), SecureContext, IsolatedContext]
interface SmartCardResourceManager {
Promise<SmartCardContext> establishContext();
};
Methods on this interface complete asynchronously, queuing work on the smart card task source.
Requests a PC/SC context from the platform's PC/SC stack.
TheestablishContext() method steps are:
SecurityError" DOMException.
RESOURCEMANAGER class.EstablishContext method of resourceManager with
a "system" Scope parameter.RESPONSECODE is not SCARD_S_SUCCESS, perform
the following steps:
corresponding
exception.SmartCardContext whose
[[resourceManager]] internal slot is set
to resourceManager.A context for communicating with the PC/SC resource manager.
WebIDL[Exposed=(DedicatedWorker, SharedWorker, Window), SecureContext, IsolatedContext]
interface SmartCardContext {
Promise<sequence<DOMString>> listReaders();
Promise<sequence<SmartCardReaderStateOut>> getStatusChange(
sequence<SmartCardReaderStateIn> readerStates,
optional SmartCardGetStatusChangeOptions options = {});
Promise<SmartCardConnectResult> connect(
DOMString readerName,
SmartCardAccessMode accessMode,
optional SmartCardConnectOptions options = {});
};
Instances of SmartCardContext are created with the internal slots
described in the following table:
| Internal slot | Initial value | Description (non-normative) |
|---|---|---|
| [[resourceManager]] | null |
The platform's [PCSC5] RESOURCEMANAGER to be used. |
| [[operationInProgress]] | false |
Whether there is an ongoing PC/SC operation in this context. |
| [[connections]] | An empty ordered set | The existing SmartCardConnections created by this context. |
| [[tracker]] | null |
A [PCSC5] SCARDTRACK instance. |
| [[signal]] | null |
The AbortSignal of the outstanding
getStatusChange() call, if any. |
The listReaders() method steps
are:
[[operationInProgress]] is
true, reject promise with a "InvalidStateError"
DOMException and return promise.[[operationInProgress]] to
true.RESOURCEQUERY class, with
this.[[resourceManager]] as its
constructor input parameter.STR[]
containing the list of group names that is equivalent to "all
readers in the system" in that platform.
STR[].
ListReaders method of resourceQuery with
groups as input and pcscReaders as output parameters.RESPONSECODE.SCARD_S_SUCCESS:
SCARD_E_NO_READERS_AVAILABLE,
resolve promise with an empty sequence of
DOMString.
corresponding to
responseCode.sequence of
DOMString equivalent to pcscReaders.The getStatusChange(readerStates, options) method steps
are:
[[operationInProgress]] is
true, reject promise with a "InvalidStateError"
DOMException and return promise.signal"]
exists, run the following steps:
signal"].[[signal]] to signalCancel the outstanding GetStatusChange algorithm to signal.DWORD set to [PCSC5]
INFINITE.timeout"]
exists, set pcscTimeout to
options["timeout"].SCARD_READERSTATE[] corresponding to
readerStates.[[operationInProgress]] to
true.[[tracker]] to a new instance of the
platform's [PCSC5] SCARDTRACK class, with
this.[[resourceManager]] as its
constructor input parameter.[[tracker]].GetStatusChange()
with pcscReaderStates and pcscTimeout as input parameters.RESPONSECODE.[[tracker]] to null.undefined.[[signal]] is not null,
run the following steps:
[[signal]] is
aborted then set abortReason to
this.[[signal]]'s
abort reason.cancel the outstanding GetStatusChange algorithm from
this.[[signal]].[[signal]] to
null.SCARD_S_SUCCESS, run the
following steps:
SCARD_E_CANCELLED and
abortReason is not undefined then reject
promise with abortReason.corresponding to responseCode.SmartCardReaderStateOut
corresponding to
pcscReaderStates.WebIDLdictionary SmartCardReaderStateIn {
required DOMString readerName;
required SmartCardReaderStateFlagsIn currentState;
unsigned long currentCount;
};
readerName membercurrentState membercurrentCount memberGiven a sequence of SmartCardReaderStateIn named
readerStates, a
corresponding
[PCSC5] SCARD_READERSTATE[] is created with the following
steps:
SCARD_READERSTATE[].SCARD_READERSTATE.Reader to
stateIn["readerName"].CurrentState to the DWORD
corresponding
to stateIn["currentState"].currentCount"]
exists, set the high word of
pcscState.CurrentState to
stateIn["currentCount"].EventState to zero.WebIDLdictionary SmartCardReaderStateFlagsIn {
boolean unaware = false;
boolean ignore = false;
boolean empty = false;
boolean present = false;
boolean exclusive = false;
boolean inuse = false;
boolean mute = false;
boolean unpowered = false;
};
unaware memberignore memberunavailable memberempty memberpresent memberexclusive memberinuse membermute memberunpowered memberThe [PCSC5] DWORD
corresponding
to a given SmartCardReaderStateFlagsIn is created with the
following steps:
SmartCardReaderStateFlagsIn.DWORD set to zero.unaware"] is
true, add [PCSC5] SCARD_STATE_UNAWARE to
pcscFlags.ignore"] is
true, add [PCSC5] SCARD_STATE_IGNORE to
pcscFlags.unavailable"]
is true, add [PCSC5]
SCARD_STATE_UNAVAILABLE to pcscFlags.empty"] is
true, add [PCSC5] SCARD_STATE_EMPTY to
pcscFlags.present"] is
true, add [PCSC5] SCARD_STATE_PRESENT to
pcscFlags.exclusive"] is
true, add [PCSC5] SCARD_STATE_EXCLUSIVE to
pcscFlags.inuse"] is
true, add [PCSC5] SCARD_STATE_INUSE to
pcscFlags.mute"] is
true, add SCARD_STATE_MUTE to
pcscFlags.
unpowered"] is
true, add SCARD_STATE_UNPOWERED to
pcscFlags.The actual state of a smart card reader.
WebIDLdictionary SmartCardReaderStateOut {
required DOMString readerName;
required SmartCardReaderStateFlagsOut eventState;
required unsigned long eventCount;
ArrayBuffer answerToReset;
};
readerName membereventState membereventCount memberanswerToReset memberGiven a [PCSC5] SCARD_READERSTATE[] named
pcscReaderStates, a corresponding sequence of
SmartCardReaderStateOut is created with the following steps:
SmartCardReaderStateOut.SmartCardReaderStateOut.readerName"] to
pcscState.Reader.eventState"] to
the SmartCardReaderStateFlagsOut dictionary
corresponding
to pcscState.EventState.eventCount"] to
the high word of pcscState.EventState.
SCARD_READERSTATE structure has a member
containing the card's [ISO7186-3] Answer To Reset, set
stateOut["answerToReset"] to
that value.WebIDLdictionary SmartCardReaderStateFlagsOut {
boolean ignore = false;
boolean changed = false;
boolean unknown = false;
boolean empty = false;
boolean present = false;
boolean exclusive = false;
boolean inuse = false;
boolean mute = false;
boolean unpowered = false;
};
ignore memberchanged memberunavailable memberunknown memberempty memberpresent memberexclusive memberinuse membermute memberunpowered memberGiven a [PCSC5] DWORD named pcscFlags, a corresponding
SmartCardReaderStateFlagsOut dictionary is created with the
following steps:
SmartCardReaderStateFlagsOut dictionary with default members.SCARD_STATE_IGNORE, set
flagsOut["ignore"] to
true.SCARD_STATE_CHANGED, set
flagsOut["changed"] to
true.SCARD_STATE_UNAVAILABLE, set
flagsOut["unavailable"] to
true.SCARD_STATE_UNKNOWN, set
flagsOut["unknown"] to
true.SCARD_STATE_EMPTY, set
flagsOut["empty"] to
true.SCARD_STATE_PRESENT, set
flagsOut["present"] to
true.SCARD_STATE_EXCLUSIVE, set
flagsOut["exclusive"] to
true.SCARD_STATE_INUSE, set
flagsOut["inuse"] to
true.SCARD_STATE_MUTE, set
flagsOut["mute"] to
true.SCARD_STATE_UNPOWERED, set
flagsOut["unpowered"] to
true.WebIDLdictionary SmartCardGetStatusChangeOptions {
DOMHighResTimeStamp timeout;
AbortSignal signal;
};
timeout membersignal memberThe connect(readerName, accessMode, options)
method steps are:
[[operationInProgress]] is
true, reject promise with a "InvalidStateError"
DOMException and return promise.[[operationInProgress]] to
true.DWORD
corresponding to
accessMode.DWORD set to 0.preferredProtocols"]
exists, set protocolFlags to its
corresponding flags.DWORD set to 0.SCARDCOMM class, with
this.[[resourceManager]] as its
constructor parameter.Connect() with readerName, accessFlags
and protocolFlags as input and activeProtocol as output parameters.RESPONSECODE.SCARD_S_SUCCESS:
corresponding to responseCode and abort these steps.SmartCardConnectResult dictionary.SmartCardConnection.[[connections]].[[comm]] to comm.
[[context]] to
this.
[[activeProtocol]] to
activeProtocol.
connection"] to
connection.activeProtocol"] to the
corresponding SmartCardProtocol.WebIDLenum SmartCardProtocol {
"raw",
"t0",
"t1"
};
rawSCARD_PROTOCOL_RAW DWORD.t0SCARD_PROTOCOL_T0 DWORD.t1SCARD_PROTOCOL_T1
DWORD.A [PCSC5] DWORD is a valid protocol value if it is either
[PCSC5] SCARD_PROTOCOL_T0, [PCSC5] SCARD_PROTOCOL_T1 or
[PCSC5] SCARD_PROTOCOL_RAW.
Given a sequence of SmartCardProtocol named
protocols, a [PCSC5] DWORD
with the corresponding
flags is created with the following steps:
WebIDLdictionary SmartCardConnectResult {
required SmartCardConnection connection;
SmartCardProtocol activeProtocol;
};
connection memberactiveProtocol memberWebIDLenum SmartCardAccessMode {
"shared",
"exclusive",
"direct"
};
sharedexclusivedirectGiven a SmartCardAccessMode enum named
accessMode, a corresponding [PCSC5]
DWORD is created with the following steps:
WebIDLdictionary SmartCardConnectOptions {
sequence<SmartCardProtocol> preferredProtocols;
};
preferredProtocolsTo clear the operationInProgress of a
SmartCardContext context, perform the following steps:
[[operationInProgress]]
is true.[[operationInProgress]] to
false.[[connections]]:
[[operationInProgress]] is
true, abort there steps.The cancel the outstanding GetStatusChange algorithm steps are:
[[tracker]].Cancel().The high word of a [PCSC5] DWORD is the result of an
unsigned right shift of 16 bits on that DWORD.
To set the high word of a [PCSC5] DWORD named
dword to a given number n, perform the following steps.
0xFFFF.To add a flag f to a [PCSC5] DWORD
flags, set flags to flags bitwise OR f.
A [PCSC5] DWORD flags has a flag f
if flags bitwise AND f is f.
WebIDL[Exposed=(DedicatedWorker, SharedWorker, Window), SecureContext, IsolatedContext]
interface SmartCardConnection {
Promise<undefined> disconnect(optional SmartCardDisposition disposition = "leave");
Promise<ArrayBuffer> transmit(BufferSource sendBuffer,
optional SmartCardTransmitOptions options = {});
Promise<undefined> startTransaction(SmartCardTransactionCallback transaction,
optional SmartCardTransactionOptions options = {});
Promise<SmartCardConnectionStatus> status();
Promise<ArrayBuffer> control([EnforceRange] unsigned long controlCode,
BufferSource data);
Promise<ArrayBuffer> getAttribute([EnforceRange] unsigned long tag);
Promise<undefined> setAttribute([EnforceRange] unsigned long tag, BufferSource value);
};
callback SmartCardTransactionCallback = Promise<SmartCardDisposition?> ();
Instances of SmartCardConnection are created with the internal slots
described in the following table:
| Internal slot | Initial value | Description (non-normative) |
|---|---|---|
| [[comm]] | null |
The platform's [PCSC5] SCARDCOMM to be used. |
| [[context]] | null |
The SmartCardContext that created this instance. |
| [[activeProtocol]] | 0 | The active protocol DWORD, as returned by the platform's
[PCSC5] implementation. |
| [[transactionState]] | null |
Holds the state of an ongoing transaction
started with startTransaction(), if
any. |
The disconnect(disposition) method steps
are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.[[context]].[[operationInProgress]]
to true.[[comm]].Disconnect()
with a DWORD corresponding to
disposition as input parameter.RESPONSECODE.[[context]].SCARD_S_SUCCESS, reject
promise with an exception
corresponding to responseCode and abort
these steps.[[comm]].[[comm]] to null.WebIDLenum SmartCardDisposition {
"leave",
"reset",
"unpower",
"eject"
};
leaveSCARD_LEAVE_CARD DWORD.resetSCARD_RESET_CARD
DWORD.unpowerSCARD_UNPOWER_CARD DWORD.ejectSCARD_EJECT_CARD DWORD.The transmit(sendBuffer, options) method steps
are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.DWORD set to
this.[[activeProtocol]].
protocol"]
exists, set protocol to the DWORD corresponding to
options["protocol"].
InvalidStateError" DOMException
and return promise.[[context]].[[operationInProgress]]
to true.SCARD_IO_HEADER corresponding to
this.[[activeProtocol]].BYTE[]
containing sendBuffer.SCARD_IO_HEADER
equivalent of empty or null.BYTE[] big enough to hold
the largest [ISO7186-3] extended response APDU (65538 bytes).DWORD set to 0.[[comm]].Transmit()
with sendPci, pcscSendBuffer, recvPci, recvBuffer and
recvLength as arguments.RESPONSECODE.[[context]].SCARD_S_SUCCESS, reject
promise with an exception
corresponding to responseCode and abort
these steps.ArrayBuffer containing
the first recvLength bytes of recvBuffer.WebIDLdictionary SmartCardTransmitOptions {
SmartCardProtocol protocol;
};
protocol memberThe startTransaction(transaction, options)
method steps are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.[[transactionState]] is not
null, reject promise with a "InvalidStateError"
DOMException and return promise.AbortSignal set to null.signal"]
exists, run the following steps:
[[context]].[[operationInProgress]]
to true.[[comm]].BeginTransaction().RESPONSECODE.WebIDLdictionary SmartCardTransactionOptions {
AbortSignal signal;
};
signal memberA transaction state is a struct with the following items:
| Item | Description (non-normative) |
|---|---|
| pendingDisposition | If set, it means once the ongoing PC/SC operation finishes
[PCSC5] EndTransaction() should be called with this value as the
SmartCardDisposition parameter. |
| pendingException | The exception to be used when rejecting promise. |
| promise | The pending Promise returned by a
startTransaction() call. |
To process the result of a BeginTransaction given a
SmartCardConnection connection, a [PCSC5]
RESPONSECODE responseCode, an AbortSignal
signal, a SmartCardTransactionCallback
transaction and a Promise
promise, perform the following steps:
[[context]].undefined.null:
cancel algorithm from
signal.SCARD_S_SUCCESS:
SCARD_E_CANCELLED and
abortReason is not undefined then reject
promise with abortReason.corresponding to
responseCode.[[transactionState]]
to transactionState.reset".
undefined, set disposition to
v.[[context]].[[operationInProgress]]
is true:
InvalidStateError"
DOMException.[[context]].[[operationInProgress]]
is true, set
transactionState's pendingDisposition to
"reset".reset".To end the transaction of a SmartCardConnection
connection with a SmartCardDisposition
disposition, perform the following steps:
[[context]].[[operationInProgress]]
is false.[[transactionState]] is not
null.[[transactionState]]'s
pendingDisposition is null.[[transactionState]]'s
promise.[[comm]] is null:
InvalidStateError"
DOMException.[[transactionState]] to
null.[[context]].[[operationInProgress]]
to true.[[comm]].EndTransaction() with
a DWORD corresponding to disposition as input parameter.RESPONSECODE.[[context]].[[transactionState]]'s
pendingException.null, perform the following steps:
SCARD_S_SUCCESS,
resolve transactionPromise.corresponding to
responseCode.[[transactionState]]
to null.To end any settled transaction of a
SmartCardConnection connection, perform the
following steps:
[[transactionState]] is
null, abort these steps.[[transactionState]]'s
pendingDisposition.null, abort these steps.[[transactionState]]'s
pendingDisposition to null.To cancel outstanding [PCSC5] SCARDCOMM operations,
call this.[[comm]].Cancel().
The status() method steps are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.[[context]].[[operationInProgress]]
to true.STR[].DWORD set to 0.DWORD set to 0.BYTE[] big enough to hold
any [ISO7186-3] Answer To Reset (ATR).[[comm]].Status()
with pcscReader, pcscState, activeProtocol and pcscAtr as
output parameters.RESPONSECODE.[[context]].SCARD_S_SUCCESS, reject
promise with an exception
corresponding to responseCode and abort
these steps.SmartCardConnectionState
corresponding to pcscState
and activeProtocol.undefined, reject promise with an
"UnknownError" DOMException and abort these steps.SmartCardConnectionStatus.readerName"]
to pcscReader.state"]
to state.answerToReset"] to
an ArrayBuffer with the bytes that were written to
pcscAtr.WebIDLdictionary SmartCardConnectionStatus {
required DOMString readerName;
required SmartCardConnectionState state;
ArrayBuffer answerToReset;
};
readerName memberstate memberanswerToReset memberWebIDLenum SmartCardConnectionState {
"absent",
"present",
"swallowed",
"powered",
"negotiable",
"t0",
"t1",
"raw"
};
absentpresentswallowedpowerednegotiablet0t1rawGiven a [PCSC5] DWORD pcscState and a DWORD
activeProtocol, a
corresponding
SmartCardConnectionState is created with the following steps:
SCARD_ABSENT, return
"absent".SCARD_PRESENT, return
"present".SCARD_SWALLOWED, return
"swallowed".SCARD_POWERED, return
"powered".SCARD_NEGOTIABLE, return
"negotiable".SCARD_SPECIFIC, perform the
following steps:
undefined.The control(controlCode, data) method steps are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.[[context]].[[operationInProgress]]
to true.DWORD containing
controlCode.BYTE[] inBuffer.BYTE[] large enough
to hold any control command response.DWORD set to 0.[[comm]].Control()
with pcscControlCode, inBuffer, outBuffer and
outBufferLength as arguments.RESPONSECODE.[[context]].SCARD_S_SUCCESS, reject
promise with an exception
corresponding to responseCode and abort
these steps.ArrayBuffer from
resultBytes in this's relevant Realm.The getAttribute(tag) method steps are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.[[context]].[[operationInProgress]]
to true.DWORD containing tag.BYTE[] large
enough to hold this reader attribute, as determined by the
platform's [PCSC5] implementation.[[comm]].GetReaderCapabilities()
with pcscTag and buffer as arguments.RESPONSECODE.[[context]].SCARD_S_SUCCESS, reject
promise with an exception
corresponding to responseCode and abort
these steps.ArrayBuffer from
resultBytes in this's relevant Realm.The setAttribute(tag, value) method steps are:
[[context]].[[operationInProgress]]
is true, reject promise with a "InvalidStateError"
DOMException and return promise.[[comm]] is null, reject
promise with a "InvalidStateError" DOMException and return
promise.[[context]].[[operationInProgress]]
to true.DWORD containing
tag.BYTE[] buffer.[[comm]].SetReaderCapabilities()
with pcscTag and buffer as arguments.RESPONSECODE.[[context]].SCARD_S_SUCCESS, reject
promise with an exception
corresponding to responseCode and abort
these steps.WebIDL[
Exposed=(DedicatedWorker, SharedWorker, Window),
SecureContext,
IsolatedContext
] interface SmartCardError : DOMException {
constructor(optional DOMString message = "", SmartCardErrorOptions options);
readonly attribute SmartCardResponseCode responseCode;
};
The responseCode attribute is the error or warning response
code returned by the related [PCSC5] method.
Given a [PCSC5] RESPONSECODE different from SCARD_S_SUCCESS, a
corresponding exception is
created with the following steps:
RESPONSECODE.SCARD_E_NO_SERVICE, return a new
"no-service" SmartCardError.
SCARD_E_NO_SMARTCARD, return a new
"no-smartcard" SmartCardError.SCARD_E_NOT_READY, return a new
"not-ready" SmartCardError.SCARD_E_NOT_TRANSACTED, return a new
"not-transacted" SmartCardError.SCARD_E_PROTO_MISMATCH, return a new
"proto-mismatch" SmartCardError.SCARD_E_READER_UNAVAILABLE, return a new
"reader-unavailable"
SmartCardError.SCARD_W_REMOVED_CARD, return a new
"removed-card" SmartCardError.SCARD_W_RESET_CARD, return a new
"reset-card" SmartCardError.SCARD_E_SERVER_TOO_BUSY, return a new
"server-too-busy" SmartCardError.SCARD_E_SHARING_VIOLATION, return a new
"sharing-violation" SmartCardError.SCARD_E_SYSTEM_CANCELLED, return a new
"system-cancelled" SmartCardError.SCARD_E_UNKNOWN_READER, return a new
"unknown-reader" SmartCardError.SCARD_W_UNPOWERED_CARD, return a new
"unpowered-card" SmartCardError.SCARD_W_UNRESPONSIVE_CARD, return a new
"unresponsive-card" SmartCardError.SCARD_W_UNSUPPORTED_CARD, return a new
"unsupported-card" SmartCardError.SCARD_E_UNSUPPORTED_FEATURE, return a new
"unsupported-feature"
SmartCardError.SCARD_E_INVALID_PARAMETER, return a new
TypeError.SCARD_E_INVALID_HANDLE, return a new
"InvalidStateError" DOMException.SCARD_E_SERVICE_STOPPED, return a new
"InvalidStateError" DOMException.SCARD_P_SHUTDOWN, return a new
"AbortError" DOMException.UnknownError" DOMException.WebIDLdictionary SmartCardErrorOptions {
required SmartCardResponseCode responseCode;
};
The responseCode member is the value for SmartCardError's
responseCode attribute.
WebIDLenum SmartCardResponseCode {
"no-service",
"no-smartcard",
"not-ready",
"not-transacted",
"proto-mismatch",
"reader-unavailable",
"removed-card",
"reset-card",
"server-too-busy",
"sharing-violation",
"system-cancelled",
"unknown-reader",
"unpowered-card",
"unresponsive-card",
"unsupported-card",
"unsupported-feature"
};
no-serviceno-smartcardnot-readynot-transactedproto-mismatchreader-unavailableremoved-cardreset-cardserver-too-busysharing-violationsystem-cancelledunknown-readerunpowered-cardunresponsive-cardunsupported-cardunsupported-featureThis API provides web applications with access to the host's PC/SC smart card subsystem. This is a powerful feature that, if misused, could have significant negative impacts on a user's security and privacy. This section outlines the threats considered and the normative requirements for user agents to mitigate them.
Access to a smart card reader and any card present within it is a
powerful feature. A user agent MUST NOT
allow a web application to gain access to a SmartCardConnection
object without express permission.
User consent MUST be obtained for a specific
origin. The request for consent MUST be
triggered by a call to the connect() method. The
user agent MUST display a permission prompt
that clearly indicates which origin is requesting access and provides
the user with enough information to make an informed decision (for
example, by displaying the name of the smart card reader).
User agents SHOULD provide options for both transient (e.g., "for this session only") and persistent permission. To mitigate the risk of users forgetting they have granted persistent access, transient permission SHOULD be the default and more prominent option.
Users MUST be provided with a mechanism to view and revoke any previously granted permissions for this API.
The listReaders() method and the
answerToReset member of the
SmartCardReaderStateOut dictionary expose information that can be
used for passive fingerprinting. The presence and model of smart card
readers can reveal information about the user, such as whether they
are in a corporate environment. The Answer to Reset (ATR) can further
identify the type and issuer of a smart card.
While this specification does not require a permission prompt before
calling listReaders(), access to the entire API
is controlled by the "smart-card"
policy-controlled feature. This allows administrators or users to
disable the API for specific origins, mitigating the fingerprinting
risk.
The control() and
setAttribute() methods provide direct,
low-level access to the smart card reader hardware. A malicious site
could potentially use these methods to upload malicious firmware,
render the device inoperable, or otherwise interfere with its normal
operation.
Similarly, a malicious site with a connection to a smart card could repeatedly attempt PIN verification to permanently block the card, or access or overwrite sensitive, unprotected data.
The primary mitigation for these threats is the requirement for
express permission before a SmartCardConnection object is created,
as this gates access to all subsequent powerful methods.
This API operates at a low level and does not have inherent protections against phishing or other forms of spoofing attacks that are present in higher-level APIs like WebAuthn. A malicious site could trick a user into performing an authentication ceremony that is then used to impersonate the user on a different site.
For authentication use cases, developers SHOULD prefer using the Web Authentication API wherever possible.
A smart card with writable memory could be used as a side-channel for different origins to exchange data, bypassing other same-origin policies. The mitigation for this is that express permission is granted to a specific origin. An attack would require the user to grant smart card access to multiple, potentially malicious, origins.
This API MUST only be exposed in an isolated context.
To prevent documents from holding connections to sensitive hardware
while not in the user's direct control, a user agent
MUST dispose of all active
SmartCardContext objects and their associated
SmartCardConnections when a document is no longer
fully active. This includes automatically disconnecting
any active connections as if disconnect() were
called.
This specification defines a feature that controls whether the
methods exposed by the smartCard attribute on the
Navigator object may be used.
The feature name for this feature is "smart-card".
The default allowlist for this feature
is 'none'. User agents MAY override this
to 'self' for particular origins (for example based on user decision).
As well as sections marked as non-normative, all authoring guidelines, diagrams, examples, and notes in this specification are non-normative. Everything else in this specification is normative.
The key words MAY, MUST, MUST NOT, and SHOULD in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in:
Referenced in: