Skip to content

Audit remediation: SQL-literal injection escaping (+ codecheck CI fix)#148

Merged
stevevanhooser merged 6 commits into
mainfrom
claude/charming-pasteur-8r1m9v
Jun 14, 2026
Merged

Audit remediation: SQL-literal injection escaping (+ codecheck CI fix)#148
stevevanhooser merged 6 commits into
mainfrom
claude/charming-pasteur-8r1m9v

Conversation

@stevevanhooser

@stevevanhooser stevevanhooser commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Repo-side branch of the audit work originally proposed in #146 (fork PR audriB/DID-matlab:audit/did-matlab-2026-06), brought into a VH-Lab branch so it can be edited and run through CI directly. Lockstep with VH-Lab/DID-python#23 (same audit item §6.1-3).

Changes

  • SQL-injection escaping (§6.1-3): several sqlitedb queries interpolate branch_id / doc_id / document_id / filename into double-quoted SQL string literals. run_sql_query() does not forward bind params to mksqlite, so those values can't be ? placeholders; a value containing " could break out of the literal and inject SQL. Added a private escapeSqlLiteral (doubles ", since SQLite reads "" as an escaped " inside a double-quoted token), applied at all 14 value-interpolation sites. The already-parameterized run_sql_noOpen('... =?', val) calls are unchanged. Mirrors DID-python's _sql_escape.
  • CI fix — tools/tasks/codecheckToolbox.m: the check-code@v1 action adds tools/ to the path and calls the bare-named codecheckToolbox("FoldersToCheck","src"). The wrapper was zero-arg, so this failed with "Too many input arguments" — unrelated to the escaping change and also failing on main. Fixed by making the wrapper accept and forward the name-value args while keeping CreateBadge=false (badge generation needs CPython, which the runner lacks). Keeping the bare-named wrapper means the action stays on its if branch with badges disabled, so no workflow change is needed.

Backward compatibility (normal NDI-matlab use)

No behavioral change expected. The escaping only alters values containing ", and NDI never produces such values at these sites: branch ids are 'a', doc/document ids are did.ido 16hex_16hex, and binary filenames are literals like 'data.bin'/'frames.bin'. For all of these, escapeSqlLiteral is a no-op and the generated SQL is byte-identical. No schema or stored-data format change.

Deferred — DECISION required (not changed here)

Test status

Symmetry tests (which exercise these sqlitedb queries and DID↔Python parity) and codespell pass. The codecheck static analysis itself passes (0 errors); this PR's CI commits resolve the wrapper/badge failures in that job.

https://claude.ai/code/session_01Nn5vG7DR3RqvBAGwd94JKt

audristroyer and others added 6 commits June 12, 2026 15:53
…rals (audit 6.1-3)

Several sqlitedb queries interpolate branch_id / doc_id / document_id /
filename directly into SQL string literals delimited by double quotes, e.g.
['... WHERE doc_id="' document_id '"']. run_sql_query() does not forward bind
parameters to mksqlite (it calls do_run_sql_query without varargin), so these
values cannot be passed as '?' placeholders; a value containing a double quote
could break out of the literal and inject SQL (e.g. a crafted branch name or
document id).

Add a private escapeSqlLiteral helper that doubles embedded double quotes
(inside a double-quoted token SQLite reads "" as an escaped "), mirroring the
DID-python _sql_escape (which doubles single quotes for its single-quoted
literals), and apply it at all 15 value-interpolation sites
(do_add_branch / do_delete_branch / do_get_branch_parent / do_get_sub_branches
/ do_get_doc_ids / read / remove_doc / open_doc / file path lookups). The
existing parameterized run_sql_noOpen('... =?', val) call sites are unchanged.

Lockstep with the DID-python field-name validation (same audit item 6.1-3).

Authored without a local MATLAB runtime; needs MATLAB to validate/run.
Maps the §6.1 finding addressed here (SQL-literal escaping, 6.1-3) to its
commit, notes that isa (6.1-1) and the sqlite indexes (6.1-4) needed no MATLAB
change (MATLAB is the correct reference / already has them; Python caught up),
and records the timestamp-format DECISION (§6.1-2/§7.3-13: datenum vs epoch
seconds in the same column) as a cross-client choice deliberately NOT changed
here, pending joint sign-off. Reiterates author-not-run + the lockstep merge
with audit/did-python-2026-06.
Adversarial review counted 14 escapeSqlLiteral call sites in sqlitedb.m, not 15
(the earlier count of 15 included a docstring-example occurrence that was later
reverted). All vulnerable double-quoted interpolations are still covered.
The bare-named tools/tasks/codecheckToolbox.m sits on the genpath'd
tools/ directory and shadowed matbox.tasks.codecheckToolbox, so the
check-code@v1 action's codecheckToolbox("FoldersToCheck","src") call
resolved to the local zero-arg wrapper and failed with "Too many input
arguments". Packaging it as didtools.codecheckToolbox removes the
shadow while keeping the developer convenience. Mirrors the fix already
made on the V2 branch.
Reverts the package-move approach (which let CI fall through to matbox
with CreateBadge=true and fail in createBadgeSvg: 'Python commands
require a supported version of CPython'). Instead keep the bare-named
wrapper that the check-code@v1 action resolves to, but accept and forward
the new name-value args (FoldersToCheck/src) while forcing
CreateBadge=false. Fixes both the original 'Too many input arguments'
error and the CPython badge error without changing the workflow.
@github-actions

Copy link
Copy Markdown
Contributor

Test Results

101 tests  ±0   101 ✅ ±0   1m 10s ⏱️ -1s
 14 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 2e7a968. ± Comparison against base commit 03b0f7f.

@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 41.62%. Comparing base (03b0f7f) to head (2e7a968).

Files with missing lines Patch % Lines
src/did/+did/+implementations/sqlitedb.m 80.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #148      +/-   ##
==========================================
+ Coverage   41.60%   41.62%   +0.01%     
==========================================
  Files          55       55              
  Lines        3158     3159       +1     
==========================================
+ Hits         1314     1315       +1     
  Misses       1844     1844              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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.

4 participants