Bug or incorrect parametrised SPARQL Update query?

2 views
Skip to first unread message

justforthe...@gmail.com

unread,
May 10, 2016, 2:00:08 PM5/10/16
to Stardog
I have a problem with a very simple SPARQL Update query. It does DELETE but it doesn't INSERT. If the insert failed, I understood it should give an exception and rollback the deletion, but none of these happen. Everything seems normal except from the fact that the data are deleted and not inserted.
If I modify the query string ?name for  \"harcoded\" , it works fine. So it seems something related to the parametrisation of the INSERT clause.

The Java code is:

        UpdateQuery aQuery = aCon.update(QUERY);
        aQuery.parameter(ID, Values.iri(id));
        aQuery.parameter(NAME,"New name");
        aQuery.execute();

The query is:

        DELETE { ?id ex:name ?oldname .
        }
        INSERT { ?id ex:name ?name .
        }
        WHERE { OPTIONAL { ?id ex:name ?oldname }
        }

The replacement seems correct:

# Overrides by the API: 
# PARAMETERS ( ?name ?id ) {
# "New name"
# }



Distinct [cardinality=1]
  Projection(?id, ?_const_ced134bd_uri, ?oldname) [cardinality=1]
    DELETE
      Projection(?id AS ?subject, ?_const_ced134bd_uri AS ?predicate, ?oldname AS ?object) [cardinality=?]
        Bind((<http://www.example.com/d#name> AS ?_const_ced134bd_uri)) [cardinality=?]
    INSERT
      Projection(?id AS ?subject, ?_const_ced134bd_uri AS ?predicate, ?name AS ?object) [cardinality=?]
        Bind((<http://www.example.com/d#name> AS ?_const_ced134bd_uri)) [cardinality=?]
    WHERE
      LoopJoinOuter[_] [cardinality=0]
        Singleton [cardinality=1]
        Bind((<http://www.example.com/d#doc1> AS ?id)) [cardinality=0]
          Scan[POS](<http://www.example.com/d#doc1>, ex:name, ?oldname){all} [cardinality=0]

Michael Grove

unread,
May 10, 2016, 2:31:06 PM5/10/16
to stardog
On Tue, May 10, 2016 at 2:00 PM, <justforthe...@gmail.com> wrote:
I have a problem with a very simple SPARQL Update query. It does DELETE but it doesn't INSERT. If the insert failed, I understood it should give an exception and rollback the deletion, but none of these happen. Everything seems normal except from the fact that the data are deleted and not inserted.
If I modify the query string ?name for  \"harcoded\" , it works fine. So it seems something related to the parametrisation of the INSERT clause.

The Java code is:

        UpdateQuery aQuery = aCon.update(QUERY);
        aQuery.parameter(ID, Values.iri(id));
        aQuery.parameter(NAME,"New name");
        aQuery.execute();

The query is:

        DELETE { ?id ex:name ?oldname .
        }
        INSERT { ?id ex:name ?name .
        }
        WHERE { OPTIONAL { ?id ex:name ?oldname }
        }

The replacement seems correct:

# Overrides by the API: 
# PARAMETERS ( ?name ?id ) {
# "New name"
# }

This is the expected behavior, parameters are only applied to the WHERE clause in modify queries.

Cheers,

Mike
 



Distinct [cardinality=1]
  Projection(?id, ?_const_ced134bd_uri, ?oldname) [cardinality=1]
    DELETE
      Projection(?id AS ?subject, ?_const_ced134bd_uri AS ?predicate, ?oldname AS ?object) [cardinality=?]
        Bind((<http://www.example.com/d#name> AS ?_const_ced134bd_uri)) [cardinality=?]
    INSERT
      Projection(?id AS ?subject, ?_const_ced134bd_uri AS ?predicate, ?name AS ?object) [cardinality=?]
        Bind((<http://www.example.com/d#name> AS ?_const_ced134bd_uri)) [cardinality=?]
    WHERE
      LoopJoinOuter[_] [cardinality=0]
        Singleton [cardinality=1]
        Bind((<http://www.example.com/d#doc1> AS ?id)) [cardinality=0]
          Scan[POS](<http://www.example.com/d#doc1>, ex:name, ?oldname){all} [cardinality=0]

--
-- --
You received this message because you are subscribed to the C&P "Stardog" group.
To post to this group, send email to sta...@clarkparsia.com
To unsubscribe from this group, send email to
stardog+u...@clarkparsia.com
For more options, visit this group at
http://groups.google.com/a/clarkparsia.com/group/stardog?hl=en

Jeremy Iron

unread,
May 10, 2016, 2:49:59 PM5/10/16
to stardog
Thanks Mike, the issue has been driving me crazy for days.

Mmm.. is there any technical reason or that?

So is there any recommendation to avoid injections or should I simply concatenate the strings?


---
You received this message because you are subscribed to a topic in the Google Groups "Stardog" group.
To unsubscribe from this topic, visit https://groups.google.com/a/clarkparsia.com/d/topic/stardog/8nn5ha8ESDU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to stardog+u...@clarkparsia.com.

Michael Grove

unread,
May 10, 2016, 3:06:24 PM5/10/16
to stardog
On Tue, May 10, 2016 at 2:49 PM, Jeremy Iron <justforthe...@gmail.com> wrote:
Thanks Mike, the issue has been driving me crazy for days.

Mmm.. is there any technical reason or that?

No, the behavior is not something defined by the spec, it's specific to Stardog.
 

So is there any recommendation to avoid injections or should I simply concatenate the strings?

I'd avoid concatenating Strings to build queries as much as possible.

Cheers,

Mike

Jeremy Iron

unread,
May 10, 2016, 3:10:32 PM5/10/16
to stardog
Yes, I know it is a very bad practice and it will make me redesign the clean method I created in my Java program to execute my queries, but how am I suppose to avoid injection in Stardog?  Is "insert parametrization" a new feature that might be contemplated in future releases?

Thanks.

Michael Grove

unread,
May 10, 2016, 3:54:12 PM5/10/16
to stardog
On Tue, May 10, 2016 at 3:10 PM, Jeremy Iron <justforthe...@gmail.com> wrote:
Yes, I know it is a very bad practice and it will make me redesign the clean method I created in my Java program to execute my queries, but how am I suppose to avoid injection in Stardog? 

Use `Query#parameter` as much as possible as this scrubs input automatically to avoid injection attacks. Any "parameterization" you do on your own must go through similar procedures.
 
Is "insert parametrization" a new feature that might be contemplated in future releases?

Modify queries are already parameterized, however, the parameters are only applied to the WHERE clause. We would consider extending this to parameterize the INSERT and/or DELETE clauses of the query in a future version. But that would not be until 4.2 at the earliest, if not 5.0 since that's a significant behavioral change that would impact anyone relying on the current behavior.

Cheers,

Mike

Jeremy Iron

unread,
May 10, 2016, 4:17:25 PM5/10/16
to stardog
Thanks for the consideration.

I think it is worth considering since anyone updating Stardog from an application will need it. It is necessary to have the parameter in the where clause, but also in the insert since no application will hardcode the insert values. Actually, I suppose you might use something similar in your Stardog Web interface in the "Edit" data option, since you allow users to input data from Web forms. I guess such code is not public but I will research how you actually do it (any pointer is very welcome).

Jeremy Iron

unread,
May 11, 2016, 7:08:05 AM5/11/16
to stardog
After trying to implement this, the solution is still not convincing, since it is very ugly, tedious and error prone. What I got clear from the answer is that the parameters do not apply to INSERT clauses, so at least now I can rest thinking that I am not programming anything wrongly.

So if someone has had experience modifying a Stardog database data via an application that receives data from users (usual CRUD), please share, as any pointers are appreciated. My thoughts are:

  • In my opinion, modification queries are not parametrized in Stardog, since INSERT clauses cannot be parametrized. Yes, WHERE clauses can be parametrized, but this does not solve the problem. I cannot imagine many scenarios where users want to modify data and they can only input WHERE clause data. Any modification by users will have to use INSERT data provided directly by users, so if there is no way to parametrize the INSERT clause, the injection attack can easily happen. Having parametrized DELETE does not help me much if anyway I have to implement myself the "parametrized INSERT". To support this idea, I can think in SQL terms, where all user input (INSERT input) is enabled for parametrization, that is one of the main points in the first place.
  • I am not sure what Mike meant by "that's a significant behavioral change that would impact anyone relying on the current behavior." because I am not sure what parametrized INSERTs will change in the way updates are currently made by users. This is probably due to my lack of knowledge. From my limited knowledge, I can only see that parametrize INSERTS are simply a plus, they do not mess with other components or provide unexpected results. If someone places a variable in a query and parametrize it, the logical conclusion is that the value would be substituted. The strange behaviour is the opposite, that you try to parametrize a variable, the logging is saying that the value is changed but no changes occurred. Moreover, the data are deleted but not inserted, so one would expect that if the insert fails, the delete would not have happened in the first place. That is why I contemplated this to be a bug in such situation.
  • So, on one hand I am wisely advised to use parameter() as much as possible, but on the other, that I cannot use parameter() with user input for INSERT. My current solution would go then from [1] to [2] below, so I will have to do things like:  INSERT { ?id ex:name \"" + validateParameter( inputName ) + "\" .  I do know this is an awful programming practice, but I need to embed the user input in the query and also verify that it is not using any potential injection, so this means implementing the validations myself for each data type. This seems odd, and I suppose there is another way to do it, even if it is reusing the code used to parametrize WHERE clauses. My knowledge is again very limited, but I feel there should be another way. My current approach seems like the spartan way to solve my problem.
  • So, as a conclusion, I think I am missing something or I am not looking at the right way to solve my problem. I cannot imagine anyone generating a "modification query" from an application that will not need to parametrize INSERT user input. I do not have to look too far, this is needed in Stardog itself (http://localhost:5820/mydb#!/browse/owl%3ANamedIndividual/ex%3Aitem1/edit). So there should be a better way that I am not aware of.

Please, share any suggestion.

[1]
==============================================
final String QUERY = "    // I write the code this way (without using multiple line concatenation) for clarity
        DELETE { ?id ex:name ?oldname .
                       // rest of properties
        }
        INSERT { ?id ex:name ?name .
                      // rest of properties
        }
        WHERE { OPTIONAL { ?id ex:name ?oldname }
                     // rest of properties
        }";

....

        UpdateQuery aQuery = aCon.update(QUERY);
        aQuery.parameter(ID, Values.iri(id));
        aQuery.parameter(NAME, inputName );
        // rest of properties
        aQuery.execute();
==============================================

[2]
==============================================
String query = "    // I write the code this way (without using multiple line concatenation) for clarity
        DELETE { ?id ex:name ?oldname .
                       // rest of properties
        }
        INSERT { ?id ex:name \"" + validateParameter( inputName ) + "\" .
                      // rest of properties
        }
        WHERE { OPTIONAL { ?id ex:name ?oldname }
                     // rest of properties
        }";

        UpdateQuery aQuery = aCon.update(QUERY);
        aQuery.parameter(ID, Values.iri(id));
        aQuery.execute();



private String validateParameter(IRI iri) {
...
}

private String validateParameter(String string) {
...
}

private String validateParameter(Date date) {
...
}

private String validateParameter(Integer integer) {
...
}

.....

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


Evren Sirin

unread,
May 11, 2016, 9:40:01 AM5/11/16
to Stardog
If you put your variable in the WHERE clause and use a BIND then
you'll get parametrization working with updates:

DELETE { ?id ex:name ?oldname }
INSERT { ?id ex:name ?name }
WHERE {
BIND(?idParam AS ?id)
BIND(?nameParam AS ?name)
OPTIONAL { ?id ex:name ?oldname }
}

Set idParam and nameParam variables before executing the query and you are set.

Best,
Evren

Jeremy Iron

unread,
May 11, 2016, 10:05:17 AM5/11/16
to stardog
That was the sort of answer I was looking for!

Many thanks for this information, it works great! And now I see how this can be done in a clean and elegant way. Stardog rules!
Reply all
Reply to author
Forward
0 new messages