Summary
Since 1.10, the REST API endpoint /scan/<taskid>/data returns a JSON-quoted Python repr() string for value fields where it previously returned a structured JSON object. This breaks any client that parses the documented response shape.
Reproduction
git clone --depth 1 --branch 1.10.4 https://github.com/sqlmapproject/sqlmap.git
cd sqlmap
python3 -c "
import sys; sys.path.insert(0, '.')
from lib.core.convert import stdoutEncode
target = {'url': 'http://example.com/foo', 'query': None, 'data': 'id=1'}
encoded = stdoutEncode(target)
print('input :', repr(target))
print('output :', repr(encoded))
print('type :', type(encoded).__name__)
"
Output
1.10.4 (current — broken):
input : {'url': 'http://example.com/foo', 'query': None, 'data': 'id=1'}
output : "{'url': 'http://example.com/foo', 'query': None, 'data': 'id=1'}"
type : str
1.9.4 (previous — correct):
input : {'url': 'http://example.com/foo', 'query': None, 'data': 'id=1'}
output : {'url': 'http://example.com/foo', 'query': None, 'data': 'id=1'}
type : dict
Why this matters
stdoutEncode is the encoder for the API write path: in lib/core/dump.py Dumper.string() → _write() → lib/core/common.py dataToStdout() → sys.stdout.write(stdoutEncode(clearColors(data)), ...) — where sys.stdout.write is overridden by the API's write() in lib/utils/api.py, which then does jsonize(value).
Concrete impact, called from lib/controller/controller.py:181:
conf.dumper.string("", {"url": conf.url, "query": ..., "data": ...},
content_type=CONTENT_TYPE.TARGET)
- Before:
stdoutEncode returned the dict unchanged → jsonize(dict) produced a JSON object → REST clients got "value": {"url": "...", "query": null, "data": "..."}.
- After:
stdoutEncode returns str(dict) (Python repr) → jsonize(string) produces a JSON string → REST clients get "value": "{'url': '...', 'query': None, 'data': '...'}" — unparseable, since None and single-quotes aren't JSON.
For CONTENT_TYPE.TECHNIQUES (type 1) the breakage is worse: the value contains nested dicts with integer keys ({1: {...}, 2: {...}}), so the resulting Python repr is not even convertible to JSON without a Python-literal parser.
Root cause
Commit 09fadc43 ("Minor improvement of stdoutEncode", 2025-12-31) replaced the else: retVal = value branch with elif not isinstance(value, str): value = str(value), eagerly stringifying any non-string input.
Suggested fix
In stdoutEncode, skip the str(value) coercion when conf.api is set (the API path expects to forward structured values to jsonize), or move that coercion out of stdoutEncode and only into the non-API stdout branch in dataToStdout.
Screenshots
If applicable, add screenshots to help explain your problem.
Summary
Since 1.10, the REST API endpoint
/scan/<taskid>/datareturns a JSON-quoted Pythonrepr()string forvaluefields where it previously returned a structured JSON object. This breaks any client that parses the documented response shape.Reproduction
Output
1.10.4 (current — broken):
1.9.4 (previous — correct):
Why this matters
stdoutEncodeis the encoder for the API write path: inlib/core/dump.pyDumper.string()→_write()→lib/core/common.pydataToStdout()→sys.stdout.write(stdoutEncode(clearColors(data)), ...)— wheresys.stdout.writeis overridden by the API'swrite()inlib/utils/api.py, which then doesjsonize(value).Concrete impact, called from
lib/controller/controller.py:181:stdoutEncodereturned the dict unchanged →jsonize(dict)produced a JSON object → REST clients got"value": {"url": "...", "query": null, "data": "..."}.stdoutEncodereturnsstr(dict)(Python repr) →jsonize(string)produces a JSON string → REST clients get"value": "{'url': '...', 'query': None, 'data': '...'}"— unparseable, sinceNoneand single-quotes aren't JSON.For
CONTENT_TYPE.TECHNIQUES(type 1) the breakage is worse: the value contains nested dicts with integer keys ({1: {...}, 2: {...}}), so the resulting Python repr is not even convertible to JSON without a Python-literal parser.Root cause
Commit
09fadc43("Minor improvement of stdoutEncode", 2025-12-31) replaced theelse: retVal = valuebranch withelif not isinstance(value, str): value = str(value), eagerly stringifying any non-string input.Suggested fix
In
stdoutEncode, skip thestr(value)coercion whenconf.apiis set (the API path expects to forward structured values tojsonize), or move that coercion out ofstdoutEncodeand only into the non-API stdout branch indataToStdout.Screenshots
If applicable, add screenshots to help explain your problem.