Files

20 lines
1.2 KiB
JavaScript
Raw Permalink Normal View History

// Contract G02 requires source-level protection even with verbose logging enabled.
const {test}=require('node:test');
const assert=require('node:assert/strict');
const fs=require('node:fs');
const path=require('node:path');
const root=path.resolve(__dirname,'../components/volc_conv_ai/src');
function sources(dir){return fs.readdirSync(dir,{withFileTypes:true}).flatMap(x=>x.isDirectory()?sources(path.join(dir,x.name)):x.name.endsWith('.c')?[path.join(dir,x.name)]:[]);}
test('vendor SDK does not log credential, transcript, config, or HTTP payload buffers',()=>{
const unsafe=[];
for(const file of sources(root)){
const code=fs.readFileSync(file,'utf8').replace(/^\s*\/\/[^\n]*/gm,'');
for(const match of code.matchAll(/\bLOG[VDEIWF]\s*\(([^;]+)\);/g)){
// Match arguments separately: diagnostic words in a constant message are safe.
const args=match[1].replace(/"(?:\\.|[^"\\])*"/g,'');
if(/(?<!\.)\b(?:secret|params|param_str|post_data|json_str|json|buffer|token|response|data|extencontent|error_reason|message|decoded_payload|output)\b|->p_token\b/.test(args)&&/%(?:\.\*|\d*)s/.test(match[1]))unsafe.push(path.relative(root,file)+': '+match[0]);
}
}
assert.deepEqual(unsafe,[],'private buffers must not be passed to SDK log macros');
});