Skip to content

Feature/json path hyphen - #56

Merged
ppomes merged 2 commits into
ppomes:mainfrom
daanj1998:feature/json-path-hyphen
Sep 3, 2026
Merged

Feature/json path hyphen#56
ppomes merged 2 commits into
ppomes:mainfrom
daanj1998:feature/json-path-hyphen

Conversation

@daanj1998

@daanj1998 daanj1998 commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Allow hyphens in JSON paths

What this changes

is_valid_json_path() only accepts letters, numbers, _, . and []. This adds - to
that list. It is one character in one line.

The first commit also adds a test with three shapes: a hyphenated key at the top level, a
hyphenated key inside an object, and a hyphenated key that holds an array.

The second commit fixes a small memory leak I found while writing that test. When a path is
rejected, the config entry is never freed and never added to the list, so the cleanup at exit
does not reach it.

Why it is needed

Many applications use UUIDs as JSON keys, and a UUID always contains hyphens. Today myanon
rejects every such path:

Invalid json path '.a1b2c3d4-e5f6-7890-abcd-ef1234567890', ignoring it

The warning goes to stderr, but myanon still exits 0 and writes the field unchanged. In a
mysqldump | myanon | gzip pipeline you do not notice this: the exit code is clean, the dump
is valid SQL, and the personal data is still in it. So the config looks like it works, and
nothing gets masked.

There is also no way around it. You cannot escape or quote the hyphen, because the path
walker only splits on . and [.

is_valid_json_path() accepted only alphanumerics, '_', '.' and '[]', so
any path directive naming a JSON key that contains a hyphen was dropped
with an "Invalid json path '...', ignoring it" warning on stderr. myanon
still exits 0 and the field is copied through unanonymized, so the data
leaks silently.

Hyphenated keys are not an exotic case: Craft CMS stores field content in
a JSON column keyed by layout element UIDs, for instance
'514a4f07-3621-4e1c-9e0f-2b6f4c1d8a93', so with such a config every path
is rejected and nothing at all gets masked.

Add '-' to the accepted character set, plus a reference test covering a
hyphenated top level key, a hyphenated nested key and a hyphenated key
holding an array.
jscur is allocated for every 'path' directive, but on the invalid path
branch it is neither freed nor added to jslist, while the final cleanup
in myanon.c only walks curfield->json. Every rejected path therefore
leaks sizeof(anon_json_st) (3168 bytes on x86_64). Only the last one
still looks reachable through the static jscur pointer, so a config with
more than one bad path is reported as definitely lost:

  in use at exit: 9,504 bytes in 3 blocks
  definitely lost: 6,336 bytes in 2 blocks
  still reachable: 3,168 bytes in 1 blocks

With the free() in place the same config gives "All heap blocks were
freed -- no leaks are possible", and make valgrind-check stays clean.
@ppomes

ppomes commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Hi @daanj1998, thanks for this contribution!

@ppomes
ppomes merged commit 35fb238 into ppomes:main Sep 3, 2026
3 checks passed
ppomes added a commit that referenced this pull request Sep 3, 2026
Mirror the C change from PR #56: accept '-' in is_valid_json_path() so
UUID-style and kebab-case JSON keys are no longer rejected. Add unit
tests, include test_json_hyphen_path.conf in the parse-all-configs test,
and update the README test count (15 core + 6 Python).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants