diff --git a/security.md b/security.md
new file mode 100644
index 0000000000000000000000000000000000000000..8132cdca4b96037ed79bf2b2fe56743819ca2297
--- /dev/null
+++ b/security.md
@@ -0,0 +1,58 @@
+# Security considerations
+
+## SPARQL injection
+
+A common use case of (web) application backends is to process user inputs and transport them to the database layer by means of executing queries in the specific database query language (e.g. SPARQL or SQL). A typical pattern is to _inject_ values into the database query via string manipulation. Insufficient validation/sanitization of the user input to be injected enables an attack vector called _injection attack_ where the attacker is able to execute malicious statements of the database query language inside the query.
+
+### Literature
+
+General:
+* SPARQL/RDQL/SPARUL Injection: [slides](https://de.slideshare.net/Morelab/sparqlrdqlsparul-injection) and [website](https://morelab.deusto.es/code_injection/index.html)
+* W3C:
+  * [Discussion of a future design for SPARQL query parameterization](https://github.com/w3c/sparql-dev/issues/57)
+  * [Escaping in SPARQL 1.1](https://github.com/w3c/sparql-dev/issues/77)
+* [Towards Secure SPARQL Queries in Semantic Web Applications using PHP (Extended Version)](https://arxiv.org/pdf/1701.07671)
+
+Mitigation in semantic web frameworks:
+* Apache Jena:
+  * [Parameterized SPARQL String](https://jena.apache.org/documentation/query/parameterized-sparql-strings.html)
+  * [notes on SPARQL injection](https://jena.apache.org/documentation/query/parameterized-sparql-strings.html#sparql-injection-notes)
+  * [Tests](https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1391)
+* dotNetRDF: [SparqlParameterizedString](https://dotnetrdf.org/api/html/T_VDS_RDF_Query_SparqlParameterizedString.htm)
+* RDFLib: [Prepared Queries](https://rdflib.readthedocs.io/en/stable/intro_to_sparql.html#prepared-queries)
+
+Escaping:
+* https://stackoverflow.com/q/29601839
+* [Skosmos](https://github.com/NatLibFi/Skosmos/blob/84b37b4cbd7bab294f3a34f4c9f01e7d9bd0b08e/src/model/sparql/JenaTextSparql.php#L48)
+* [prez](https://github.com/RDFLib/prez/blob/165ee61434936b0f5e180a9bca27a7062000af51/prez/services/query_generation/sparql_escaping.py)
+* [Data Pen](https://github.com/humanitiesplusdesign/data-pen/blob/01023fca04083b6d386dffbda260378450cf15eb/app/services/sparql-autocomplete-service.ts#L48)
+
+### Malicious federated queries
+
+Once a SPARQL injection attack is successful one particularly interesting attack scenario is the execution of federated queries (aka `SERVICE`). These could aim to query another RDF dataset that is exposed by the same triplestore via a SPARQL endpoint (e.g. for information disclosure).
+
+Another interesting "application" of federated queries is to target HTTP endpoints inside the infrastructure of the triplestore such as those of [Fuseki's HTTP Administration Protocol](https://jena.apache.org/documentation/fuseki2/fuseki-server-protocol.html). This kind of attack type is a [Server Side Request Forgery](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery). By default, Apache Jena's SPARQL engine uses either GET or POST to query a remote SPARQL endpoint to execute a federated query depending on the size of the query inside the `SERVICE` statement (size limit is 2048 bytes according to the [documentation](https://jena.apache.org/documentation/query/service.html#arqhttpservicesendmode)). For instance the SPARQL query
+```sparql
+SELECT * WHERE {
+  SERVICE <http://127.0.0.1:3030/$/backup/dalia> {
+    ?s ?p "<a very long string>"
+  }
+}
+```
+can trigger the [backup endpoint](https://jena.apache.org/documentation/fuseki2/fuseki-server-protocol.html#backup) with POST, thus initiating a backup of the _dalia_ dataset.
+
+Note: This kind of attack vector has been disabled by setting `arq:httpServiceSendMode` to `"asGetAlways"` with commit [bb535029](https://git.rwth-aachen.de/dalia/backend/fuseki/-/commit/bb5350292b869c1418163f3a8eac988769f7f930).
+
+### Parameter injection into SPARQL queries in this project
+
+RDFLib's [prepared queries](https://rdflib.readthedocs.io/en/stable/intro_to_sparql.html#prepared-queries) cannot be used because [they are not supported by `SPARQLStore`](https://github.com/RDFLib/rdflib/issues/2055).
+
+Our business logic uses a [query builder](https://git.rwth-aachen.de/dalia/backend/django/-/tree/main/project/dalia/query_builder) to construct SPARQL queries. User input can be injected via a `Literal` (strings, numbers, etc.) or `URIRef` (URIs) object. Upon serialization of the `QueryBuilder` object to a string via its `build()` method the `n3()` method is called for all nested objects to give their string representation in [Notation3 format](https://en.wikipedia.org/wiki/Notation3).
+
+#### Strings
+
+`Literal`'s [`n3()` method](https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.Literal.n3) returns a quoted string with proper escaping of problematic characters, which happens in the [`_quote_encode`](https://github.com/RDFLib/rdflib/blob/28a61908c22b7d2f94975197256772b2a00eb8df/rdflib/term.py#L1640-L1665) method. This seems to be a safe way to inject strings and has been pentested extensively by the developer of this project.
+
+#### URIs
+
+`URIRef`'s [`n3()` method](https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.term.URIRef.n3) tests for [invalid characters](https://github.com/RDFLib/rdflib/blob/main/rdflib/term.py#L101-L108) in the URI and raises an exception upon detection.
diff --git a/tests/project/dalia/query_builder/test_issue790.py b/tests/project/dalia/query_builder/test_issue790.py
index 7bc0caa1bf04b168f4d431513a04f36d15210d9d..b8c8f7beab853448436c103ecb8f875d145b9821 100644
--- a/tests/project/dalia/query_builder/test_issue790.py
+++ b/tests/project/dalia/query_builder/test_issue790.py
@@ -1240,3 +1240,151 @@ def test_query_with_property_paths():
         ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#rest>*/<http://www.w3.org/1999/02/22-rdf-syntax-ns#first> ?o . 
         } 
     """)
+
+
+@pytest.mark.parametrize(
+    "inject_string, expected_query",
+    [
+        (
+            # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1414
+            'hello\" } ; DROP ALL ; INSERT DATA { <s> <p> <goodbye>',
+            'SELECT ?s  \nWHERE { \n?s ?p "hello\\" } ; DROP ALL ; INSERT DATA { <s> <p> <goodbye>" . \n} \n',
+        ),
+        (
+            # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1437
+            'hello\" . ?s ?p ?o',
+            'SELECT ?s  \nWHERE { \n?s ?p "hello\\" . ?s ?p ?o" . \n} \n',
+        ),
+        (
+            # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1458
+            "hello' . } ; DROP ALL ; INSERT DATA { <s> <p> \"goodbye",
+            'SELECT ?s  \nWHERE { \n?s ?p "hello\' . } ; DROP ALL ; INSERT DATA { <s> <p> \\"goodbye" . \n} \n',
+        ),
+        (
+            # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1496
+            '\" . } ; DROP ALL ; INSERT DATA { <s> <p> <o> }#',
+            'SELECT ?s  \nWHERE { \n?s ?p "\\" . } ; DROP ALL ; INSERT DATA { <s> <p> <o> }#" . \n} \n',
+        ),
+        (
+            # https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.Literal.n3
+            "foo\nbar",
+            'SELECT ?s  \nWHERE { \n?s ?p """foo\nbar""" . \n} \n',
+        ),
+        (
+            # https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.Literal.n3
+            "''\'",
+            'SELECT ?s  \nWHERE { \n?s ?p "\'\'\'" . \n} \n',
+        ),
+        (
+            # https://rdflib.readthedocs.io/en/stable/apidocs/rdflib.html#rdflib.Literal.n3
+            '"""',
+            'SELECT ?s  \nWHERE { \n?s ?p "\\"\\"\\"" . \n} \n',
+        ),
+        (
+            # character excluded from STRING_LITERAL1 (https://www.w3.org/TR/sparql11-query/#rSTRING_LITERAL1)
+            "\x27",
+            'SELECT ?s  \nWHERE { \n?s ?p "\'" . \n} \n',
+        ),
+        (
+            # character excluded from STRING_LITERAL1 (https://www.w3.org/TR/sparql11-query/#rSTRING_LITERAL1)
+            "\x5C",
+            'SELECT ?s  \nWHERE { \n?s ?p "\\\\" . \n} \n',
+        ),
+        (
+            # character excluded from STRING_LITERAL1 (https://www.w3.org/TR/sparql11-query/#rSTRING_LITERAL1)
+            "\x0A",
+            'SELECT ?s  \nWHERE { \n?s ?p """\n""" . \n} \n',
+        ),
+        (
+            # character excluded from STRING_LITERAL1 (https://www.w3.org/TR/sparql11-query/#rSTRING_LITERAL1)
+            "\x0D",
+            'SELECT ?s  \nWHERE { \n?s ?p "\\r" . \n} \n',
+        ),
+        (
+            # character excluded from STRING_LITERAL2 (https://www.w3.org/TR/sparql11-query/#rSTRING_LITERAL2)
+            "\x22",
+            'SELECT ?s  \nWHERE { \n?s ?p "\\"" . \n} \n',
+        ),
+        (
+            # character in ECHAR (https://www.w3.org/TR/sparql11-query/#rECHAR)
+            "\t",
+            'SELECT ?s  \nWHERE { \n?s ?p "\t" . \n} \n',
+        ),
+        (
+            # character in ECHAR (https://www.w3.org/TR/sparql11-query/#rECHAR)
+            "\b",
+            'SELECT ?s  \nWHERE { \n?s ?p "\x08" . \n} \n',
+        ),
+        (
+            # character in ECHAR (https://www.w3.org/TR/sparql11-query/#rECHAR)
+            "\f",
+            'SELECT ?s  \nWHERE { \n?s ?p "\x0C" . \n} \n',
+        ),
+        (
+            "\[ \]",
+            'SELECT ?s  \nWHERE { \n?s ?p "\\\\[ \\\\]" . \n} \n',
+        ),
+        (
+            "\( \)",
+            'SELECT ?s  \nWHERE { \n?s ?p "\\\\( \\\\)" . \n} \n',
+        ),
+        (
+            "\{ \}",
+            'SELECT ?s  \nWHERE { \n?s ?p "\\\\{ \\\\}" . \n} \n',
+        ),
+    ]
+)
+def test_sparql_injection_with_string_literal(inject_string, expected_query):
+    query = QueryBuilder().SELECT(
+        _var_s
+    ).WHERE(
+        (_var_s, _var_p, Literal(inject_string))
+    ).build()
+
+    assert query == expected_query
+
+
+@pytest.mark.parametrize(
+    "inject_uri",
+    [
+        # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1391
+        'hello> } ; DROP ALL ; INSERT DATA { <s> <p> <goodbye>',
+        # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1402
+        'hello> } ; DROP ALL ; INSERT DATA { <s> <p> <goodbye',
+        # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1425
+        'hello> . ?s ?p ?o',
+        # https://github.com/apache/jena/blob/c720c3fb092f63ac3085281fedf1a80932885fd8/jena-arq/src/test/java/org/apache/jena/query/TestParameterizedSparqlString.java#L1425
+        'hello> . ?s ?p ?o',
+        'http://example.com/abc<',
+        'http://example.com/abc\<',
+        'http://example.com/abc>',
+        'http://example.com/abc\>',
+        'http://example.com/abc"',
+        'http://example.com/abc\"',
+        'http://example.com/abc ',
+        'http://example.com/abc\ ',
+        'http://example.com/abc{',
+        'http://example.com/abc\{',
+        'http://example.com/abc}',
+        'http://example.com/abc\}',
+        'http://example.com/abc|',
+        'http://example.com/abc\|',
+        'http://example.com/abc\\',
+        'http://example.com/abc\\\\',
+        'http://example.com/abc^',
+        'http://example.com/abc\^',
+        'http://example.com/abc`',
+        'http://example.com/abc\`',
+    ]
+)
+def test_sparql_injection_with_uri_raises_exception(inject_uri):
+    with pytest.raises(
+            Exception,
+            match=r"does not look like a valid URI, I cannot serialize this as N3/Turtle. Perhaps you wanted to "
+                  r"urlencode it?"
+    ):
+        QueryBuilder().SELECT(
+            _var_s
+        ).WHERE(
+            (_var_s, _var_p, URIRef(inject_uri))
+        ).build()