Subject: [Json] Working Group Last Call on draft-ietf-json-text-sequence

From: Paul Hoffman <[email-masked]>
Date: Thu, 22 May 2014 14:00:42 -0700

This begins a two-week Working Group Last Call on draft-ietf-json-text-sequence <http://tools.ietf.org/html/draft-ietf-json-text-sequence>. We are seeking any and all comments on the document in order to assess the strength of consensus for it. If you are on this mailing list and have not yet read the document, please do so now, and then comment on the list. If you have already read the draft and commented, please feel free to do so again.

As a reminder, comments can be anywhere in the continuum of "looks fine" to "terrible idea"; they can include questions; they can include suggestions for singificant editorial changes; they can include minor editorial notes.

--Matt Miller and Paul Hoffman

---

From: Nico Williams <[email-masked]>
Date: Thu, 22 May 2014 16:30:22 -0500

I should probably add more text to the acknowledgements section.  The
community's input has made a huge difference.  Thanks,

Nico
--

---

From: Tim Bray <[email-masked]>
Date: Thu, 22 May 2014 18:24:02 -0500

>From section 1:

   Ideally such datasets could be parsed and processed one element at a
   time.  Even if each element must be parsed in a not-online manner due
   to local choice of parser, the result will usually be sufficiently
   online: limited by the size of the biggest element in the sequence
   rather than by the size of the sequence.

The second sentence is klunky and I don’t understand what it’s trying
to say.  I suggest attaching the first sentence to the previous para
and just losing the 2nd sentence.

=====================

Just lose section 2.1.  Section 2 says perfectly clearly what a JSON
sequence is, and requires that the material separating the texts MUST
include one newline; so this language is at best redundant.  How about
putting a one-liner after the ABNF in section 2 saying.

“The effect of the ABNF is that the JSON texts in a JSON Text Sequence
are separated by whitespace which MUST include at least one newilne
(U+000A) character.”

=====================

3., first para: missing word, should be “until they are closed”.

=====================

I suggest removing section 3. It’s not hard to construct something
that could appear in the middle of a JSON text that would match
“boundary”. As you note, this will not be a very common circumstance,
and I’m thinking of a bunch of different approaches I’d use.  In
practice, the best solution is probably to arrange that records
deterministically start with "\n{".

Having said that, this is obviously an attack surface. I wonder how
well deployed JSON parsers would survive bogus sequences constructed
with careful maliciousness to drive typical parser implementations
into severe CPU or memory burn?  I bet I could construct a byte stream
that would cause serious pain to most of the popular parsers.

=====================

Security considerations:

- Why does the lack of an end-of-seq indicator constitute a security
issue?  I can believe it might be but there needs to be some sort of
threat model

- this paragraph...

   JSON text sequence parsers based on non-incremental, non-online JSON
   text parsers will not be able to efficiently parser JSON texts in
   which newlines appear; attempting to parse such sequences with non-
   incremental, non-online JSON text parsers creates a compute resource
   exhaustion vulnerability.

Huh? What does the word “online” mean in this context?  Not a
rhetorical question, I genuinely don’t get it.  I propose the
following rewrite for Security Considerations

<div>

All the security considerations of JSON [RFC7159] apply to JSON Text Sequences.

An attacker could try to cause breakage in JSON Text Sequence
processing software by arranging for a JSON text in a sequence to be
very large, for example by including very large keys or values in JSON
objects.  JSON allows parsing software to impose limits on the such
lengths, and implementors receiving software SHOULD implement and
enforce such limits.

An attacker could try to cause breakage in JSON Text Sequence
processing software by including syntactically broken JSON texts which
are designed to cause misbehavior in software attempting
resynchronization.

</div>

On Thu, May 22, 2014 at 4:00 PM, Paul Hoffman <[email-masked]> wrote:

> This begins a two-week Working Group Last Call on
> draft-ietf-json-text-sequence <
> http://tools.ietf.org/html/draft-ietf-json-text-sequence>. We are seeking
> any and all comments on the document in order to assess the strength of
> consensus for it. If you are on this mailing list and have not yet read the
> document, please do so now, and then comment on the list. If you have
> already read the draft and commented, please feel free to do so again.
>
> As a reminder, comments can be anywhere in the continuum of "looks fine"
> to "terrible idea"; they can include questions; they can include
> suggestions for singificant editorial changes; they can include minor
> editorial notes.
>
> _______________________________________________
> json mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/json
>

-- 
- Tim Bray (If you’d like to send me a private message, see
https://keybase.io/timbray)

---

From: John Cowan <[email-masked]>
Date: Thu, 22 May 2014 21:32:40 -0400

> and just losing the 2nd sentence.

The key to understanding the second sentence is that "online" means what
you and I call "streaming".

-- 
John Cowan          http://www.ccil.org/~cowan        [email-masked]
Winter:  MIT, / Keio, INRIA, / Issue lots of Drafts.
So much more to understand! / Might simplicity return?
                (A "tanka", or extended haiku)

---

From: "Martin J. Dürst" <[email-masked]>
Date: Fri, 23 May 2014 15:53:36 +0900

I have said so earlier, and will say it here again: I consider this a 
*terrible idea*, because JSON in and by itself is perfectly able to 
represent sequences (using arrays).

The two things needed for making this work are changing the delimiter 
from a line break to a comma (trivial) and to start the thing with a '[' 
and end it with ']'. Only the ending part is non-trivial, but there are 
many ways to deal with it, depending on the parser at hand. These are 
very similar to the problems that some parsers will have with 
"overfeeding" them with more than a single JSON text.

The scarcity of actual use cases and the negligible amount of mostly 
just perceived difficulties with the main format (JSON) stand in stark 
contrast with the costs of *yet another format* (YAF, anybody?).

Questions, comments, and confusions such as "No, this isn't JSON, it's a 
JSON text sequence." or "Do we use JSON, or JSON text sequences?" and so 
on can best be avoided by just forgetting about JSON text sequences once 
and for all. Also, JSON text sequences aren't recursively composible.

So my baseline proposal is for the WG to just abandon this work item. 
It's in the charter, but at least that part of the charter came as a 
surprise and didn't have too many active proponents. It's better to 
acknowledge a mistake later than never.

If the WG can't get to such a conclusion, I alternatively propose to 
degrade the document to Experimental. That might make it possible to 
evaluate the actual need for such a format and balance it against the 
potential confusion.

I also propose that if the document moves forward with publication, it 
contain very clear text in the abstract, the introduction, the security 
section and potentially elsewhere to the effect that this is NOT JSON, 
and shouldn't be confused with JSON. It should also say that whenever 
there's a choice between JSON and JSON text sequences, the former 
(potentially with an array at the top) should be chosen unless there is 
an unrefutable reason for the later (this will increase interoperability).

The introduction also should tone down the discussion about problems 
with parsing a one-million value array. If that's a practical problem, 
then it's not too difficult to parse the delimiters separately and only 
have the values parsed by a JSON parser (the availability of a JSON 
parser that stops when having finished reading a single value is assumed 
anyway).

Regards,    Martin.

---

From: "Martin J. Dürst" <[email-masked]>
Date: Fri, 23 May 2014 16:36:41 +0900

> you and I call "streaming".

Can we make sure that at least once early in the document, one of the 
term is explained by also using the other one?

Regards,   Martin.

---

From: Nico Williams <[email-masked]>
Date: Fri, 23 May 2014 11:01:34 -0500

> you and I call "streaming".

I classify JSON parsers as follows:

 - streaming -> consume input text incrementally AND produce results
incrementally (e.g., a path+value pair for each scalar value in a
text)

 - online -> consume input text incrementally (but -perhaps- produces
one value for a complete parsed text)

 - not-online -> consumes input text non-incrementally, must be
provided complete texts

Streaming parsers are also online parsers in my classification.

Perhaps I'm using the wrong terminology, but I've yet to see a
standard classification of JSON parsers that captures these
distinctions.

The value of JSON text sequences comes from not having to use a
streaming parser (since they can be unwieldy).  There is also value on
the encoding side: not having to use a streaming encoder, nor manually
emit an opening '[' and ','s between texts.

A real-world example of this is jq (https://stedolan.github.io/jq),
which has an online-but-streaming parser, and which naturally supports
JSON text sequences.  jq can consume (and produce) JSON text sequences
in a "streaming" manner even though its JSON parser and encoder are
not streaming.

Nico
--

---

From: Tim Bray <[email-masked]>
Date: Fri, 23 May 2014 12:02:35 -0500

Clearly the current language is confusing readers of the spec. So I suggest
that you be careful to define specialized terms that you are going to use
in the spec.  An even better solution would be to structure the spec to
avoid having to bring in this level of implementation idiosyncrasy.

The more I think about the resync-after-error problem, the unhappier I get.
 If the JSON texts in sequences were required to be JSON objects, and
required to start on new lines, this would be immensely easier for
implementors.

---

From: Nico Williams <[email-masked]>
Date: Fri, 23 May 2014 15:45:04 -0500

On Fri, May 23, 2014 at 12:02 PM, Tim Bray <[email-masked]> wrote:
> that you be careful to define specialized terms that you are going to use in
> the spec.  An even better solution would be to structure the spec to avoid
> having to bring in this level of implementation idiosyncrasy.
>

That is not sufficient.  Consider this text:

{ "foo":
{ "bar":"baz" }
}

Clearly looking only for LF '{' is insufficient.

The text describes how to ensure that resynchronization can be done safely.

First, it says that "writers SHOULD validate (parse) any untrusted
JSON text inputs".  Then it gives two methods that, together with
validation, make resynchronization possible.

One method is to remove all newlines from JSON texts (a trivial
operation, see below) prior to writing them to the log file.  Then the
only boundary that matters is newlines, and that's very easy to search
for reliably.

The other method is to prefix every text with another text consisting
of something like 'null' (or 'true', or any value which will by
convention have no meaning other than as a resynchronization helper).
Also a trivial operation.

(Note that because newlines in strings must always be escaped, then
only newlines interior to any JSON text are... superfluous whitespace
that can be safely removed without having to parse and re-encode the
JSON text.)

Most attacks on loggers are easily thwarted by checking that any JSON
text to be logged is valid.  This leaves only one attack vector:
forcing a write by the logger to fail after starting -- this is a
non-trivial attack to mount, and it is trivially defeated by either
removing internal newlines from texts prior to writing them, or by
prefixing them with a meaningless-by-convention text (e.g., 'null').

Nico
--

---

From: Paul Hoffman <[email-masked]>
Date: Fri, 23 May 2014 14:59:54 -0700

<no hat>

> Clearly looking only for LF '{' is insufficient.

Having this discussion in a short subsection in the introduction would be useful to answer a wary reader's question of "why is this needed?".

--Paul Hoffman

---

From: Carsten Bormann <[email-masked]>
Date: Sat, 24 May 2014 19:02:11 +0200

On 23 May 2014, at 08:53, Martin J. Dürst <[email-masked]> wrote:

> it's not too difficult to parse the delimiters separately and only have the values parsed by a JSON parser

Indeed.  I continue to believe that this is the only reasonable way to operate on sequences of JSON instances.
Either

1) use a delimiter that cannot occur in JSON (staying in UTF-8 with ASCII control characters as in NUL, FF or RS; or breaking out of UTF-8 as in using 0xFF bytes);
2) use LF as the delimiter, and remove the LFs from the JSON instances.

Using LFs as inter-stream delimiters, while also retaining their insignificant whitespace role within JSON instances, strikes me as the most complicated way to approach this problem.
There may be practical reasons to use this most-complicated way, but it seems suboptimal to standardize on it.

(I’m not a big fan of wrapping separate JSON instances in outermost JSON arrays for the kinds of applications addressed here.
This can obviously already be used for those cases where it works (no need for concatenation, no need for resilience), but except in those cases where a combined JSON instance had been the right thing to use in the first place, it combines all the same problems of dual-use LFs with the need to add wrapping brackets.)

Grüße, Carsten

---

From: Tim Bray <[email-masked]>
Date: Sat, 24 May 2014 13:10:44 -0500

On reflection, I support Carsten’s option #1; choose a suitable delimiter
that can’t occur in UTF-8-encoded JSON.  It makes the syncing problem
vanish and removes worrying attack vectors.

On Sat, May 24, 2014 at 12:02 PM, Carsten Bormann <[email-masked]> wrote:

> 1) use a delimiter that cannot occur in JSON (staying in UTF-8 with ASCII
> control characters as in NUL, FF or RS; or breaking out of UTF-8 as in
> using 0xFF bytes);
> Using LFs as inter-stream delimiters, while also retaining their
> insignificant whitespace role within JSON instances, strikes me as the most
> complicated way to approach this problem.
> (I’m not a big fan of wrapping separate JSON instances in outermost JSON
> arrays for the kinds of applications addressed here.
> This can obviously already be used for those cases where it works (no need
> for concatenation, no need for resilience), but except in those cases where
> a combined JSON instance had been the right thing to use in the first
> place, it combines all the same problems of dual-use LFs with the need to
> add wrapping brackets.)
>
> Grüße, Carsten
>

---

From: R S <[email-masked]>
Date: Sat, 24 May 2014 14:38:02 -0700

> vanish and removes worrying attack vectors.

Option #1 has two options. I think breaking out of UTF-8 will cause more
problems than it solves, so using an ASCII control character is what I'd
do. It looks to me like this is what Record Separator was designed for. Why
not use it?

- Rob

---

From: Nico Williams <[email-masked]>
Date: Sat, 24 May 2014 17:37:21 -0500

> Indeed.  I continue to believe that this is the only reasonable way to operate on sequences of JSON instances.

jq has no problems using LF.  LF is only a problem if you have
corrupted entries, which is only really a problem for logfiles.

Nico
--