In the context of protocol buffers, security comes into play when decoding untrusted data. Naturally, if the attacker can modify the contents of a protocol buffers message, he can feed the application any values possible. Therefore the application itself must be prepared to receive untrusted values.
Where nanopb plays a part is preventing the attacker from running arbitrary code on the target system. Mostly this means that there must not be any possibility to cause buffer overruns, memory corruption or invalid pointers by the means of crafting a malicious message.
The following data is regarded as trusted. It must be under the control of the application writer. Malicious data in these structures could cause security issues, such as execution of arbitrary code:
pb_msgdesc_t
.pb_istream_t
and pb_ostream_t
structures
(this does not mean the contents of the stream itself, just the
stream definition).The following data is regarded as untrusted. Invalid/malicious data in these will cause "garbage in, garbage out" behaviour. It will not cause buffer overflows, information disclosure or other security problems:
pb_istream_t
.pb_callback_t
structures)_count
fields for pointerspb_extension_t
structures)The following invariants are maintained during operation, even if the untrusted data has been maliciously crafted:
bytes_left
bytes from
pb_istream_t
.max_size
bytes to
pb_ostream_t
.pb_decode()
returns successfully, the message structure will
be internally consistent:
count
fields of arrays will not exceed the array size.size
field of bytes will not exceed the allocated size.NULL
or point to valid datapb_encode()
returns successfully, the resulting message is a
valid protocol buffers message. (Except if user-defined callbacks
write incorrect data.)pb_decode()
will be released by a subsequent
call to pb_release()
on the same message.Even if the nanopb library is free of any security issues, there are still several possible attack vectors that the application author must consider. The following list is not comprehensive:
pb_istream_t
to stop a denial of service attack from using an
infinite message.malloc()
support, some method of limiting memory use
should be employed. This can be done by defining custom
pb_realloc()
function. Nanopb will properly detect and handle
failed memory allocations.