Spring `application.{properties,yml}` keys (and Shopify Liquid `{% schema %}`
blocks) were storing the config VALUE in the node docstring, and
`codegraph_explore`'s source section re-read the raw `key = value` line off
disk — so a secret committed to a config file (DB password, API key, JDBC URL
with embedded credentials) could be pushed into an agent's context via
explore/node output without the agent ever opening the file.
Config-leaf nodes (`kind: 'constant'` in a config language) now surface the KEY
only, via a shared `isConfigLeafNode` predicate applied at both surfacing
paths: the value is dropped from extraction, `getCode`/`includeCode` returns
the key instead of the file line, and explore excludes config leaves from
source rendering. The predicate can't match real code (real constants are
ts/java/go/…), so `@Value`/`@ConfigurationProperties` resolution and impact are
unaffected. Adds a regression test asserting a planted secret never appears in
`codegraph_explore` / `codegraph_node` output while the keys still resolve.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
80db274e5f
commit
112e278b5c
+6
-1
@@ -26,7 +26,7 @@ import {
|
||||
existsSync,
|
||||
readFileSync,
|
||||
} from 'fs';
|
||||
import { clamp, validatePathWithinRoot, validateProjectPath } from '../utils';
|
||||
import { clamp, validatePathWithinRoot, validateProjectPath, isConfigLeafNode } from '../utils';
|
||||
import { isGeneratedFile } from '../extraction/generated-detection';
|
||||
import { resolve as resolvePath } from 'path';
|
||||
|
||||
@@ -1705,6 +1705,11 @@ export class ToolHandler {
|
||||
for (const node of subgraph.nodes.values()) {
|
||||
// Skip import/export nodes — they add noise without information
|
||||
if (node.kind === 'import' || node.kind === 'export') continue;
|
||||
// SECURITY (#383): never render the on-disk source of a config-leaf
|
||||
// (Spring application.{yml,properties} key) — its line is `key = <secret>`,
|
||||
// so whole-file/cluster rendering here would push secrets into context
|
||||
// unbidden. The key still appears in the flow/symbol listing above.
|
||||
if (isConfigLeafNode(node)) continue;
|
||||
|
||||
const group = fileGroups.get(node.filePath) || { nodes: [], score: 0 };
|
||||
group.nodes.push(node);
|
||||
|
||||
Reference in New Issue
Block a user