20 lines
1.2 KiB
JavaScript
20 lines
1.2 KiB
JavaScript
// 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');
|
||
|
|
});
|