The framework aims to solve three major pain points experienced with Swift's
- Provide a library of fully featured implementations of popular serialization formats
- Allow decoding and/or encoding values of unknown structure (i.e. any encoded tree of values)
- Support polymorphic type encoding/decoding while still allowing Swift to implement
- Reduce the complexity and amount of code required to implement and test new serialization formats
With regard to the first point
ASN.1 are currently supported and support for
YAML is coming in the near term.
You forgot to include a link!
Be mindful that using dynamic type lookup to automatically instantiate types without some sort of registration mechanism is a common security vulnerability. I would recommend against using any kind of dynamic type lookup and provide a way for code to register the set of types they expect to be able to decode at a certain point instead.
Good point, I hadn't really thought of that.
Interestingly, due to its existing limitations, I am working on a more expressive method that involves registering classes for the
EmbeddedRef types. Once this is completed I'll remove the current method.
Ref part of the readme is both difficult to understand and seems to contain incorrect code.
Very nice to see a CBOR Coder, it's a great format
Have you done any comparative benchmarks how it stacks up against the JSON coders (throughput / allocations / size)?
The framework has been updated to 1.7.0. @Joe_Groff's recommendation has finally been implemented for polymorphic decoding.
The default type lookup now requires explicit registration of allowed types. This removes any security vulnerability and allows values types (e.g. struct & enum) to be used as well.
Also, If your code happens to have an alternate method of type lookup the default implementation can be swapped out with a custom type index.
Looks great! One concern about messaging though (and take this feedback with a grain of salt because I haven't gotten a chance to use and explore your implementation) — keep in mind that there still is at least one security issue that can't be resolved with type registration like this:
- Framework A offers a protocol/class
Foo which is generally useful to conform to or subclass
- Your app has some subclasses of/types conforming to
Baz), which it wants to decode
- Framework B is a framework which your app uses, and it also finds Framework A and
Foo useful, so offers its own subtype of
Quux. Within its contexts, it expects to be able to encode and decode
Quux, so it registers it as an expected type with the default type index
- Your app goes to decode a
Foo expecting one of
Baz but instead gets a
Quux because that's what the archive contained. Depending on how you use the
Foo this could end up being an attack vector or a plain old DoS vector
I think this approach is great for usability, but I would be a little wary of making certain security claims. (In practice, the risk of this is small, but still present, which is why
Codable didn't offer this on its own.)
This is actually precluded by the default implementation only allowing the setting of the complete list of classes, (i.e. each call to
mapAllowedTypes overwrites the previous). This makes it convenient and safe for simple applications.
Frameworks shouldn't be using
EmbeddedRef as the list of allowed types is unknown; instead the should defined their own
CustomRef with a custom type index. This is why the type index is swappable and frameworks should/must use this feature to make the allowed types stable and retain security.
I understand that isn't all that well documented in the README.
Ah, this is pretty key. Unless I'm misunderstanding, in the worst-case scenario it does still seem possible (Framework B doesn't define its own custom type index, although it's supposed to, and the app forgets to call
mapAllowedTypes so the type index still contains
Quux instead of
Baz even though it's supposed to), but the list of allowed types doesn't continue growing over time so the scenario in which this could happen is very constrained. My mistake!
This seems like a very effective approach given the circumstances; I like it!
Thanks! It's clear we need more and better documentation on the use of polymorphic decoding; specifically in how frameworks are expected to use it.